<?php

namespace App\Livewire\Dashboard;

use App\Domain\Financial\Enums\InvoiceStatus;
use App\Domain\Financial\Models\Invoice;
use App\Domain\Participant\Models\Participant;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Enums\EnrollmentStatus;
use App\Domain\Training\Enums\RenewalPolicy;
use App\Domain\Training\Models\Enrollment;
use Livewire\Component;

class OverdueRenewalsAlert extends Component
{
    use UsesBranchScope;

    public bool $showList = false;

    public function toggleList(): void
    {
        $this->showList = !$this->showList;
    }

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

        $unpaidInvoices = Invoice::whereIn('status', [InvoiceStatus::Sent, InvoiceStatus::PartiallyPaid, InvoiceStatus::Overdue])
            ->where('due_amount', '>', 0)
            ->where('billable_type', Participant::class)
            ->where('notes', 'like', '%تجديد%')
            ->when($branchId, fn ($q) => $q->whereHasMorph('billable', [Participant::class], fn ($p) => $p->where('branch_id', $branchId)))
            ->with(['billable.person'])
            ->orderBy('due_date')
            ->get();

        $overdueEnrollments = Enrollment::where('status', EnrollmentStatus::Active)
            ->whereNotNull('next_billing_date')
            ->where('next_billing_date', '<=', $today)
            ->whereHas('program', fn ($q) => $q->whereIn('renewal_policy', [
                RenewalPolicy::AutoRenew->value,
                RenewalPolicy::ManualRenew->value,
            ]))
            ->when($branchId, fn ($q) => $q->whereHas('group', fn ($g) => $g->where('branch_id', $branchId)))
            ->with(['participant.person', 'program', 'group.branch'])
            ->get()
            ->filter(function ($enrollment) {
                if (!$enrollment->participant) {
                    return false;
                }
                return !Invoice::where('billable_type', Participant::class)
                    ->where('billable_id', $enrollment->participant_id)
                    ->whereIn('status', [InvoiceStatus::Sent, InvoiceStatus::PartiallyPaid, InvoiceStatus::Overdue, InvoiceStatus::Draft])
                    ->where('due_amount', '>', 0)
                    ->where('notes', 'like', '%' . ($enrollment->program?->name_ar ?? 'تجديد') . '%')
                    ->exists();
            });

        $invoiceCount = $unpaidInvoices->count();
        $enrollmentCount = $overdueEnrollments->count();
        $totalOverdue = $invoiceCount + $enrollmentCount;
        $totalAmount = $unpaidInvoices->sum('due_amount');

        $items = collect();
        if ($this->showList) {
            foreach ($unpaidInvoices as $invoice) {
                $participant = $invoice->billable;
                if (!$participant) {
                    continue;
                }
                $items->push([
                    'participant_name' => $participant->person?->name_ar ?? $invoice->contact_name ?? '-',
                    'participant_phone' => $participant->person?->phone ?? null,
                    'participant_uuid' => $participant->uuid,
                    'amount' => $invoice->due_amount,
                    'program_name' => $this->extractProgramName($invoice->notes),
                    // Carbon 3 signs its diffs — $a->diffInDays($b) is $b − $a.
                    // Asked the other way round, every overdue invoice reported
                    // a negative number of days and the list sorted backwards.
                    'days_overdue' => $invoice->due_date?->isPast() ? (int) $invoice->due_date->diffInDays(now()) : 0,
                    'type' => 'invoice',
                ]);
            }

            foreach ($overdueEnrollments as $enrollment) {
                $items->push([
                    'participant_name' => $enrollment->participant?->person?->name_ar ?? '-',
                    'participant_phone' => $enrollment->participant?->person?->phone ?? null,
                    'participant_uuid' => $enrollment->participant?->uuid,
                    'amount' => null,
                    'program_name' => $enrollment->program?->name_ar ?? '-',
                    'days_overdue' => (int) ($enrollment->next_billing_date?->diffInDays(now()) ?? 0),
                    'type' => 'no_invoice',
                ]);
            }

            $items = $items->sortByDesc('days_overdue')->values();
        }

        return view('livewire.dashboard.overdue-renewals-alert', [
            'items' => $items,
            'totalOverdue' => $totalOverdue,
            'totalAmount' => $totalAmount,
            'invoiceCount' => $invoiceCount,
            'enrollmentCount' => $enrollmentCount,
        ]);
    }

    private function extractProgramName(?string $notes): string
    {
        if (!$notes) {
            return '-';
        }
        if (preg_match('/[—:]\s*(.+)$/', $notes, $m)) {
            return trim($m[1]);
        }
        return $notes;
    }
}
