<?php

namespace App\Livewire\Reports;

use App\Domain\Financial\Models\Invoice;
use App\Domain\Financial\Models\Payment;
use App\Domain\Shared\Traits\UsesBranchScope;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Url;
use Livewire\Component;

#[Layout('layouts.app')]
class FinancialReport extends Component
{
    use UsesBranchScope;

    #[Url]
    public string $period = 'month';

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

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

    public function mount(): void
    {
        $this->authorize('reports.view');

        if (!$this->dateFrom) {
            $this->dateFrom = now()->startOfMonth()->toDateString();
        }
        if (!$this->dateTo) {
            $this->dateTo = now()->toDateString();
        }
    }

    public function updatedPeriod(): void
    {
        match ($this->period) {
            'today' => $this->dateFrom = $this->dateTo = now()->toDateString(),
            'week' => (function () {
                $this->dateFrom = now()->startOfWeek()->toDateString();
                $this->dateTo = now()->toDateString();
            })(),
            'month' => (function () {
                $this->dateFrom = now()->startOfMonth()->toDateString();
                $this->dateTo = now()->toDateString();
            })(),
            'quarter' => (function () {
                $this->dateFrom = now()->startOfQuarter()->toDateString();
                $this->dateTo = now()->toDateString();
            })(),
            'year' => (function () {
                $this->dateFrom = now()->startOfYear()->toDateString();
                $this->dateTo = now()->toDateString();
            })(),
            default => null,
        };
    }

    public function render()
    {
        $branchId = $this->getActiveBranchId();
        $academyId = app()->has('current_academy') ? app('current_academy')?->id : null;

        $payments = Payment::where('direction', 'inbound')->where('status', 'confirmed')
            ->whereBetween('created_at', [$this->dateFrom, $this->dateTo . ' 23:59:59'])
            ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
            ->get();

        $totalRevenue = $payments->sum('amount');
        $paymentsByMethod = $payments->groupBy('method')
            ->map(fn ($group) => $group->sum('amount'));

        // No branch clause here on purpose: Invoice carries BranchScope, so this
        // is already the active branch's invoices. The filter that used to sit
        // here reached the branch through the billable participant, which both
        // followed a transferred player into their new branch and dropped every
        // invoice billed to something other than a participant out of the
        // totals — an under-report, not just a misattribution.
        $invoices = Invoice::whereBetween('created_at', [$this->dateFrom, $this->dateTo . ' 23:59:59'])
            ->get();
        $totalInvoiced = $invoices->sum('total_amount');
        $totalOutstanding = $invoices->whereIn('status', ['sent', 'partially_paid', 'overdue'])->sum('due_amount');
        $overdueCount = $invoices->where('status', 'overdue')->count();

        $dailyRevenue = Payment::where('direction', 'inbound')->where('status', 'confirmed')
            ->whereBetween('created_at', [$this->dateFrom, $this->dateTo . ' 23:59:59'])
            ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
            ->select(DB::raw('DATE(created_at) as date'), DB::raw('SUM(amount) as total'))
            ->groupBy('date')
            ->orderBy('date')
            ->pluck('total', 'date')
            ->toArray();

        // Raw builder: neither the academy scope nor the branch scope reaches it,
        // so both are applied by hand — and on `invoices`, the joined table that
        // actually owns the line. The previous branch clause tested the billable
        // participant's branch, which followed a transferred player and silently
        // excluded every invoice whose billable was not a participant.
        $topPrograms = DB::table('invoice_items')
            ->join('invoices', 'invoices.id', '=', 'invoice_items.invoice_id')
            ->whereNull('invoices.deleted_at')
            ->where('invoices.status', '!=', 'cancelled')
            ->whereBetween('invoices.created_at', [$this->dateFrom, $this->dateTo . ' 23:59:59'])
            ->whereNotNull('invoice_items.itemable_type')
            ->when($academyId, fn ($q) => $q->where('invoices.academy_id', $academyId))
            ->when($branchId, fn ($q) => $q->where('invoices.branch_id', $branchId))
            ->select('invoice_items.description', DB::raw('SUM(invoice_items.total_amount) as revenue'), DB::raw('COUNT(*) as count'))
            ->groupBy('invoice_items.description')
            ->orderByDesc('revenue')
            ->limit(10)
            ->get();

        return view('livewire.reports.financial-report', [
            'totalRevenue' => $totalRevenue,
            'paymentsByMethod' => $paymentsByMethod,
            'totalInvoiced' => $totalInvoiced,
            'totalOutstanding' => $totalOutstanding,
            'overdueCount' => $overdueCount,
            'dailyRevenue' => $dailyRevenue,
            'topPrograms' => $topPrograms,
        ]);
    }
}
