<?php

namespace App\Filament\Resources\Clients\Pages;

use App\Filament\Resources\Clients\ClientResource;
use App\Models\Ledger;
use Filament\Resources\Pages\Page;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Filters\Filter;
use Filament\Forms\Components\DatePicker;
use Illuminate\Database\Eloquent\Builder;
use Filament\Resources\Pages\Concerns\InteractsWithRecord;
use pxlrbt\FilamentExcel\Actions\ExportAction as ExcelExportAction;
use pxlrbt\FilamentExcel\Exports\ExcelExport;
use pxlrbt\FilamentExcel\Columns\Column;

class GeneralLedger extends Page implements HasTable
{
    use InteractsWithTable;
    use InteractsWithRecord;

    protected static string $resource = ClientResource::class;

    protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-document-text';

    protected string $view = 'filament.resources.client-resource.pages.general-ledger';

    public function mount(int | string $record): void
    {
        $this->record = $this->resolveRecord($record);
    }

    public function table(Table $table): Table
    {
        return $table
            ->query(
                Ledger::query()
                    ->where('client_id', $this->getRecord()->id)
                    ->with(['account', 'transaction', 'journal'])
            )
            ->columns([
                TextColumn::make('date')
                    ->label('Date')
                    ->state(function (Ledger $record) {
                        return $record->transaction?->happened_on?->format('Y-m-d') 
                            ?? $record->journal?->happened_on?->format('Y-m-d') 
                            ?? $record->created_at->format('Y-m-d');
                    })
                    ->sortable(),
                TextColumn::make('account.account')
                    ->label('Account')
                    ->searchable()
                    ->sortable(),
                TextColumn::make('description')
                    ->limit(50)
                    ->tooltip(function (TextColumn $column): ?string {
                        $state = $column->getState();
                        if (strlen($state) <= $column->getCharacterLimit()) {
                            return null;
                        }
                        return $state;
                    }),
                TextColumn::make('debit_amount')
                    ->label('Debit')
                    ->money('PHP')
                    ->sortable(),
                TextColumn::make('credit_amount')
                    ->label('Credit')
                    ->money('PHP')
                    ->sortable(),
            ])
            ->filters([
                SelectFilter::make('account')
                    ->relationship('account', 'account', fn (Builder $query) => $query->where('client_id', $this->getRecord()->id))
                    ->searchable()
                    ->preload(),
                Filter::make('date_range')
                    ->schema([
                        DatePicker::make('from'),
                        DatePicker::make('to'),
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        return $query
                            ->when(
                                $data['from'],
                                fn (Builder $query, $date): Builder => $query->where(function ($q) use ($date) {
                                    $q->whereHas('transaction', fn ($q) => $q->whereDate('happened_on', '>=', $date))
                                      ->orWhereHas('journal', fn ($q) => $q->whereDate('happened_on', '>=', $date))
                                      ->orWhere(fn($q) => $q->whereDoesntHave('transaction')->whereDoesntHave('journal')->whereDate('created_at', '>=', $date));
                                })
                            )
                            ->when(
                                $data['to'],
                                fn (Builder $query, $date): Builder => $query->where(function ($q) use ($date) {
                                    $q->whereHas('transaction', fn ($q) => $q->whereDate('happened_on', '<=', $date))
                                      ->orWhereHas('journal', fn ($q) => $q->whereDate('happened_on', '<=', $date))
                                      ->orWhere(fn($q) => $q->whereDoesntHave('transaction')->whereDoesntHave('journal')->whereDate('created_at', '<=', $date));
                                })
                            );
                    })
            ])
            ->defaultSort('created_at', 'desc')
            ->groups([
                'account.account',
            ])
            ->headerActions([
                ExcelExportAction::make()
                    ->label('Export General Ledger')
                    ->exports([
                        ExcelExport::make()
                            ->fromTable()
                            ->withFilename(fn () => $this->getRecord()->name . ' - General Ledger - ' . date('Y-m-d'))
                            ->withColumns([
                                Column::make('date')
                                    ->heading('Date')
                                    ->formatStateUsing(fn ($record) => $record->transaction?->happened_on?->format('Y-m-d') 
                                        ?? $record->journal?->happened_on?->format('Y-m-d') 
                                        ?? $record->created_at->format('Y-m-d')),
                                Column::make('reference')
                                    ->heading('Reference')
                                    ->formatStateUsing(fn ($record) => match(true) {
                                        $record->transaction && $record->transaction->transactionable => 
                                            $record->transaction->transactionable->voucher_number 
                                            ?? $record->transaction->transactionable->reference_number 
                                            ?? 'TR-'.$record->transaction->id,
                                        $record->transaction => 'TR-'.$record->transaction->id,
                                        $record->journal => $record->journal->series ?? 'JV-'.$record->journal->id,
                                        default => 'L-'.$record->id,
                                    }),
                                Column::make('account.account')->heading('Account'),
                                Column::make('description')->heading('Description'),
                                Column::make('debit_amount')->heading('Debit'),
                                Column::make('credit_amount')->heading('Credit'),
                            ])
                    ])
            ]);
    }
}
