<?php

namespace App\Filament\Pages\Reports;

use App\Filament\Support\StatusLookup;
use App\Models\Lookups\Status;
use App\Models\Sales\Transaction;
use App\Services\CurrentContext;
use Filament\Actions\Action;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Section;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

/**
 * Ported from ReportController::payments(), including its cheque-overdue rule
 * (a cheque dated in the past whose status is not cleared/settled). Same date
 * window (now the shared date-range preset), same summary figures and CSV
 * columns; rows come from a native Filament table instead of a 500-row array.
 */
class PaymentsReport extends ReportPage
{
    protected static string|\BackedEnum|null $navigationIcon = Heroicon::OutlinedBanknotes;

    protected static ?string $navigationLabel = 'Payment Collections';

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

    protected static ?string $title = 'Payment Collections';

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

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

    public function columns(): array
    {
        return [
            'date' => 'Date',
            'reference' => 'Reference',
            'customer' => 'Customer',
            'method' => 'Method',
            'amount' => 'Amount',
            'status' => 'Status',
            'cheque_number' => 'Cheque #',
            'cheque_date' => 'Cheque Date',
        ];
    }

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

    public function table(Table $table): Table
    {
        return $this->baseTable($table)
            ->columns([
                TextColumn::make('created_at')->label('Date')->date()->sortable(),
                TextColumn::make('transaction_number')->label('Reference')
                    ->state(fn (Transaction $record): string => $record->transaction_number ?? (string) $record->id)
                    ->searchable(query: fn (Builder $query, string $search): Builder => $query
                        ->where('transaction_number', 'like', "%{$search}%"))
                    ->sortable(),
                TextColumn::make('customer.business_name')->label('Customer')->placeholder('—')->searchable(),
                TextColumn::make('paymentMethod.name')->label('Method')->placeholder('—'),
                TextColumn::make('amount')->label('Amount')->money(fn () => app(CurrentContext::class)->currencyCode())->sortable(),
                TextColumn::make('paymentStatus.code')->label('Status')
                    ->badge()
                    ->color(fn (string $state): ?string => StatusLookup::colorOf(Status::CTX_TRANSACTION, $state))
                    ->formatStateUsing(fn (string $state): string => StatusLookup::nameOf(Status::CTX_TRANSACTION, $state)),
                TextColumn::make('cheque_number')->label('Cheque #')->placeholder('—')->searchable(),
                TextColumn::make('cheque_date')->label('Cheque Date')->date()->placeholder('—'),
            ])
            ->recordActions([$this->transactionViewAction()]);
    }

    protected function transactionViewAction(): Action
    {
        return Action::make('view')
            ->label('View')
            ->icon('heroicon-m-eye')
            ->color('gray')
            ->schema([
                Section::make()->columns(4)->schema([
                    TextEntry::make('transaction_number')->label('Reference')
                        ->state(fn (Transaction $record): string => $record->transaction_number ?? (string) $record->id),
                    TextEntry::make('created_at')->label('Date')->dateTime(),
                    TextEntry::make('customer.business_name')->label('Customer')->placeholder('—'),
                    TextEntry::make('paymentMethod.name')->label('Method')->placeholder('—'),
                    TextEntry::make('amount')->label('Amount')
                        ->money(fn (): string => app(CurrentContext::class)->currencyCode()),
                    TextEntry::make('paymentStatus.name')->label('Status')->badge()
                        ->color(fn (Transaction $record): ?string => StatusLookup::colorOf(Status::CTX_TRANSACTION, (string) ($record->paymentStatus?->code ?? ''))),
                    TextEntry::make('taken_on')->label('Taken on')->dateTime()->placeholder('—'),
                    TextEntry::make('reference')->label('Reference note')->placeholder('—'),
                    TextEntry::make('note')->label('Note')->placeholder('—')->columnSpanFull(),
                ]),

                Section::make('Cheque')
                    ->visible(fn (Transaction $record): bool => filled($record->cheque_number))
                    ->columns(4)
                    ->schema([
                        TextEntry::make('cheque_number')->label('Cheque #'),
                        TextEntry::make('cheque_bank')->label('Bank')->placeholder('—'),
                        TextEntry::make('cheque_branch_code')->label('Branch code')->placeholder('—'),
                        TextEntry::make('cheque_date')->label('Cheque date')->date(),
                    ]),
            ]);
    }

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

        return [
            'date' => $t->created_at->toDateString(),
            'reference' => $t->transaction_number ?? $t->id,
            'customer' => $t->customer?->business_name ?? '—',
            'method' => $t->paymentMethod?->name ?? '—',
            'amount' => (float) $t->amount,
            'status' => $t->paymentStatus?->code ?? '',
            'cheque_number' => $t->cheque_number,
            'cheque_date' => $t->cheque_date,
        ];
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    protected function overdueCheques(): array
    {
        return $this->filteredQuery()
            ->get()
            ->filter(fn (Transaction $t): bool => $t->cheque_date
                && now()->isAfter($t->cheque_date)
                && ! in_array($t->paymentStatus?->code ?? '', ['cleared', 'settled']))
            ->all();
    }

    public function summary(): array
    {
        $records = $this->filteredQuery()->get();

        $total = (float) $records->sum('amount');
        $pendingCheques = $records->filter(fn (Transaction $t): bool => $t->cheque_number
            && ! in_array($t->paymentStatus?->code ?? '', ['cleared', 'settled']));
        $overdue = $this->overdueCheques();

        return [
            'Total collected' => 'Rs. '.number_format($total, 2),
            'Pending cheques' => (string) $pendingCheques->count(),
            'Overdue cheques' => (string) count($overdue),
            'Overdue amount' => 'Rs. '.number_format(array_sum(array_map(
                fn (Transaction $t): float => (float) $t->amount,
                $overdue,
            )), 2),
        ];
    }

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

        return [
            'label' => $t->created_at->format('d/m/y').' '.($t->transaction_number ?? $t->id).' — '.($t->customer?->business_name ?? '—'),
            'value' => $this->formatAmount($t->amount),
        ];
    }

    protected function receiptTotals(): array
    {
        return [
            ['label' => 'Total collected', 'value' => $this->formatAmount($this->filteredQuery()->sum('amount'))],
        ];
    }
}
