<?php

namespace App\Filament\Pages\Reports;

use App\Models\InvoiceItem;
use App\Models\Location;
use App\Models\Unit;
use Filament\Forms\Form;
use Filament\Pages\Page;
use Filament\Forms\Components\Select;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;


class UnitRecapByLocationReport extends Page
{
    protected static ?string $navigationLabel = 'Rekapitulasi Unit per Lokasi';
    protected static ?string $navigationGroup = 'Laporan';
    protected static ?string $navigationIcon  = 'heroicon-o-table-cells';
    protected static ?int $navigationSort     = 76;

    protected static string $view = 'filament.pages.reports.unit-recap-by-location';

    protected static ?string $slug = 'reports/unit-recap-by-location';

    public ?int $location_id = null;
    public ?int $year = null;

    public array $matrix = [];
    public array $totals = [];
    public array $matrixAccrual = [];
    public array $totalsAccrual = [];


    public function mount(): void
    {
        $this->year = $this->year ?? now()->year;

        $this->location_id = $this->location_id
            ?? Location::query()->where('is_active', true)->orderBy('name')->value('id');

        $this->loadData();
    }

    public function form(Form $form): Form
    {
        return $form->schema([
            Select::make('location_id')
                ->label('Lokasi')
                ->options(
                    Location::query()
                        ->where('is_active', true)
                        ->orderBy('name')
                        ->pluck('name', 'id')
                        ->toArray()
                )
                ->searchable()
                ->required()
                ->live()
                ->afterStateUpdated(fn () => $this->loadData()),

            Select::make('year')
                ->label('Tahun')
                ->options($this->yearOptions())
                ->required()
                ->live()
                ->afterStateUpdated(fn () => $this->loadData()),
        ])->columns(2);
    }

    protected function yearOptions(): array
    {
        $current = now()->year;
        return collect(range($current - 5, $current + 1))
            ->mapWithKeys(fn ($y) => [$y => (string) $y])
            ->toArray();
    }

    public function loadData(): void
    {
        $locationId = $this->location_id;
        $year = (int) $this->year;

        if (!$locationId || !$year) {
            $this->matrix = [];
            $this->totals = [];
            $this->matrixAccrual = [];
            $this->totalsAccrual = [];
            return;
        }

        // 1) daftar unit lokasi tsb
        $units = Unit::query()
            ->where('location_id', $locationId)
            ->orderBy('name')
            ->get(['id', 'name']);

        if ($units->isEmpty()) {
            $this->matrix = [];
            $this->totals = [];
            $this->matrixAccrual = [];
            $this->totalsAccrual = [];
            return;
        }

        $unitIds = $units->pluck('id')->all();
        $monthKeys = range(1, 12);

        /**
         * =========================
         * A) CASH / INVOICE-BASED
         * (seperti yang sudah kamu punya)
         * =========================
         */
        $rows = InvoiceItem::query()
            ->join('invoices', 'invoices.id', '=', 'invoice_items.invoice_id')
            ->whereYear('invoices.period_start', $year)
            ->whereIn('invoice_items.unit_id', $unitIds)
            ->where('invoices.status', '!=', 'void')
            ->groupBy('invoice_items.unit_id', DB::raw('MONTH(invoices.period_start)'))
            ->selectRaw('invoice_items.unit_id as unit_id, MONTH(invoices.period_start) as m, SUM(invoice_items.amount) as total')
            ->get();

        $map = [];
        foreach ($rows as $r) {
            $map[(int) $r->unit_id][(int) $r->m] = (float) $r->total;
        }

        $matrix = [];
        $totals = array_fill(1, 12, 0.0);
        $grandTotal = 0.0;

        foreach ($units as $unit) {
            $rowTotal = 0.0;
            $months = [];

            foreach ($monthKeys as $m) {
                $val = $map[$unit->id][$m] ?? 0.0;
                $months[$m] = $val;

                $rowTotal += $val;
                $totals[$m] += $val;
                $grandTotal += $val;
            }

            $matrix[] = [
                'unit_name' => $unit->name,
                'months'    => $months,
                'total'     => $rowTotal,
            ];
        }

        $this->matrix = $matrix;
        $this->totals = [
            'months' => $totals,
            'grand'  => $grandTotal,
        ];

        /**
         * =========================
         * B) NILAI SEWA (GABUNGAN)
         * - monthly: tampil full di bulan period_start
         * - yearly: dibagi 12 bulan (mulai bulan period_start, total 12 bulan)
         * =========================
         */
        $items = InvoiceItem::query()
            ->join('invoices', 'invoices.id', '=', 'invoice_items.invoice_id')
            ->where('invoices.status', '!=', 'void')
            ->whereIn('invoice_items.unit_id', $unitIds)
            // ambil invoice yang period-nya bersinggungan dengan tahun terpilih
            ->whereDate('invoices.period_start', '<=', "{$year}-12-31")
            ->whereDate('invoices.period_end', '>=', "{$year}-01-01")
            ->selectRaw('invoice_items.unit_id, invoice_items.amount, invoices.period_start, invoices.period_type')
            ->get();

        $accrualMap = []; // [unit_id][month] => total

        foreach ($items as $it) {
            $unitId = (int) $it->unit_id;
            $amount = (float) $it->amount;

            $startMonth = Carbon::parse($it->period_start)->startOfMonth();

            if ($it->period_type === 'monthly') {
                // monthly: taruh full ke bulan period_start
                if ((int) $startMonth->year === $year) {
                    $m = (int) $startMonth->month;
                    $accrualMap[$unitId][$m] = ($accrualMap[$unitId][$m] ?? 0.0) + $amount;
                }
                continue;
            }

            if ($it->period_type === 'yearly') {
                // yearly: selalu 12 bulan, mulai dari bulan period_start (Mei -> Apr tahun depan)
                $perMonth = $amount / 12.0;

                for ($i = 0; $i < 12; $i++) {
                    $month = $startMonth->copy()->addMonths($i);
                    if ((int) $month->year === $year) {
                        $m = (int) $month->month;
                        $accrualMap[$unitId][$m] = ($accrualMap[$unitId][$m] ?? 0.0) + $perMonth;
                    }
                }
                continue;
            }

            // kalau ada tipe lain (misal weekly), skip dulu
        }

        /** bentuk matrix accrual */
        $matrixAcc = [];
        $totAccMonths = array_fill(1, 12, 0.0);
        $grandAcc = 0.0;

        foreach ($units as $unit) {
            $rowTotal = 0.0;
            $months = [];

            foreach ($monthKeys as $m) {
                $val = $accrualMap[$unit->id][$m] ?? 0.0;
                $months[$m] = $val;

                $rowTotal += $val;
                $totAccMonths[$m] += $val;
                $grandAcc += $val;
            }

            $matrixAcc[] = [
                'unit_name' => $unit->name,
                'months'    => $months,
                'total'     => $rowTotal,
            ];
        }

        $this->matrixAccrual = $matrixAcc;
        $this->totalsAccrual = [
            'months' => $totAccMonths,
            'grand'  => $grandAcc,
        ];

}
}
