<?php

namespace App\Filament\Resources;

use App\Enums\Currency;
use App\Enums\PaymentStatus;
use App\Enums\SaleOrigin;
use App\Enums\SaleType;
use App\Enums\UserRole;
use App\Filament\Resources\SaleResource\Pages;
use App\Filament\Resources\SaleResource\RelationManagers;
use App\Models\Account;
use App\Models\Client;
use App\Models\Payment;
use App\Models\Sale;
use App\Models\SystemSetting;
use App\Models\User;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

class SaleResource extends Resource
{
    protected static ?string $model = Sale::class;
    protected static ?string $navigationIcon   = 'heroicon-o-currency-dollar';
    protected static ?string $navigationGroup  = 'Comercial';
    protected static ?string $navigationLabel  = 'Ventas';
    protected static ?string $modelLabel       = 'Venta';
    protected static ?string $pluralModelLabel = 'Ventas';
    protected static ?int    $navigationSort   = 2;

    // ── Permisos ──────────────────────────────────────────────────────────────
    public static function canViewAny(): bool { return true; }
    public static function canCreate(): bool  { return true; }
    public static function canEdit($record): bool { return true; }
    public static function canDelete($record): bool
    {
        return auth()->user()?->isAdmin() || auth()->user()?->isContador();
    }

