<?php

namespace App\Filament\Resources\Credits\Schemas;

use App\Models\Client;
use App\Models\Company;
use App\Models\CompanyFinancialSettings;
use App\Models\User;
use App\Support\Concerns\CalculatesCreditSummary;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get as GetSchema;
use Filament\Schemas\Schema;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Number;

class CreditForm
{
    use CalculatesCreditSummary;

    public static function configure(Schema $schema): Schema
    {
        $livewire = $schema->getLivewire();
        $credit = $livewire->record ?? null;
        $hasPayments = $credit?->hasPayments() ?? false;
        $isClosed = $credit?->isClosed() ?? false;
        $user = Auth::user();
        $isSuperAdmin = $user->hasRole('super_admin');
        $currentCompany = $isSuperAdmin ? null : $user->company_id;

        // Límites por empresa (misma fuente que la PWA StoreCreditRequest):
        // CompanyFinancialSettings. Antes el formulario usaba topes hardcodeados
        // (monto min 1 sin max, tasa max 100, cuotas max 365), permitiendo a un
        // admin emitir créditos fuera de la política financiera de su empresa.
        // Para super_admin (cross-company) se usan fallbacks amplios.
        $settings = $currentCompany ? CompanyFinancialSettings::forCompany($currentCompany) : null;
        $minAmount = (float) ($settings->min_credit_amount ?? 1);
        $maxAmount = (float) ($settings->max_credit_amount ?? 50_000_000);
        $minRate = (float) ($settings->min_interest_rate ?? 0);
        $maxRate = (float) ($settings->max_interest_rate ?? 100);
        $minInstallments = (int) ($settings->min_installments ?? 1);
        $maxInstallments = (int) ($settings->max_installments ?? 365);

        $periodicityLabels = [
            'daily' => 'Diaria',
            'weekly' => 'Semanal',
            'biweekly' => 'Quincenal',
            'monthly' => 'Mensual',
        ];
        $allowedPeriodicities = ! empty($settings->allowed_periodicities)
            ? $settings->allowed_periodicities
            : array_keys($periodicityLabels);
        $periodicityOptions = array_intersect_key($periodicityLabels, array_flip($allowedPeriodicities));

        return $schema
            ->components([
                /*=====================================================
                | SECCIÓN 1: DATOS BÁSICOS DEL CRÉDITO
                =====================================================*/
                Section::make('Datos del Préstamo')
                    ->description('Defina el cliente, monto, tasa y plazo del crédito.')
                    ->columns(2)
                    ->columnSpanFull()
                    ->schema([

                        // COMPANY (multi-tenant)
                        ! $isSuperAdmin
                            ? Hidden::make('company_id')
                                ->default($currentCompany)
                            : null,

                        Hidden::make('created_by_user_id')
                            ->default(fn () => Auth::id()),

                        Select::make('company_id')
                            ->label('Compañía')
                            ->relationship('company', 'name')
                            ->searchable()
                            ->preload()
                            ->required()
                            ->hidden(! $isSuperAdmin)
                            ->default($currentCompany)
                            ->disabled(fn () => $isClosed || $hasPayments),

                        // CLIENTE
                        Select::make('client_id')
                            ->label('Cliente')
                            ->relationship(
                                name: 'client',
                                titleAttribute: 'name',
                                modifyQueryUsing: function (
                                    Builder $query,
                                    GetSchema $get,
                                    $livewire
                                ) use ($currentCompany, $isSuperAdmin) {

                                    $preselectedClient = $livewire->selectedClient ?? null;

                                    if ($preselectedClient) {
                                        return $query->where('id', $preselectedClient->id);
                                    }

                                    $companyId = $get('company_id') ?? $currentCompany;

                                    return $query
                                        ->where('is_active', true)
                                        ->when(
                                            ! $isSuperAdmin && $companyId,
                                            fn ($q) => $q->where('company_id', $companyId)
                                        )
                                        ->when(
                                            $isSuperAdmin && $companyId,
                                            fn ($q) => $q->where('company_id', $companyId)
                                        );
                                }
                            )
                            ->getOptionLabelFromRecordUsing(
                                fn (Client $record) => "{$record->name} ({$record->identification})"
                            )
                            ->searchable()
                            ->preload()
                            ->required()
                            ->disabled(fn ($livewire) => isset($livewire->selectedClient)
                                || ($livewire->record && $livewire->record->hasPayments())
                                || ($livewire->record && $livewire->record->isClosed())
                            )
                            ->dehydrated()
                            ->default(
                                fn ($livewire) => $livewire->selectedClient->id ?? null
                            ),

                        // CAMPOS FINANCIEROS
                        TextInput::make('amount')
                            ->label('Monto Principal (COP)')
                            ->numeric()
                            ->inputMode('decimal')
                            ->minValue($minAmount)
                            ->maxValue($maxAmount)
                            ->required()
                            ->live(debounce: 400)
                            ->disabled(fn () => $isClosed || $hasPayments),

                        TextInput::make('interest_rate')
                            ->label('Tasa de Interés (%)')
                            ->numeric()
                            ->inputMode('decimal')
                            ->minValue($minRate)
                            ->maxValue($maxRate)
                            ->suffix('%')
                            ->required()
                            ->live(debounce: 400)
                            ->disabled(fn () => $isClosed || $hasPayments),

                        TextInput::make('installments_count')
                            ->label('No. de Cuotas')
                            ->numeric()
                            ->integer()
                            ->minValue($minInstallments)
                            ->maxValue($maxInstallments)
                            ->required()
                            ->live(debounce: 400)
                            ->disabled(fn () => $isClosed || $hasPayments),

                        Select::make('periodicity')
                            ->label('Periodicidad')
                            ->options($periodicityOptions)
                            ->required()
                            ->live()
                            ->disabled(fn () => $isClosed || $hasPayments),

                        DatePicker::make('start_date')
                            ->label('Fecha de Desembolso')
                            ->default(now())
                            ->required()
                            ->live()
                            ->disabled(fn () => $isClosed || $hasPayments),
                    ]),

                /*=====================================================
                | SECCIÓN 2: CONFIGURACIÓN DE COBRO
                =====================================================*/
                Section::make('Configuración de Cobro')
                    ->description('Ajuste la fecha de la primera cuota, cobrador y días de cobro.')
                    ->columns(2)
                    ->columnSpanFull()
                    ->collapsible()
                    ->collapsed()
                    ->schema([

                        // COBRADOR
                        Select::make('collector_user_id')
                            ->label('Cobrador Asignado')
                            ->options(function (GetSchema $get) use ($currentCompany) {
                                $companyId = $get('company_id') ?? $currentCompany;
                                if (! $companyId) {
                                    return [];
                                }

                                return User::query()
                                    ->where('company_id', $companyId)
                                    ->role(['collector', 'supervisor'])
                                    ->pluck('name', 'id');
                            })
                            ->default(function (GetSchema $get) use ($currentCompany) {
                                $companyId = $get('company_id') ?? $currentCompany;
                                if (! $companyId) {
                                    return null;
                                }

                                $collectorIds = User::query()
                                    ->where('company_id', $companyId)
                                    ->role(['collector', 'supervisor'])
                                    ->limit(2)
                                    ->pluck('id');

                                return $collectorIds->count() === 1
                                    ? $collectorIds->first()
                                    : null;
                            })
                            ->searchable()
                            ->preload()
                            ->live()
                            ->nullable()
                            ->disabled(fn () => $isClosed || $hasPayments),

                        // DÍA(S) DE COBRO
                        Select::make('due_day_1')
                            ->label(fn (GetSchema $get) => match ($get('periodicity')) {
                                'weekly' => 'Día de la Semana',
                                'biweekly',
                                'monthly' => 'Día del Mes (1)',
                                default => 'Día de Cobro',
                            })
                            ->options(fn (GetSchema $get) => match ($get('periodicity')) {
                                'weekly' => [
                                    1 => 'Lunes', 2 => 'Martes', 3 => 'Miércoles', 4 => 'Jueves',
                                    5 => 'Viernes', 6 => 'Sábado', 7 => 'Domingo',
                                ],
                                'biweekly' => array_combine(range(1, 15), range(1, 15)),
                                'monthly' => array_combine(range(1, 31), range(1, 31)),
                                default => [],
                            })
                            ->required(fn (GetSchema $get) => in_array($get('periodicity'), ['weekly', 'biweekly', 'monthly'], true)
                            )
                            ->visible(fn (GetSchema $get) => in_array($get('periodicity'), ['weekly', 'biweekly', 'monthly'], true)
                            )
                            ->live()
                            ->helperText(fn (GetSchema $get) => match ($get('periodicity')) {
                                'weekly' => 'Seleccione el día de la semana en que se cobra.',
                                'biweekly' => 'Día del mes para la primera cuota (1 al 15).',
                                'monthly' => 'Día del mes para la cuota mensual.',
                                default => null,
                            })
                            ->disabled(fn () => $isClosed || $hasPayments),

                        Select::make('due_day_2')
                            ->label('Segundo Día del Mes (Quincenal)')
                            ->options(array_combine(range(16, 31), range(16, 31)))
                            ->required(fn (GetSchema $get) => $get('periodicity') === 'biweekly')
                            ->visible(fn (GetSchema $get) => $get('periodicity') === 'biweekly')
                            ->live()
                            ->helperText('Solo aplica para créditos quincenales.')
                            ->disabled(fn () => $isClosed || $hasPayments),

                        DatePicker::make('first_due_date_override')
                            ->label('Fecha de primera cuota (opcional)')
                            ->helperText('Útil para dar una semana de gracia u otro plazo inicial.')
                            ->minDate(fn (GetSchema $get) => $get('start_date'))
                            ->live()
                            ->visible(fn (GetSchema $get) => filled($get('periodicity')))
                            ->nullable()
                            ->disabled(fn () => $isClosed),
                    ]),

                /*=====================================================
                | SECCIÓN 3: RESUMEN DEL CRÉDITO ESTIMADO
                =====================================================*/
                Section::make(function (GetSchema $get) use ($currentCompany) {
                    $companyId = $get('company_id') ?? $currentCompany;
                    $method = Company::find($companyId)?->interest_method;

                    $label = match ($method) {
                        'flat_rate_projected' => 'Tasa Mensual Proyectada',
                        'diminishing_balance' => 'Saldo Decreciente',
                        default => 'Tasa Total Plazo',
                    };

                    return "Resumen del Crédito Estimado ({$label})";
                })
                    ->description('Información calculada antes de guardar, según el método de interés de la compañía.')
                    ->columns(2)
                    ->columnSpanFull()
                    ->collapsible()
                    ->collapsed()
                    ->schema([
                        Placeholder::make('monthly_payment_placeholder')
                            ->label('Valor de la Cuota (Tentativo)')
                            ->content(function (Placeholder $component, GetSchema $get) {
                                $summary = CreditForm::getSummary($get);

                                return $summary['payment']
                                    ? Number::currency($summary['payment'], 'COP', locale: 'es_CO')
                                    : 'Ingrese monto, tasa y cuotas.';
                            }),

                        Placeholder::make('total_repay_placeholder')
                            ->label('Total a Pagar (Estimado)')
                            ->content(function (Placeholder $component, GetSchema $get) {
                                $summary = CreditForm::getSummary($get);

                                return $summary['totalRepay']
                                    ? Number::currency($summary['totalRepay'], 'COP', locale: 'es_CO')
                                    : '-';
                            }),

                        Placeholder::make('total_interest_placeholder')
                            ->label('Interés Total (Estimado)')
                            ->content(function (Placeholder $component, GetSchema $get) {
                                $summary = CreditForm::getSummary($get);

                                return $summary['totalInterest']
                                    ? Number::currency($summary['totalInterest'], 'COP', locale: 'es_CO')
                                    : '-';
                            }),
                    ]),
            ]);
    }

    /**
     * Wrapper para cálculo de resumen, manteniendo tu lógica original.
     */
    protected static function getSummary(GetSchema $get): array
    {
        $companyId = $get('company_id') ?? Auth::user()->company_id;

        $method = Company::find($companyId)?->interest_method ?? 'flat_rate';

        $amount = (float) $get('amount');
        $rate = (float) $get('interest_rate');
        $installments = (int) $get('installments_count');
        $periodicity = $get('periodicity');

        if (! $amount || ! $rate || ! $installments) {
            return [
                'payment' => null,
                'totalRepay' => null,
                'totalInterest' => null,
            ];
        }

        return match ($method) {
            'flat_rate_projected' => self::calculateFlatRateProjectedSummary($amount, $rate, $installments, $periodicity),
            'flat_rate' => self::calculateFlatRateSummary($amount, $rate, $installments, $periodicity),
            'diminishing_balance' => self::calculateDiminishingBalanceSummary($amount, $rate, $installments, $periodicity),
            default => [
                'payment' => null,
                'totalRepay' => null,
                'totalInterest' => null,
            ],
        };
    }
}
