<?php

namespace App\Livewire\Invoices;

use App\Domain\Financial\Services\InvoiceService;
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 CreateInvoiceWizard extends Component
{
    use UsesBranchScope;

    public int $currentStep = 1;
    public int $totalSteps = 5;
    public bool $completed = false;

    // Step 1: Client
    public string $participantSearch = '';
    public ?int $participantId = null;
    public ?string $participantName = null;
    public string $contactName = '';
    public string $contactPhone = '';

    // Step 2: Items (repeatable)
    public array $items = [];

    // Step 3: Discount & Tax
    public string $discountAmount = '0';
    public string $taxAmount = '0';

    // Step 4: Dates
    public string $issueDate = '';
    public string $dueDate = '';
    public string $notes = '';

    public function mount(): void
    {
        $this->authorize('invoices.create');
        $this->issueDate = now()->format('Y-m-d');
        $this->dueDate = now()->addDays(30)->format('Y-m-d');
        $this->addItem();
    }

    public function getStepLabels(): array
    {
        return [
            1 => 'العميل',
            2 => 'البنود',
            3 => 'الخصم والضريبة',
            4 => 'تاريخ الاستحقاق',
            5 => 'مراجعة',
        ];
    }

    public function rulesForStep(): array
    {
        return match ($this->currentStep) {
            1 => [
                'participantId' => 'required|exists:participants,id',
                'contactName' => 'nullable|string|max:255',
                'contactPhone' => 'nullable|string|max:20',
            ],
            2 => [
                'items' => 'required|array|min:1',
                'items.*.description' => 'required|string|max:255',
                'items.*.quantity' => 'required|integer|min:1',
                'items.*.unit_price' => 'required|numeric|min:0.01',
            ],
            3 => [
                'discountAmount' => 'nullable|numeric|min:0',
                'taxAmount' => 'nullable|numeric|min:0',
            ],
            4 => [
                'issueDate' => 'required|date',
                'dueDate' => 'required|date|after_or_equal:issueDate',
                'notes' => 'nullable|string|max:1000',
            ],
            default => [],
        };
    }

    public function messages(): array
    {
        return [
            'participantId.required' => 'يرجى اختيار العميل',
            'participantId.exists' => 'العميل المختار غير موجود',
            'items.required' => 'يجب إضافة بند واحد على الأقل',
            'items.min' => 'يجب إضافة بند واحد على الأقل',
            'items.*.description.required' => 'وصف البند مطلوب',
            'items.*.quantity.required' => 'الكمية مطلوبة',
            'items.*.quantity.min' => 'الكمية يجب أن تكون 1 على الأقل',
            'items.*.unit_price.required' => 'سعر الوحدة مطلوب',
            'items.*.unit_price.min' => 'سعر الوحدة يجب أن يكون أكبر من صفر',
            'issueDate.required' => 'تاريخ الإصدار مطلوب',
            'dueDate.required' => 'تاريخ الاستحقاق مطلوب',
            'dueDate.after_or_equal' => 'تاريخ الاستحقاق يجب أن يكون بعد أو يساوي تاريخ الإصدار',
        ];
    }

    public function addItem(): void
    {
        $this->items[] = [
            'description' => '',
            'quantity' => 1,
            'unit_price' => '',
        ];
    }

    public function removeItem(int $index): void
    {
        if (count($this->items) > 1) {
            unset($this->items[$index]);
            $this->items = array_values($this->items);
        }
    }

    public function selectParticipant(int $id): void
    {
        $participant = Participant::with('person')->find($id);
        if ($participant) {
            $this->participantId = $participant->id;
            $this->participantName = $participant->person?->name_ar ?? $participant->person?->name;
            $this->contactName = $participant->person?->name_ar ?? '';
            $this->contactPhone = $participant->person?->phone ?? '';
        }
    }

    public function getSubtotalProperty(): int
    {
        $subtotal = 0;
        foreach ($this->items as $item) {
            $price = (float) ($item['unit_price'] ?? 0);
            $qty = (int) ($item['quantity'] ?? 0);
            $subtotal += (int) round($price * 100) * $qty;
        }
        return $subtotal;
    }

    public function getTotalProperty(): int
    {
        $subtotal = $this->getSubtotalProperty();
        $discount = (int) round((float) ($this->discountAmount ?? 0) * 100);
        $tax = (int) round((float) ($this->taxAmount ?? 0) * 100);
        return $subtotal - $discount + $tax;
    }

    public function nextStep(): void
    {
        $this->validate($this->rulesForStep(), $this->messages());
        $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(): void
    {
        try {
            $subtotal = $this->getSubtotalProperty();
            $discount = (int) round((float) ($this->discountAmount ?? 0) * 100);
            $tax = (int) round((float) ($this->taxAmount ?? 0) * 100);
            $total = $subtotal - $discount + $tax;

            $data = [
                'billable_type' => \App\Domain\Participant\Models\Participant::class,
                'billable_id' => $this->participantId,
                'contact_name' => $this->contactName ?: $this->participantName,
                'contact_phone' => $this->contactPhone ?: null,
                'subtotal_amount' => $subtotal,
                'discount_amount' => $discount,
                'tax_amount' => $tax,
                'total_amount' => $total,
                'issue_date' => $this->issueDate,
                'due_date' => $this->dueDate,
                'notes' => $this->notes ?: null,
                'currency' => 'EGP',
            ];

            $items = collect($this->items)->map(function ($item) {
                $unitPrice = (int) round((float) $item['unit_price'] * 100);
                $quantity = (int) $item['quantity'];
                return [
                    'description' => $item['description'],
                    'quantity' => $quantity,
                    'unit_price' => $unitPrice,
                    'discount_amount' => 0,
                    'tax_amount' => 0,
                ];
            })->toArray();

            app(InvoiceService::class)->create($data, $items, auth()->user());

            $this->completed = true;
            session()->flash('success', 'تم إنشاء الفاتورة بنجاح');
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function render()
    {
        $searchResults = collect();
        if (strlen($this->participantSearch) >= 2 && !$this->participantId) {
            $branchId = $this->getActiveBranchId();
        $searchResults = Participant::query()
            ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
                ->with('person')
                ->where(function ($q) {
                    $search = $this->participantSearch;
                    $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}%");
                      });
                })
                ->limit(10)
                ->get();
        }

        return view('livewire.invoices.create-invoice-wizard', [
            'searchResults' => $searchResults,
        ]);
    }
}
