<?php

namespace App\Filament\Resources;

use App\Filament\Exports\LoyaltyPointTransactionExporter;
use App\Filament\Resources\Concerns\HasModulePermissions;
use App\Filament\Resources\Concerns\HasStandardTableFeatures;
use App\Filament\Resources\LoyaltyTransactionResource\Pages\ListLoyaltyTransactions;
use App\Models\Loyalty\LoyaltyPointTransaction;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Enums\FiltersLayout;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

/**
 * The append-only points ledger behind Loyalty Balances: every earn, redeem,
 * expiry, adjustment and reversal, in order, with the running balance after
 * each entry and the document that caused it. This is the observability half
 * of a well-run loyalty program — auditors and managers can answer "why does
 * this customer have N points" without digging through the database.
 *
 * Read-only by design: rows are only ever written by LoyaltyService, never
 * created, edited or deleted by hand.
 *
 * Shares the isms_loyalty module: `access` gates the list, `export` gates
 * the table export (customer PII — same convention as Loyalty Balances).
 */
class LoyaltyTransactionResource extends Resource
{
    use HasModulePermissions;
    use HasStandardTableFeatures;

    protected static ?string $model = LoyaltyPointTransaction::class;

    protected static string $permissionModuleKey = 'isms_loyalty';

    protected static string $exporter = LoyaltyPointTransactionExporter::class;

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

    protected static string|\UnitEnum|null $navigationGroup = 'Promotions & Loyalty';

    protected static ?string $navigationLabel = 'Points History';

    protected static ?int $navigationSort = 21;

    protected static ?string $slug = 'loyalty-transactions';

    public static function canCreate(): bool
    {
        return false;
    }

    public static function canEdit(Model $record): bool
    {
        return false;
    }

    public static function canDelete(Model $record): bool
    {
        return false;
    }

    public static function canDeleteAny(): bool
    {
        return false;
    }

    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()
            ->with(['customer:id,business_name,phone', 'program:id,name', 'type', 'invoice:id,invoice_number']);
    }

    public static function table(Table $table): Table
    {
        return static::standardTableDefaults($table)
            ->recordUrl(static::standardRecordUrl())
            ->emptyStateHeading('No loyalty transactions yet')
            ->emptyStateDescription('Points earned and spent will appear here.')
            ->columns([
                TextColumn::make('created_at')->label('Date')->dateTime()->sortable(),
                TextColumn::make('customer.business_name')->label('Customer')->searchable()->placeholder('—'),
                TextColumn::make('type.name')->label('Type')->badge()->color(fn ($state, LoyaltyPointTransaction $record): string => (float) $record->points >= 0 ? 'success' : 'danger')->placeholder('—'),
                TextColumn::make('points')
                    ->label('Points')
                    ->sortable()
                    ->formatStateUsing(fn ($state) => (float) $state > 0 ? '+'.rtrim(rtrim(number_format((float) $state, 2, '.', ''), '0'), '.') : rtrim(rtrim(number_format((float) $state, 2, '.', ''), '0'), '.')),
                TextColumn::make('balance_after')->label('Balance after')->sortable(),
                TextColumn::make('expires_at')->label('Expires')->date()->placeholder('—'),
                TextColumn::make('invoice.invoice_number')->label('Invoice')->placeholder('—'),
                TextColumn::make('description')->label('Description')->limit(60)->placeholder('—'),
                IconColumn::make('is_reversed')->boolean()->label('Reversed'),
            ])
            ->defaultSort('created_at', 'desc')
            ->filters([
                Filter::make('customer')
                    ->schema([TextInput::make('value')->label('Customer')])
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $value) => $q->whereHas('customer', fn ($qq) => $qq->where('business_name', 'like', "%{$value}%")),
                    )),
                SelectFilter::make('loyalty_transaction_type_id')
                    ->label('Type')
                    ->relationship('type', 'name'),
                Filter::make('issued_between')
                    ->label('Date range')
                    ->schema([
                        DatePicker::make('from')->label('From'),
                        DatePicker::make('to')->label('To'),
                    ])
                    ->query(fn (Builder $query, array $data): Builder => $query
                        ->when($data['from'] ?? null, fn (Builder $q, $v) => $q->whereDate('created_at', '>=', $v))
                        ->when($data['to'] ?? null, fn (Builder $q, $v) => $q->whereDate('created_at', '<=', $v))),
            ])
            ->filtersLayout(FiltersLayout::AboveContentCollapsible)
            ->filtersFormColumns(2)
            ->headerActions(static::standardExportActions())
            ->toolbarActions(static::standardExportBulkActions());
    }

    public static function getPages(): array
    {
        return [
            'index' => ListLoyaltyTransactions::route('/'),
        ];
    }
}
