<?php

namespace App\Filament\Pages\Reports;

use App\Filament\Pages\Reports\Concerns\ProvidesInvoiceViewModal;
use App\Filament\Support\StatusLookup;
use App\Models\Lookups\Status;
use App\Models\Sales\Invoice;
use App\Services\CurrentContext;
use App\Services\VatSettings;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

/**
 * Ported from ReportController::invoices(). Same date window (now the shared
 * date-range preset), branch filter, summary and CSV columns — plus the VAT
 * column appearing only for VAT-registered tenants, and native table rows
 * instead of a 500-row capped array.
 */
class InvoicesReport extends ReportPage
{
    use ProvidesInvoiceViewModal;

    protected static string|\BackedEnum|null $navigationIcon = Heroicon::OutlinedDocumentText;

    protected static ?string $navigationLabel = 'Invoice Report';

    protected static ?string $slug = 'reports/invoices';

    protected static ?string $title = 'Invoice Report';

    public static function moduleKey(): string
    {
        return 'reports_invoices';
    }

    public function csvFilename(): string
    {
        return 'invoices-report.csv';
    }

    public function columns(): array
    {
        return array_filter([
            'date' => 'Date',
            'reference' => 'Invoice #',
            'customer' => 'Customer',
            'subtotal' => 'Subtotal',
            'discount' => 'Discount',
            // Dropped from the table and the CSV export outright, not just
            // hidden — a tenant not registered for VAT should see no trace of
            // it in a report either.
            'vat' => app(VatSettings::class)->enabled() ? 'VAT' : null,
            'total' => 'Total',
            'paid' => 'Paid',
            'balance' => 'Balance',
            'payment_status' => 'Payment Status',
            'order_status' => 'Order Status',
            'channel' => 'Channel',
        ]);
    }

    protected function reportQuery(): Builder
    {
        return Invoice::query()
            ->when($this->branchFilter(), fn ($q, $branchId) => $q->where('branch_id', $branchId))
            ->with(['customer:id,business_name', 'paymentStatus:id,code,name', 'orderStatus:id,code,name'])
            ->orderByDesc('created_at');
    }

    protected function tableFilters(): array
    {
        return [
            ...parent::tableFilters(),
            SelectFilter::make('payment_status')
                ->label('Payment status')
                ->options(fn (): array => StatusLookup::options(Status::CTX_INVOICE_PAYMENT))
                ->query(fn (Builder $query, array $data): Builder => $query->when(
                    $data['value'] ?? null,
                    fn (Builder $q, $code) => $q->whereHas('paymentStatus', fn (Builder $s) => $s->where('code', $code)),
                )),
            SelectFilter::make('order_status')
                ->label('Order status')
                ->options(fn (): array => StatusLookup::options(Status::CTX_INVOICE_ORDER))
                ->query(fn (Builder $query, array $data): Builder => $query->when(
                    $data['value'] ?? null,
                    fn (Builder $q, $code) => $q->whereHas('orderStatus', fn (Builder $s) => $s->where('code', $code)),
                )),
        ];
    }

    public function table(Table $table): Table
    {
        return $this->baseTable($table)
            ->columns([
                TextColumn::make('created_at')->label('Date')->date()->sortable(),
                TextColumn::make('invoice_number')->label('Invoice #')->searchable()->sortable(),
                TextColumn::make('customer.business_name')->label('Customer')->placeholder('Walk-in')->searchable(),
                TextColumn::make('subtotal')->label('Subtotal')->money(fn () => app(CurrentContext::class)->currencyCode())->sortable(),
                TextColumn::make('discount')->label('Discount')->money(fn () => app(CurrentContext::class)->currencyCode())->sortable(),
                TextColumn::make('vat_total')->label('VAT')
                    ->visible(fn (): bool => app(VatSettings::class)->enabled())
                    ->money(fn () => app(CurrentContext::class)->currencyCode())->sortable(),
                TextColumn::make('net_total')->label('Total')->money(fn () => app(CurrentContext::class)->currencyCode())->sortable(),
                TextColumn::make('paid_amount')->label('Paid')->money(fn () => app(CurrentContext::class)->currencyCode())->sortable(),
                TextColumn::make('balance')->label('Balance')->money(fn () => app(CurrentContext::class)->currencyCode())->sortable(),
                TextColumn::make('paymentStatus.code')->label('Payment status')
                    ->badge()
                    ->color(fn (string $state): ?string => StatusLookup::colorOf(Status::CTX_INVOICE_PAYMENT, $state))
                    ->formatStateUsing(fn (string $state): string => StatusLookup::nameOf(Status::CTX_INVOICE_PAYMENT, $state)),
                TextColumn::make('orderStatus.code')->label('Order status')
                    ->badge()
                    ->color(fn (string $state): ?string => StatusLookup::colorOf(Status::CTX_INVOICE_ORDER, $state))
                    ->formatStateUsing(fn (string $state): string => StatusLookup::nameOf(Status::CTX_INVOICE_ORDER, $state)),
                TextColumn::make('channel')->label('Channel')->placeholder('—'),
            ])
            ->recordActions([$this->invoiceViewAction()]);
    }

    protected function exportRow(Model $record): array
    {
        $inv = $record;

        return [
            'date' => $inv->created_at->toDateString(),
            'reference' => $inv->invoice_number,
            'customer' => $inv->customer?->business_name ?? 'Walk-in',
            'subtotal' => (float) $inv->subtotal,
            'discount' => (float) $inv->discount,
            'vat' => (float) $inv->vat_total,
            'total' => (float) $inv->net_total,
            'paid' => (float) $inv->paid_amount,
            'balance' => (float) $inv->balance,
            'payment_status' => $inv->paymentStatus?->code ?? '',
            'order_status' => $inv->orderStatus?->code ?? '',
            'channel' => $inv->channel,
        ];
    }

    public function summary(): array
    {
        $rows = $this->rows();

        return [
            'Total invoiced' => 'Rs. '.number_format(array_sum(array_column($rows, 'total')), 2),
            'Total paid' => 'Rs. '.number_format(array_sum(array_column($rows, 'paid')), 2),
            'Total outstanding' => 'Rs. '.number_format(array_sum(array_column($rows, 'balance')), 2),
            'Total discount' => 'Rs. '.number_format(array_sum(array_column($rows, 'discount')), 2),
            'Invoices' => (string) count($rows),
        ];
    }

    protected function receiptLine(Model $record): array
    {
        $inv = $record;

        return [
            'label' => $inv->created_at->format('d/m/y').' '.$inv->invoice_number.' — '.($inv->customer?->business_name ?? 'Walk-in'),
            'value' => $this->formatAmount($inv->net_total),
        ];
    }

    protected function receiptTotals(): array
    {
        $query = $this->filteredQuery();

        return [
            ['label' => 'Total invoiced', 'value' => $this->formatAmount($query->clone()->sum('net_total'))],
            ['label' => 'Total paid', 'value' => $this->formatAmount($query->clone()->sum('paid_amount'))],
            ['label' => 'Total outstanding', 'value' => $this->formatAmount($query->clone()->sum('balance'))],
            ['label' => 'Invoices', 'value' => (string) $query->clone()->count()],
        ];
    }
}
