<?php

namespace App\Livewire\Financial;

use App\Domain\Financial\Models\Expense;
use App\Domain\Financial\Services\ExpenseService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Traits\UsesBranchScope;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Title;
use Livewire\Component;
use Livewire\WithFileUploads;

#[Layout('layouts.app')]
#[Title('تفاصيل المصروف')]
class ExpenseShow extends Component
{
    use UsesBranchScope, WithFileUploads;

    #[Locked]
    public string $uuid = '';

    public $receipt = null;
    public bool $showCancelModal = false;
    public bool $showRemoveModal = false;
    public string $cancellationReason = '';

    public function mount(string $uuid): void
    {
        $this->authorize('expenses.create');
        $this->uuid = $uuid;

        // Resolve once up front so an out-of-branch or unknown uuid fails on
        // the way in rather than on the way out.
        $this->expense();
    }

    /**
     * Re-read on every request instead of holding the model in component
     * state: the service mutates both the row and its journal, and a stale
     * copy would render a ledger that no longer exists.
     */
    private function expense(): Expense
    {
        $expense = Expense::with([
            'creator', 'canceller', 'attachmentUploader', 'branch',
            'transactions.debitAccount', 'transactions.creditAccount', 'transactions.creator',
        ])->where('uuid', $this->uuid)->firstOrFail();

        $branchId = $this->getActiveBranchId();

        abort_if($branchId && $expense->branch_id && $expense->branch_id !== $branchId, 403);

        return $expense;
    }

    public function rules(): array
    {
        return [
            'receipt' => 'required|file|max:5120|mimes:jpg,jpeg,png,pdf,webp',
        ];
    }

    public function messages(): array
    {
        return [
            'receipt.required' => 'اختر ملف الإيصال أولاً',
            'receipt.max' => 'حجم الملف لا يتجاوز 5 ميجابايت',
            'receipt.mimes' => 'الملف يجب أن يكون صورة (jpg, png, webp) أو PDF',
        ];
    }

    public function uploadReceipt(ExpenseService $service): void
    {
        $this->authorize('expenses.create');
        $this->validate();

        try {
            $service->attachReceipt($this->expense(), [
                'path' => $this->receipt->store('expenses/receipts', 'local'),
                'name' => $this->receipt->getClientOriginalName(),
                'disk' => 'local',
                'mime' => $this->receipt->getMimeType(),
                'size' => $this->receipt->getSize(),
            ], auth()->user());

            $this->receipt = null;
            session()->flash('success', __('تم إرفاق المستند بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function removeReceipt(ExpenseService $service): void
    {
        $this->authorize('expenses.create');

        try {
            $service->removeReceipt($this->expense(), auth()->user());
            session()->flash('success', __('تم حذف المرفق'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }

        $this->showRemoveModal = false;
    }

    public function confirmCancel(ExpenseService $service): void
    {
        $this->authorize('expenses.create');

        $this->validate([
            'cancellationReason' => 'required|min:3|max:500',
        ], [
            'cancellationReason.required' => 'يرجى كتابة سبب الإلغاء',
            'cancellationReason.min' => 'السبب قصير جداً',
        ]);

        try {
            $service->cancelExpense($this->expense(), $this->cancellationReason, auth()->user());
            session()->flash('success', __('تم إلغاء المصروف بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }

        $this->showCancelModal = false;
        $this->cancellationReason = '';
    }

    public function render()
    {
        return view('livewire.financial.expense-show', [
            'expense' => $this->expense(),
        ]);
    }
}
