<?php

namespace App\Filament\Resources;

use App\Filament\Exports\VoucherExporter;
use App\Filament\Resources\Concerns\AssertsBranchAccess;
use App\Filament\Resources\Concerns\HasModulePermissions;
use App\Filament\Resources\Concerns\HasStandardTableFeatures;
use App\Filament\Resources\VoucherResource\Pages\CreateVoucher;
use App\Filament\Resources\VoucherResource\Pages\ListVouchers;
use App\Filament\Support\Chip;
use App\Filament\Support\Perm;
use App\Filament\Support\RelationSelect;
use App\Filament\Support\StatusLookup;
use App\Models\Lookups\DiscountType;
use App\Models\Lookups\Status;
use App\Models\Lookups\VoucherType;
use App\Models\Vouchers\Voucher;
use App\Services\AuditLog;
use App\Services\CurrentContext;
use Filament\Actions\Action;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Schema;
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;

/**
 * Ported from App\Http\Controllers\Isms\VoucherController + VoucherService
 * (docs/migration-plan.md Phase 7).
 *
 * The module's catalog actions are access/create/void only — there is no
 * update or delete route in the source (a voucher is voided, never edited or
 * removed), so neither surface is invented here.
 *
 * Creation goes through VoucherService::generate(), which owns code generation
 * and the initial status; the source then overwrites the generated code when
 * the operator supplied their own, and that two-step is reproduced exactly.
 */
class VoucherResource extends Resource
{
    use AssertsBranchAccess;
    use HasModulePermissions;
    use HasStandardTableFeatures;

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

    protected static string $permissionModuleKey = 'isms_vouchers';

    protected static string $exporter = VoucherExporter::class;

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

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

    protected static ?int $navigationSort = 0;

    protected static ?string $recordTitleAttribute = 'code';

    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 form(Schema $schema): Schema
    {
        return $schema->components([
            Section::make()->schema([
                TextInput::make('code')
                    ->maxLength(50)
                    ->unique('vouchers', 'code')
                    ->helperText('Leave blank to auto-generate.'),
                TextInput::make('name')->required()->maxLength(150),
                RelationSelect::standalone(
                    name: 'voucher_type_id',
                    modelClass: VoucherType::class,
                    titleAttribute: 'name',
                )->label('Voucher type')->required()->live(),
                RelationSelect::standalone(
                    name: 'discount_type_id',
                    modelClass: DiscountType::class,
                    titleAttribute: 'name',
                )->label('Discount type'),
                TextInput::make('discount_value')->numeric()->minValue(0)->default(0),
                // Only balance-based voucher types carry an opening balance —
                // the source nulls it out for every other type.
                TextInput::make('initial_balance')
                    ->numeric()->minValue(0)
                    ->prefix('Rs.')
                    ->visible(fn (Get $get): bool => static::isBalanceBased($get('voucher_type_id'))),
                TextInput::make('minimum_purchase')->numeric()->minValue(0)->default(0)->prefix('Rs.'),
                TextInput::make('maximum_discount')->numeric()->minValue(0)->prefix('Rs.'),
                TextInput::make('usage_limit')->numeric()->integer()->minValue(1),
                Toggle::make('is_partial_redemption')->default(false),
                Toggle::make('is_stackable')->default(false),
                // Manual kill switch: a deactivated voucher stops validating
                // immediately (VoucherService::validate()), independently of
                // its lifecycle status — useful to halt a code without voiding
                // its redemption history.
                Toggle::make('is_active')->default(true),
            ])->columns(3),

            Section::make('Restrictions')->schema([
                RelationSelect::make(
                    name: 'customer_id',
                    relationship: 'customer',
                    titleAttribute: 'business_name',
                    modifyQueryUsing: fn ($query) => $query->where('is_active', true),
                )->label('Customer (optional)'),
                RelationSelect::make(
                    name: 'branch_id',
                    relationship: 'branch',
                    titleAttribute: 'name',
                    modifyQueryUsing: fn ($query) => $query->where('is_active', true),
                )->label('Branch (optional)'),
                DatePicker::make('valid_from'),
                DatePicker::make('valid_until')
                    ->afterOrEqual('valid_from'),
                Textarea::make('notes')->maxLength(1000)->columnSpanFull(),
            ])->columns(3),
        ]);
    }