    public static function form(Form $form): Form
    {
        return $form->schema([
            Forms\Components\Section::make('Datos principales')->schema([
                Forms\Components\Select::make('client_id')
                    ->label('Cliente')
                    ->relationship('client', 'name')
                    ->searchable()
                    ->preload()
                    ->required()
                    ->createOptionForm([
                        Forms\Components\TextInput::make('name')->label('Nombre')->required(),
                        Forms\Components\Select::make('origin')
                            ->label('Origen')
                            ->options(collect(\App\Enums\ClientOrigin::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()]))
                            ->default('manual_internacional'),
                        Forms\Components\Select::make('currency_default')
                            ->label('Moneda')
                            ->options(collect(Currency::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()]))
                            ->default('USD'),
                    ]),

                Forms\Components\Select::make('owner_user_id')
                    ->label('Responsable')
                    ->options(User::pluck('name', 'id'))
                    ->required()
                    ->default(fn () => auth()->id()),

                Forms\Components\Select::make('seller_user_id')
                    ->label('Vendedor')
                    ->options(User::where('role', UserRole::Vendedor->value)->pluck('name', 'id'))
                    ->placeholder('Sin vendedor asignado')
                    ->nullable()
                    ->searchable(),

                Forms\Components\TextInput::make('title')
                    ->label('Título')
                    ->required()
                    ->maxLength(255)
                    ->columnSpan(2),

                Forms\Components\Select::make('origin')
                    ->label('Origen')
                    ->options(collect(SaleOrigin::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()]))
                    ->required()
                    ->default(SaleOrigin::Manual->value)
                    ->live(),

                Forms\Components\Select::make('currency')
                    ->label('Moneda')
                    ->options(collect(Currency::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()]))
                    ->required()
                    ->default(Currency::USD->value),

                Forms\Components\DatePicker::make('sale_date')
                    ->label('Fecha de venta')
                    ->required()
                    ->default(now()),
            ])->columns(2),

            Forms\Components\Section::make('Importe')->schema([
                Forms\Components\Radio::make('sale_type')
                    ->label('Tipo de venta')
                    ->options(collect(SaleType::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()]))
                    ->default(SaleType::Fixed->value)
                    ->live()
                    ->afterStateUpdated(fn (Set $set) => $set('gross_amount', 0)),

                Forms\Components\TextInput::make('fixed_amount')
                    ->label('Monto fijo')
                    ->numeric()
                    ->prefix('$')
                    ->step(0.01)
                    ->visible(fn (Get $get) => $get('sale_type') === SaleType::Fixed->value)
                    ->live(debounce: 500)
                    ->afterStateUpdated(function (Get $get, Set $set) {
                        if ($get('sale_type') === SaleType::Fixed->value) {
                            $set('gross_amount', (float) $get('fixed_amount'));
                        }
                    }),

                Forms\Components\TextInput::make('hourly_rate')
                    ->label('Tarifa/hora')
                    ->numeric()
                    ->prefix('$')
                    ->step(0.01)
                    ->visible(fn (Get $get) => $get('sale_type') === SaleType::Hourly->value)
                    ->live(debounce: 500)
                    ->afterStateUpdated(function (Get $get, Set $set) {
                        $hrs = (float) $get('hours_quantity') ?: 0;
                        $rate = (float) $get('hourly_rate') ?: 0;
                        $set('gross_amount', round($rate * $hrs, 2));
                    }),

                Forms\Components\TextInput::make('hours_quantity')
                    ->label('Horas')
                    ->numeric()
                    ->step(0.25)
                    ->visible(fn (Get $get) => $get('sale_type') === SaleType::Hourly->value)
                    ->live(debounce: 500)
                    ->afterStateUpdated(function (Get $get, Set $set) {
                        $hrs = (float) $get('hours_quantity') ?: 0;
                        $rate = (float) $get('hourly_rate') ?: 0;
                        $set('gross_amount', round($rate * $hrs, 2));
                    }),

                Forms\Components\TextInput::make('gross_amount')
                    ->label('Monto bruto')
                    ->numeric()
                    ->prefix(fn (Get $get) => match($get('currency')) { 'BOB' => 'Bs.', default => '$' })
                    ->step(0.01)
                    ->dehydrated()
                    ->default(0)
                    ->helperText('Se calcula automáticamente, o puedes editarlo directamente.'),

                Forms\Components\TextInput::make('platform_fee')
                    ->label('Fee de plataforma')
                    ->numeric()
                    ->prefix(fn (Get $get) => match($get('currency')) { 'BOB' => 'Bs.', default => '$' })
                    ->step(0.01)
                    ->default(0)
                    ->helperText('Ej: 10% de Upwork. Neto = Bruto − Fee.')
                    ->suffix(fn (Get $get) => ($get('gross_amount') && $get('platform_fee'))
                        ? 'Neto: $' . number_format((float)$get('gross_amount') - (float)$get('platform_fee'), 2)
                        : null),

                Forms\Components\TextInput::make('sales_commission_pct')
                    ->label('Comisión vendedor (%)')
                    ->numeric()
                    ->step(0.01)
                    ->suffix('%')
                    ->placeholder(fn () => SystemSetting::current()->sales_commission_pct . '% (por defecto)')
                    ->helperText('Dejar vacío para usar el % global de configuración.')
                    ->nullable(),
            ])->columns(2),

            Forms\Components\Section::make('Cobro y seguimiento')->schema([
                Forms\Components\DatePicker::make('expected_collect_date')
                    ->label('Fecha esperada de cobro'),

                Forms\Components\TextInput::make('expected_collect_note')
                    ->label('Nota de cobro')
                    ->maxLength(255),

                Forms\Components\DatePicker::make('last_follow_up_date')
                    ->label('Último seguimiento'),

                Forms\Components\Textarea::make('follow_up_note')
                    ->label('Nota de seguimiento')
                    ->rows(2)
                    ->columnSpanFull(),
            ])->columns(2),

            Forms\Components\Section::make('Referencia externa')
                ->schema([
                    Forms\Components\TextInput::make('external_source')
                        ->label('Fuente externa')
                        ->maxLength(100),

                    Forms\Components\TextInput::make('external_id')
                        ->label('ID externo')
                        ->maxLength(255),
                ])
                ->columns(2)
                ->visible(fn (Get $get) => $get('origin') === SaleOrigin::Upwork->value)
                ->collapsed(),

            Forms\Components\Textarea::make('description')
                ->label('Descripción')
                ->rows(3)
                ->columnSpanFull(),
        ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('client.name')
                    ->label('Cliente')
                    ->searchable()
                    ->sortable(),

                Tables\Columns\TextColumn::make('title')
                    ->label('Título')
                    ->searchable()
                    ->limit(40),

                Tables\Columns\TextColumn::make('sale_date')
                    ->label('Fecha')
                    ->date('d/m/Y')
                    ->sortable(),

                Tables\Columns\BadgeColumn::make('currency')
                    ->label('Mon.')
                    ->formatStateUsing(fn ($state) => $state instanceof Currency ? $state->value : $state)
                    ->colors(['success' => 'USD', 'warning' => 'BOB']),

                Tables\Columns\TextColumn::make('gross_amount')
                    ->label('Bruto')
                    ->getStateUsing(fn (Sale $r) => $r->currency->symbol() . number_format((float)$r->gross_amount, 2))
                    ->sortable(),

                Tables\Columns\TextColumn::make('platform_fee')
                    ->label('Fee')
                    ->getStateUsing(fn (Sale $r) => $r->platform_fee > 0
                        ? $r->currency->symbol() . number_format((float)$r->platform_fee, 2)
                        : '—')
                    ->color('warning')
                    ->toggleable(isToggledHiddenByDefault: true),

                Tables\Columns\TextColumn::make('net_expected')
                    ->label('Neto')
                    ->getStateUsing(fn (Sale $r) => $r->currency->symbol() . number_format($r->net_expected, 2))
                    ->sortable(false),

                Tables\Columns\TextColumn::make('collected_amount_cached')
                    ->label('Cobrado')
                    ->getStateUsing(fn (Sale $r) => $r->currency->symbol() . number_format((float)$r->collected_amount_cached, 2))
                    ->sortable(),

                Tables\Columns\TextColumn::make('balance')
                    ->label('Saldo')
                    ->getStateUsing(fn (Sale $record): string => $record->currency->symbol() . number_format($record->balance, 2))
                    ->color(fn (Sale $record) => $record->balance > 0 ? 'danger' : 'success'),

                Tables\Columns\BadgeColumn::make('payment_status')
                    ->label('Estado')
                    ->formatStateUsing(fn ($state) => $state instanceof PaymentStatus ? $state->label() : $state)
                    ->colors([
                        'danger'  => PaymentStatus::Unpaid->value,
                        'warning' => PaymentStatus::Partial->value,
                        'success' => PaymentStatus::Paid->value,
                    ]),

                Tables\Columns\TextColumn::make('expected_collect_date')
                    ->label('F. Cobro')
                    ->date('d/m/Y')
                    ->sortable()
                    ->color(fn (Sale $record) => $record->expected_collect_date && $record->expected_collect_date->isPast() && $record->payment_status !== PaymentStatus::Paid ? 'danger' : null),

                Tables\Columns\TextColumn::make('owner.name')
                    ->label('Responsable')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),

                Tables\Columns\TextColumn::make('seller.name')
                    ->label('Vendedor')
                    ->default('—')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('payment_status')
                    ->label('Estado de pago')
                    ->options(collect(PaymentStatus::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()])),

                Tables\Filters\SelectFilter::make('currency')
                    ->label('Moneda')
                    ->options(collect(Currency::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()])),

                Tables\Filters\SelectFilter::make('origin')
                    ->label('Origen')
                    ->options(collect(SaleOrigin::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()])),

                Tables\Filters\SelectFilter::make('client_id')
                    ->label('Cliente')
                    ->relationship('client', 'name')
                    ->searchable()
                    ->preload(),

                Tables\Filters\Filter::make('expected_collect_this_week')
                    ->label('Cobro esta semana')
                    ->query(fn (Builder $q) => $q->whereBetween('expected_collect_date', [now(), now()->addDays(7)])),

                Tables\Filters\Filter::make('overdue')
                    ->label('CxC vencidas')
                    ->query(fn (Builder $q) => $q->where('expected_collect_date', '<', now())
                        ->where('payment_status', '!=', PaymentStatus::Paid->value)),
            ])
            ->actions([
                Tables\Actions\Action::make('register_payment')
                    ->label('Registrar pago')
                    ->icon('heroicon-o-banknotes')
                    ->color('success')
                    ->visible(fn (Sale $record) => $record->payment_status !== PaymentStatus::Paid)
                    ->fillForm(fn (Sale $record): array => [
                        'amount'       => max(0, round($record->balance, 2)),
                        'currency'     => $record->currency->value,
                        'payment_date' => now()->toDateString(),
                        'account_id'   => Account::whereRaw('LOWER(name) LIKE ?', [
                            $record->currency === Currency::USD ? '%payoneer%' : '%nuna%'
                        ])->first()?->id ?? Account::first()?->id,
                        'note' => '',
                    ])
                    ->form(fn (Sale $record) => [
                        Forms\Components\Placeholder::make('sale_info')
                            ->label('Venta')
                            ->content("{$record->client?->name} — {$record->title}"),

                        Forms\Components\Placeholder::make('balance_info')
                            ->label('Saldo pendiente')
                            ->content($record->currency->symbol() . number_format($record->balance, 2)
                                . ($record->balance < $record->net_expected
                                    ? '  (parcial previo: ' . $record->currency->symbol() . number_format((float)$record->collected_amount_cached, 2) . ')'
                                    : '')),

                        Forms\Components\Grid::make(2)->schema([
                            Forms\Components\TextInput::make('amount')
                                ->label('Monto cobrado')
                                ->numeric()
                                ->required()
                                ->step(0.01)
                                ->minValue(0.01)
                                ->prefix(fn (Get $get) => match($get('currency')) { 'BOB' => 'Bs.', default => '$' }),

                            Forms\Components\Select::make('currency')
                                ->label('Moneda')
                                ->options(collect(Currency::cases())->mapWithKeys(fn ($e) => [$e->value => $e->label()]))
                                ->required(),

                            Forms\Components\DatePicker::make('payment_date')
                                ->label('Fecha de pago')
                                ->required()
                                ->default(now()),

                            Forms\Components\Select::make('account_id')
                                ->label('Cuenta destino')
                                ->options(Account::pluck('name', 'id'))
                                ->required()
                                ->searchable(),
                        ]),

                        Forms\Components\TextInput::make('note')
                            ->label('Nota (opcional)')
                            ->maxLength(255),
                    ])
                    ->action(function (Sale $record, array $data): void {
                        Payment::create([
                            'sale_id'            => $record->id,
                            'account_id'         => $data['account_id'],
                            'created_by_user_id' => auth()->id(),
                            'payment_date'       => $data['payment_date'],
                            'amount'             => $data['amount'],
                            'currency'           => Currency::from($data['currency']),
                            'fee_amount'         => 0,
                            'net_amount'         => $data['amount'],
                            'note'               => $data['note'] ?? '',
                        ]);
                        // PaymentObserver recalcula el saldo automáticamente
                        Notification::make()
                            ->title('Pago registrado correctamente')
                            ->body("{$record->client?->name} — {$record->currency->symbol()}{$data['amount']}")
                            ->success()
                            ->send();
                    })
                    ->modalHeading(fn (Sale $record) => "Registrar pago — {$record->client?->name}")
                    ->modalSubmitActionLabel('Confirmar pago')
                    ->modalWidth('lg'),

                Tables\Actions\EditAction::make(),
                Tables\Actions\ViewAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                ]),
            ])
            ->defaultSort('sale_date', 'desc');
    }

    public static function getRelations(): array
    {
        return [
            RelationManagers\PaymentsRelationManager::class,
        ];
    }

    public static function getPages(): array
    {
        return [
            'index'  => Pages\ListSales::route('/'),
            'create' => Pages\CreateSale::route('/create'),
            'edit'   => Pages\EditSale::route('/{record}/edit'),
            'view'   => Pages\ViewSale::route('/{record}'),
        ];
    }
}
