<?php

namespace App\Livewire\Receptionist;

use App\Domain\Financial\Enums\InvoiceStatus;
use App\Domain\Financial\Models\Invoice;
use App\Domain\Financial\Services\PaymentService;
use App\Domain\Participant\Models\Participant;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Traits\UsesBranchScope;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('تحصيل مدفوعات')]
class CollectPaymentWizard extends Component
{
    use UsesBranchScope;

    public ?int $branchId = null;

    public int $currentStep = 1;
    public int $totalSteps = 5;

    // Step 1: Search
    public string $search = '';
    public ?int $selected_participant_id = null;
    public ?string $selected_participant_name = null;

    // Step 2: Invoice selection
    public ?int $selected_invoice_id = null;

    // Step 3: Payment details
    public string $payment_amount_display = '';
    public string $payment_method = 'cash';
    public string $payment_notes = '';

    // Result
    public bool $completed = false;
    public ?string $receipt_number = null;
    public ?string $last_payment_uuid = null;
    public int $paid_amount = 0;
    public ?string $participant_uuid = null;
    public ?string $invoice_uuid = null;

    public function mount(): void
    {
        $this->authorize('invoices.create');
        $this->branchId = $this->getActiveBranchIdOrFail();
    }

    public function rules(): array
    {
        return match ($this->currentStep) {
            1 => [
                'selected_participant_id' => 'required|exists:participants,id',
            ],
            2 => [
                'selected_invoice_id' => 'required|exists:invoices,id',
            ],
            3 => [
                'payment_amount_display' => 'required|numeric|min:0.01',
                'payment_method' => 'required|in:cash,card,wallet',
                'payment_notes' => 'nullable|string|max:500',
            ],
            default => [],
        };
    }

    public function messages(): array
    {
        return [
            'selected_participant_id.required' => 'يرجى اختيار المشترك',
            'selected_participant_id.exists' => 'المشترك المختار غير موجود',
            'selected_invoice_id.required' => 'يرجى اختيار الفاتورة',
            'selected_invoice_id.exists' => 'الفاتورة المختارة غير موجودة',
            'payment_amount_display.required' => 'المبلغ مطلوب',
            'payment_amount_display.numeric' => 'المبلغ يجب أن يكون رقمًا',
            'payment_amount_display.min' => 'المبلغ يجب أن يكون أكبر من صفر',
            'payment_method.required' => 'يرجى اختيار طريقة الدفع',
            'payment_method.in' => 'طريقة الدفع غير صالحة',
        ];
    }

    public function selectParticipant(int $id, string $name): void
    {
        $this->selected_participant_id = $id;
        $this->selected_participant_name = $name;
    }

    public function selectInvoice(int $id): void
    {
        $this->selected_invoice_id = $id;

        // Pre-fill the full balance due
        $invoice = Invoice::find($id);
        if ($invoice) {
            $this->payment_amount_display = number_format($invoice->due_amount / 100, 2, '.', '');
        }
    }

    public function payFullAmount(): void
    {
        $invoice = Invoice::find($this->selected_invoice_id);
        if ($invoice) {
            $this->payment_amount_display = number_format($invoice->due_amount / 100, 2, '.', '');
        }
    }

    public function nextStep(): void
    {
        $this->validate();

        // Additional validation for step 3: amount cannot exceed balance
        if ($this->currentStep === 3) {
            $invoice = Invoice::find($this->selected_invoice_id);
            $amountPiasters = (int) round((float) $this->payment_amount_display * 100);

            if ($invoice && $amountPiasters > $invoice->due_amount) {
                $this->addError('payment_amount_display', 'المبلغ أكبر من الرصيد المستحق');
                return;
            }
        }

        $this->currentStep = min($this->currentStep + 1, $this->totalSteps);
    }

    public function previousStep(): void
    {
        $this->currentStep = max($this->currentStep - 1, 1);
    }

    public function goToStep(int $step): void
    {
        if ($step < $this->currentStep) {
            $this->currentStep = $step;
        }
    }

    public function confirm(PaymentService $service): void
    {
        try {
            $amountPiasters = (int) round((float) $this->payment_amount_display * 100);

            // PaymentService::recordPayment() handles:
            // - Creating payment record
            // - Double-entry transactions (debit cash/card, credit AR)
            // - Updating invoice.paid_amount and due_amount
            // - Transitioning invoice status if fully paid
            // - Updating cash session if cash payment

            $payment = $service->recordPayment([
                'invoice_id' => $this->selected_invoice_id,
                'branch_id' => $this->branchId,
                'amount' => $amountPiasters,
                'method' => $this->payment_method,
                'direction' => 'inbound',
                'currency' => 'EGP',
                'payment_date' => now()->toDateString(),
                'notes' => $this->payment_notes ?: null,
            ], auth()->user());

            $this->completed = true;
            $this->receipt_number = $payment->reference ?? null;
            $this->last_payment_uuid = $payment->uuid;
            $this->paid_amount = $amountPiasters;
            $this->currentStep = 5;

            // Store UUIDs for navigation links
            $participant = \App\Domain\Participant\Models\Participant::find($this->selected_participant_id);
            $this->participant_uuid = $participant?->uuid;
            $invoice = \App\Domain\Financial\Models\Invoice::find($this->selected_invoice_id);
            $this->invoice_uuid = $invoice?->uuid;

            session()->flash('success', __('تم تسجيل الدفع بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function render()
    {
        $searchResults = collect();
        if (strlen($this->search) >= 2) {
            $searchResults = Participant::query()
                ->with('person')
                ->where('branch_id', $this->branchId)
                ->where(function ($q) {
                    $search = $this->search;
                    $q->where('participant_number', 'ilike', "%{$search}%")
                      ->orWhereHas('person', function ($pq) use ($search) {
                          $pq->where('name_ar', 'ilike', "%{$search}%")
                             ->orWhere('name', 'ilike', "%{$search}%")
                             ->orWhere('phone', 'like', "%{$search}%")
                             ->orWhere('national_id', 'like', "%{$search}%");
                      });
                })
                ->limit(10)
                ->get();
        }

        // Outstanding invoices for selected participant
        $invoices = collect();
        if ($this->selected_participant_id) {
            $invoices = Invoice::where('billable_type', \App\Domain\Participant\Models\Participant::class)
                ->where('billable_id', $this->selected_participant_id)
                ->whereIn('status', [
                    InvoiceStatus::Sent,
                    InvoiceStatus::PartiallyPaid,
                    InvoiceStatus::Overdue,
                ])
                ->where('due_amount', '>', 0)
                ->orderByDesc('due_date')
                ->get();
        }

        $selectedInvoice = $this->selected_invoice_id
            ? Invoice::find($this->selected_invoice_id)
            : null;

        return view('livewire.receptionist.collect-payment-wizard', [
            'searchResults' => $searchResults,
            'invoices' => $invoices,
            'selectedInvoice' => $selectedInvoice,
        ]);
    }
}