    public static function isBalanceBased(mixed $voucherTypeId): bool
    {
        return $voucherTypeId
            ? (bool) VoucherType::find($voucherTypeId)?->is_balance_based
            : false;
    }

    public static function table(Table $table): Table
    {
        return static::standardTableDefaults($table)
            ->recordUrl(static::standardRecordUrl())
            ->emptyStateHeading('No vouchers yet')
            ->emptyStateDescription('Vouchers issued to customers will appear here.')
            ->columns([
                Chip::documentNumber('code', 'Code')->searchable()->sortable(),
                TextColumn::make('name')->searchable(),
                TextColumn::make('type.name')->label('Type')->placeholder('—'),
                TextColumn::make('discountType.name')->label('Discount')->placeholder('—'),
                TextColumn::make('discount_value'),
                TextColumn::make('remaining_balance')->money(fn () => app(CurrentContext::class)->currencyCode())->placeholder('—'),
                TextColumn::make('used_count')->label('Used'),
                TextColumn::make('usage_limit')->label('Limit')->placeholder('∞'),
                TextColumn::make('status.name')
                    ->label('Status')
                    ->badge()
                    ->color(fn (Voucher $record): string => StatusLookup::colorOf(Status::CTX_VOUCHER, $record->status?->code ?? '')),
                TextColumn::make('customer.business_name')->label('Customer')->placeholder('Any')->toggleable(),
                IconColumn::make('is_stackable')->boolean()->toggleable(),
                IconColumn::make('is_active')->boolean()->label('Active')->toggleable(),
                TextColumn::make('valid_until')->date()->placeholder('—'),
                TextColumn::make('created_at')->dateTime()->sortable()->toggleable(isToggledHiddenByDefault: true),
            ])
            ->defaultSort('created_at', 'desc')
            ->filters([
                SelectFilter::make('status')
                    ->options(fn (): array => StatusLookup::options(Status::CTX_VOUCHER))
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $code) => $q->whereHas('status', fn ($qq) => $qq->where('code', $code)),
                    )),
                SelectFilter::make('voucher_type_id')->relationship('type', 'name')->label('Type'),
                Filter::make('code')
                    ->schema([TextInput::make('value')->label('Code')])
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $value) => $q->where('code', 'like', "%{$value}%"),
                    )),
            ])
            ->filtersLayout(FiltersLayout::AboveContentCollapsible)
            ->filtersFormColumns(2)
            ->headerActions(static::standardExportActions())
            ->toolbarActions(static::standardExportBulkActions())
            ->recordActions([
                Action::make('void')
                    ->color('danger')
                    ->visible(fn (): bool => Perm::can('isms_vouchers', 'void'))
                    ->requiresConfirmation()
                    ->schema([
                        Textarea::make('reason')->maxLength(500),
                    ])
                    ->action(function (Voucher $record, array $data): void {
                        $record->update(['status_id' => Status::idOf(Status::CTX_VOUCHER, Status::VOUCHER_VOID)]);
                        AuditLog::record('voucher.voided', $record, [
                            'code' => $record->code,
                            'reason' => $data['reason'] ?? null,
                        ]);
                        Notification::make()->title('Voucher voided.')->success()->send();
                    }),
                // Toggle the manual kill switch — deactivating stops the code
                // from validating while keeping its redemption history intact.
                Action::make('deactivate')
                    ->color('warning')
                    ->visible(fn (Voucher $record): bool => $record->is_active && Perm::can('isms_vouchers', 'toggle_active'))
                    ->requiresConfirmation()
                    ->action(function (Voucher $record): void {
                        $record->update(['is_active' => false]);
                        AuditLog::record('voucher.deactivated', $record, ['code' => $record->code]);
                        Notification::make()->title('Voucher deactivated.')->success()->send();
                    }),
                Action::make('activate')
                    ->color('success')
                    ->visible(fn (Voucher $record): bool => ! $record->is_active && Perm::can('isms_vouchers', 'toggle_active'))
                    ->requiresConfirmation()
                    ->action(function (Voucher $record): void {
                        $record->update(['is_active' => true]);
                        AuditLog::record('voucher.activated', $record, ['code' => $record->code]);
                        Notification::make()->title('Voucher activated.')->success()->send();
                    }),
            ]);
    }

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