<?php

namespace App\Livewire\Invoices;

use App\Domain\Financial\Enums\InvoiceStatus;
use App\Domain\Financial\Enums\PaymentMethod;
use App\Domain\Financial\Models\Invoice;
use App\Domain\Financial\Models\Payment;
use App\Domain\Participant\Models\Participant;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

#[Layout('layouts.app')]
#[Title('الفواتير')]
class InvoiceList extends Component
{
    use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;

    protected string $scopePermission = 'invoices.list';

    #[Url]
    public string $search = '';

    #[Url]
    public string $status = '';

    // Payment summary panel
    #[Url]
    public string $summaryFrom = '';

    #[Url]
    public string $summaryTo = '';

    #[Url]
    public string $primaryMethod = 'cash';

    public function mount(): void
    {
        $this->authorize('invoices.list');
        if ($this->summaryFrom === '') {
            $this->summaryFrom = now()->startOfMonth()->format('Y-m-d');
        }
        if ($this->summaryTo === '') {
            $this->summaryTo = now()->endOfMonth()->format('Y-m-d');
        }
    }

    public function setSummaryPreset(string $preset): void
    {
        match ($preset) {
            'today'         => [$this->summaryFrom, $this->summaryTo] = [now()->toDateString(), now()->toDateString()],
            'this_week'     => [$this->summaryFrom, $this->summaryTo] = [now()->startOfWeek()->toDateString(), now()->endOfWeek()->toDateString()],
            'this_month'    => [$this->summaryFrom, $this->summaryTo] = [now()->startOfMonth()->toDateString(), now()->endOfMonth()->toDateString()],
            'last_month'    => [$this->summaryFrom, $this->summaryTo] = [now()->subMonthNoOverflow()->startOfMonth()->toDateString(), now()->subMonthNoOverflow()->endOfMonth()->toDateString()],
            'this_year'     => [$this->summaryFrom, $this->summaryTo] = [now()->startOfYear()->toDateString(), now()->endOfYear()->toDateString()],
            default         => null,
        };
    }

    public function updatedSearch(): void { $this->resetPage(); }
    public function updatedStatus(): void { $this->resetPage(); }

    private function buildSummaryQuery(string $direction = 'inbound'): \Illuminate\Database\Eloquent\Builder
    {
        return Payment::query()
            ->whereBetween('payment_date', [$this->summaryFrom, $this->summaryTo])
            ->where('status', 'confirmed')
            ->where('direction', $direction);
    }

    public function render()
    {
        $branchId = $this->getActiveBranchId();

        $query = Invoice::with(['billable.person', 'payments'])
            ->when($branchId, fn ($q) => $q->whereHasMorph('billable', [Participant::class], fn ($pq) => $pq->where('branch_id', $branchId)))
            ->when($this->search, function ($q) {
                $search = $this->search;
                $q->where(function ($q2) use ($search) {
                    $q2->where('number', 'ilike', "%{$search}%")
                       ->orWhere('contact_name', 'ilike', "%{$search}%");
                });
            })
            ->when($this->status, fn ($q) => $q->where('status', $this->status))
            ->orderBy($this->sortBy, $this->sortDir);

        $this->applyRoleScope($query);

        // Payment breakdown by method for summary panel (inbound - refunds)
        $inboundRaw = $this->buildSummaryQuery('inbound')
            ->selectRaw('method, SUM(amount) as total, COUNT(*) as count')
            ->groupBy('method')
            ->get()
            ->keyBy('method');

        $refundRaw = $this->buildSummaryQuery('outbound')
            ->selectRaw('method, SUM(amount) as total, COUNT(*) as count')
            ->groupBy('method')
            ->get()
            ->keyBy('method');

        $allMethods = PaymentMethod::cases();

        $breakdown = collect($allMethods)->map(function (PaymentMethod $m) use ($inboundRaw, $refundRaw) {
            $inRow = $inboundRaw->get($m->value);
            $refRow = $refundRaw->get($m->value);
            $netTotal = ($inRow?->total ?? 0) - ($refRow?->total ?? 0);
            return [
                'value'  => $m->value,
                'label'  => $m->label(),
                'total'  => $netTotal,
                'count'  => ($inRow?->count ?? 0) - ($refRow?->count ?? 0),
            ];
        });

        $totalRefunds = $refundRaw->sum('total');

        $primaryTotal  = $breakdown->firstWhere('value', $this->primaryMethod)['total'] ?? 0;
        $primaryCount  = $breakdown->firstWhere('value', $this->primaryMethod)['count'] ?? 0;
        $otherTotal    = $breakdown->where('value', '!=', $this->primaryMethod)->sum('total');
        $otherCount    = $breakdown->where('value', '!=', $this->primaryMethod)->sum('count');
        $grandTotal    = $primaryTotal + $otherTotal;

        return view('livewire.invoices.invoice-list', [
            'invoices'       => $query->paginate(20),
            'statusOptions'  => collect(InvoiceStatus::cases())->mapWithKeys(
                fn (InvoiceStatus $s) => [$s->value => $s->label()]
            )->toArray(),
            'methodOptions'  => collect($allMethods)->mapWithKeys(
                fn (PaymentMethod $m) => [$m->value => $m->label()]
            )->toArray(),
            'breakdown'      => $breakdown,
            'primaryTotal'   => $primaryTotal,
            'primaryCount'   => $primaryCount,
            'otherTotal'     => $otherTotal,
            'otherCount'     => $otherCount,
            'grandTotal'     => $grandTotal,
            'totalRefunds'   => $totalRefunds,
        ]);
    }
}
