<?php

declare(strict_types=1);

namespace App\Filament\Resources\JobResource\Pages;

use App\Enums\JobStatus;
use App\Filament\Resources\JobResource;
use App\Models\Booking;
use App\Models\Customer;
use App\Models\Flow;
use App\Models\Job;
use App\Models\Payment;
use App\Services\VevsClient;
use Filament\Actions;
use Filament\Forms;
use Filament\Forms\Components\Actions\Action as FormAction;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Fieldset;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Tabs;
use Filament\Forms\Components\Tabs\Tab;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
use Filament\Support\RawJs;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class CreateJob extends CreateRecord
{
    protected static string $resource = JobResource::class;

    protected ?string $heading = 'Create Job';

    /** Page + form full width */
    public function getMaxContentWidth(): ?string
    {
        return 'full';
    }

    public function hasFullWidthForm(): bool
    {
        return true;
    }

    /**
     * Default form values
     */
    protected function getFormDefaults(): array
    {
        return [
            'status'   => collect(JobStatus::cases())->map(fn ($c) => $c->value)->first() ?? 'pending',
            'flow_id'  => Flow::query()->orderBy('name')->value('id'),
            'currency' => 'NZD',
        ];
    }

    protected function getFormSchema(): array
    {
        return [
            Group::make()
                ->schema([
                    Tabs::make('JobTabs')
                        ->tabs([
                            Tabs\Tab::make('Details')
                                ->schema([
                                    Section::make('Job Details')
                                        ->schema([
                                            Grid::make(12)->schema([
                                                Select::make('flow_id')
                                                    ->label('Flow')
                                                    ->relationship('flow', 'name')
                                                    ->required()
                                                    ->searchable()
                                                    ->preload()
                                                    ->columnSpan(4),

                                                Select::make('status')
                                                    ->label('Status')
                                                    ->options(
                                                        collect(JobStatus::cases())
                                                            ->mapWithKeys(fn ($c) => [$c->value => Str::headline($c->value)])
                                                            ->all()
                                                    )
                                                    ->default(
                                                        collect(JobStatus::cases())
                                                            ->map(fn ($c) => $c->value)
                                                            ->first()
                                                    )
                                                    ->required()
                                                    ->columnSpan(4),

                                                TextInput::make('reference')
                                                    ->label('Internal Job Ref')
                                                    ->placeholder('Optional internal reference')
                                                    ->maxLength(191)
                                                    ->columnSpan(4),
                                            ]),

                                            Grid::make(12)->schema([
                                                TextInput::make('title')
                                                    ->label('Title')
                                                    ->required()
                                                    ->maxLength(191)
                                                    ->helperText('Short description of what this job is for.')
                                                    ->columnSpan(8),

                                                TextInput::make('external_reference')
                                                    ->label('External Booking Ref')
                                                    ->placeholder('e.g. VEVS / website booking reference')
                                                    ->maxLength(191)
                                                    ->columnSpan(4),
                                            ]),

                                            Textarea::make('notes')
                                                ->label('Internal Notes')
                                                ->rows(3)
                                                ->columnSpanFull(),
                                        ]),
                                ]),

                            Tabs\Tab::make('Customer')
                                ->schema([
                                    Section::make('Customer')
                                        ->schema([
                                            Grid::make(12)->schema([
                                                Select::make('customer_id')
                                                    ->label('Customer')
                                                    ->relationship('customer', 'name')
                                                    ->searchable()
                                                    ->preload()
                                                    ->reactive()
                                                    ->afterStateUpdated(function (?int $state, Set $set) {
                                                        if (! $state) {
                                                            return;
                                                        }

                                                        $customer = Customer::find($state);
                                                        if (! $customer) {
                                                            return;
                                                        }

                                                        $set('customer_name', $customer->name);
                                                        $set('customer_email', $customer->email);
                                                        $set('customer_phone', $customer->phone);
                                                    })
                                                    ->columnSpan(6),

                                                TextInput::make('customer_name')
                                                    ->label('Name')
                                                    ->maxLength(191)
                                                    ->required()
                                                    ->columnSpan(6),
                                            ]),

                                            Grid::make(12)->schema([
                                                TextInput::make('customer_email')
                                                    ->label('Email')
                                                    ->email()
                                                    ->maxLength(191)
                                                    ->required()
                                                    ->columnSpan(6),

                                                TextInput::make('customer_phone')
                                                    ->label('Phone')
                                                    ->maxLength(191)
                                                    ->columnSpan(6),
                                            ]),

                                            Fieldset::make('Billing Address')
                                                ->schema([
                                                    TextInput::make('billing_address.line1')->label('Address line 1')->maxLength(191),
                                                    TextInput::make('billing_address.line2')->label('Address line 2')->maxLength(191),
                                                    TextInput::make('billing_address.city')->label('City')->maxLength(191),
                                                    TextInput::make('billing_address.region')->label('Region / State')->maxLength(191),
                                                    TextInput::make('billing_address.postcode')->label('Postcode')->maxLength(191),
                                                    TextInput::make('billing_address.country')->label('Country')->maxLength(191),
                                                ])
                                                ->columns(3)
                                                ->statePath('billing_address'),
                                        ]),
                                ]),

                            Tabs\Tab::make('Dates')
                                ->columnSpanFull()
                                ->schema([
                                    Section::make('Dates')
                                        ->schema([
                                            Grid::make(12)->schema([
                                                DateTimePicker::make('start_at')
                                                    ->label('Start')
                                                    ->seconds(false)
                                                    ->native(false)
                                                    ->required()
                                                    ->helperText('Local time.')
                                                    ->columnSpan(6),

                                                DateTimePicker::make('end_at')
                                                    ->label('End')
                                                    ->seconds(false)
                                                    ->native(false)
                                                    ->required()
                                                    ->minDate(fn (Get $get) => $get('start_at') ?: null)
                                                    ->rule('after_or_equal:start_at')
                                                    ->helperText('Must be after Start.')
                                                    ->columnSpan(6),
                                            ]),
                                        ])
                                        ->columnSpanFull(),
                                ])
                                ->lazy(),

                            Tabs\Tab::make('Vehicle')
                                ->schema([
                                    Section::make('Vehicle')
                                        ->schema([
                                            Grid::make(12)->schema([
                                                Select::make('booking_id')
                                                    ->label('Linked Booking (optional)')
                                                    ->relationship('booking', 'external_reference')
                                                    ->searchable()
                                                    ->preload()
                                                    ->helperText('Link to a website / VEVS / external booking if applicable.')
                                                    ->columnSpan(6),

                                                TextInput::make('vehicle')
                                                    ->label('Vehicle (free text)')
                                                    ->helperText('E.g. "Suzuki Jimny White", "Range Rover Sport 19".')
                                                    ->maxLength(191)
                                                    ->columnSpan(6),
                                            ]),

                                            TextInput::make('vevs_car_id')
                                                ->label('VEVS Car ID (optional)')
                                                ->numeric()
                                                ->helperText('For debugging / linking with VEVS.')
                                                ->maxLength(191),
                                        ]),
                                ]),

                            Tabs\Tab::make('Payments')
                                ->schema([
                                    Section::make('Charge')
                                        ->schema([
                                            Grid::make(12)->schema([
                                                TextInput::make('charge_amount')
                                                    ->label('Total Charge (NZD)')
                                                    ->prefix('$')
                                                    ->numeric()
                                                    ->mask(
                                                        fn (TextInput\Mask $mask) => $mask
                                                            ->numeric()
                                                            ->decimalPlaces(2)
                                                            ->minValue(0)
                                                            ->thousandsSeparator(',')
                                                    )
                                                    ->helperText('Overall amount you intend to charge for this booking.')
                                                    ->columnSpan(4),

                                                Select::make('currency')
                                                    ->label('Currency')
                                                    ->options([
                                                        'NZD' => 'NZD',
                                                    ])
                                                    ->default('NZD')
                                                    ->required()
                                                    ->columnSpan(2),

                                                Toggle::make('auto_create_deposit')
                                                    ->label('Create initial deposit payment')
                                                    ->default(true)
                                                    ->helperText('If enabled, a deposit Payment record will be created after saving.')
                                                    ->columnSpan(3),

                                                TextInput::make('deposit_amount')
                                                    ->label('Deposit Amount (NZD)')
                                                    ->prefix('$')
                                                    ->numeric()
                                                    ->mask(
                                                        fn (TextInput\Mask $mask) => $mask
                                                            ->numeric()
                                                            ->decimalPlaces(2)
                                                            ->minValue(0)
                                                            ->thousandsSeparator(',')
                                                    )
                                                    ->helperText('Optional deposit amount to create as a succeeded Payment right away.')
                                                    ->columnSpan(3),
                                            ]),
                                        ]),
                                ]),

                            Tabs\Tab::make('Sync / Meta')
                                ->schema([
                                    Section::make('External Data')
                                        ->schema([
                                            TextInput::make('external_source')
                                                ->label('External Source')
                                                ->placeholder('vevs, website, manual etc.')
                                                ->maxLength(191),

                                            TextInput::make('external_payload')
                                                ->label('External Payload ID / notes (optional)')
                                                ->maxLength(191),

                                            Textarea::make('admin_notes')
                                                ->label('Admin Notes (non customer-facing)')
                                                ->rows(3),
                                        ]),
                                ]),
                        ]),
                ])
                ->columnSpan(8),

            Group::make()
                ->schema([
                    Section::make('Quick Import')
                        ->schema([
                            Forms\Components\TextInput::make('import_reference')
                                ->label('Import from VEVS by booking reference')
                                ->placeholder('e.g. QT1692049005')
                                ->maxLength(191),

                            FormAction::make('importFromVevs')
                                ->label('Import from VEVS')
                                ->icon('heroicon-o-cloud-arrow-down')
                                ->extraAttributes(['class' => 'w-full'])
                                ->action(function (array $data, Set $set, Get $get) {
                                    $this->handleVevsImport($data, $set, $get);
                                }),
                        ])
                        ->collapsible(),

                    Section::make('Summary')
                        ->schema([
                            Placeholder::make('summary_customer')
                                ->label('Customer')
                                ->content(function (Get $get) {
                                    $name  = $get('customer_name') ?: '—';
                                    $email = $get('customer_email') ?: '—';

                                    return "{$name} ({$email})";
                                }),

                            Placeholder::make('summary_dates')
                                ->label('Dates')
                                ->content(function (Get $get) {
                                    $start = $get('start_at');
                                    $end   = $get('end_at');

                                    if (! $start || ! $end) {
                                        return 'Not set';
                                    }

                                    $start = $start instanceof Carbon
                                        ? $start
                                        : Carbon::parse($start, config('app.timezone'));

                                    $end = $end instanceof Carbon
                                        ? $end
                                        : Carbon::parse($end, config('app.timezone'));

                                    return $start->format('d M Y, H:i') . ' → ' . $end->format('d M Y, H:i');
                                }),

                            Placeholder::make('summary_amount')
                                ->label('Charge')
                                ->content(function (Get $get) {
                                    $amount = $get('charge_amount') ?? null;

                                    if ($amount === null || $amount === '') {
                                        return 'Not set';
                                    }

                                    return '$' . number_format((float) $amount, 2);
                                }),
                        ]),
                ])
                ->columnSpan(4),
        ];
    }

    /**
     * Handle VEVS import action.
     */
    protected function handleVevsImport(array $data, Set $set, Get $get): void
    {
        $ref = trim((string) ($data['import_reference'] ?? ''));
        if ($ref === '') {
            Notification::make()
                ->title('Reference required')
                ->body('Please enter a VEVS booking reference.')
                ->danger()
                ->send();

            return;
        }

        /** @var VevsClient $client */
        $client = app(VevsClient::class);

        try {
            $vevs = $client->getReservationByRef($ref);
        } catch (\Throwable $e) {
            report($e);

            Notification::make()
                ->title('VEVS error')
                ->body('Unable to fetch reservation from VEVS. Please check logs.')
                ->danger()
                ->send();

            return;
        }

        if (! $vevs) {
            Notification::make()
                ->title('Reservation not found')
                ->body("No reservation found for '{$ref}'.")
                ->danger()
                ->send();

            return;
        }

        // 1. CUSTOMER UPSERT
        $email = strtolower(trim($vevs['c_email'] ?? ''));
        $name  = trim($vevs['c_name'] ?? $vevs['c_driver_name'] ?? 'Unknown customer');

        /** @var Customer $customer */
        $customer = Customer::query()
            ->when($email !== '', fn ($q) => $q->where('email', $email))
            ->when($email === '', fn ($q) => $q->where('name', $name))
            ->first();

        if (! $customer) {
            $customer = Customer::create([
                'name'  => $name,
                'email' => $email ?: null,
                'phone' => $vevs['c_phone'] ?? null,
            ]);
        } else {
            $customer->name  = $customer->name  ?: $name;
            $customer->email = $customer->email ?: $email;
            $customer->phone = $customer->phone ?: ($vevs['c_phone'] ?? null);
            $customer->save();
        }

        // 2. BOOKING UPSERT (minimal)
        $bookingRef = $vevs['ref_id'] ?? $vevs['booking_id'] ?? null;

        /** @var Booking $booking */
        $booking = Booking::query()
            ->when($bookingRef, fn ($q) => $q->where('external_reference', $bookingRef))
            ->where('customer_id', $customer->id)
            ->first();

        if (! $booking) {
            $booking = new Booking();
            $booking->customer_id       = $customer->id;
            $booking->external_reference = $bookingRef;
        }

        $pickup  = $vevs['from'] ?? null;
        $dropoff = $vevs['to'] ?? null;
        $carId   = $vevs['car_id'] ?? null;

        // For debug / display
        $vehicleLabel = $vevs['car'] ?? null;

        $booking->status = $vevs['status'] ?? $booking->status ?? 'pending';
        $booking->source = 'vevs';

        if (! $booking->vehicle_name) {
            $booking->vehicle_name = $vehicleLabel
                ?? ($carId !== null ? (string) $carId : '');
        }

        if ($pickup) {
            $booking->start_date = Carbon::parse($pickup, config('app.timezone'));
        }

        if ($dropoff) {
            $booking->end_date = Carbon::parse($dropoff, config('app.timezone'));
        }

        if (isset($vevs['total_price'])) {
            $booking->total_amount = (int) round(((float) $vevs['total_price']) * 100);
        }

        $booking->save();

        // 3. Prepare form payload
        $billingAddress = [
            'line1'    => $vevs['c_address'] ?? null,
            'line2'    => null,
            'city'     => $vevs['c_city'] ?? null,
            'region'   => $vevs['c_state'] ?? null,
            'postcode' => $vevs['c_zip'] ?? null,
            'country'  => $vevs['country_title'] ?? null,
        ];

        $payload = [
            'customer_id'    => $customer->id,
            'customer_name'  => $customer->name,
            'customer_email' => $vevs['c_email'] ?? $booking->customer?->email,
            'customer_phone' => $vevs['c_phone'] ?? $booking->customer?->phone,

            'booking_id'  => $booking->id,
            'customer_id' => $booking->customer_id,

            // Vehicle info
            'vehicle'     => $vehicleLabel,
            'vevs_car_id' => $carId,

            // Billing address
            'billing_address' => $billingAddress,
        ];

        // Dates
        if (! empty($pickup)) {
            $payload['start_at'] = Carbon::parse($pickup, config('app.timezone'));
        }

        if (! empty($dropoff)) {
            $payload['end_at'] = Carbon::parse($dropoff, config('app.timezone'));
        }

        // Charge / deposit
        if (isset($vevs['total_price'])) {
            $payload['charge_amount'] = number_format((float) $vevs['total_price'], 2, '.', '');
        }

        if (isset($vevs['required_deposit']) && ((float) $vevs['required_deposit']) > 0) {
            $payload['deposit_amount'] = number_format((float) $vevs['required_deposit'], 2, '.', '');
        }

        if ($booking->total_amount !== null) {
            $payload['charge_amount']       = number_format(((int) $booking->total_amount) / 100, 2, '.', '');
            $payload['charge_amount_cents'] = (int) $booking->total_amount;
        }

        // Fill form
        $this->resetValidation();
        $this->form->fill(
            array_filter(
                $payload,
                fn ($v) => $v !== null && $v !== ''
            )
        );
        $this->dispatch('$refresh');

        Notification::make()
            ->title('VEVS reservation imported')
            ->body("Imported reservation {$bookingRef} into this Job form.")
            ->success()
            ->send();
    }

    /**
     * Normalize data before creating the Job.
     */
    protected function mutateFormDataBeforeCreate(array $data): array
    {
        $data['currency'] = $data['currency'] ?? 'NZD';

        // charge_amount (dollars) → cents
        if (isset($data['charge_amount']) && !isset($data['charge_amount_cents'])) {
            $norm = preg_replace('/[^\d.]/', '', (string) $data['charge_amount']);
            $data['charge_amount_cents'] = (int) round(((float) $norm) * 100);
            unset($data['charge_amount']);
        }

        // Dates are already in app timezone (Pacific/Auckland); no manual timezone conversion here.

        // deposit
        if (!empty($data['deposit_amount']) && !isset($data['deposit_amount_cents'])) {
            $norm = preg_replace('/[^\d.]/', '', (string) $data['deposit_amount']);
            $data['deposit_amount_cents'] = (int) round(((float) $norm) * 100);
        }

        $data['flow_id'] = $data['flow_id'] ?? $data['flow'] ?? Flow::query()->orderBy('name')->value('id');
        $data['flow']    = $data['flow']    ?? $data['flow_id'];
        $data['status']  = $data['status']
            ?? collect(JobStatus::cases())->map(fn ($c) => $c->value)->first()
            ?? 'pending';

        if (empty($data['external_reference']) && !empty($data['booking_id'])) {
            $data['external_reference'] = Booking::whereKey($data['booking_id'])->value('external_reference') ?? '';
        }

        return $data;
    }

    /**
     * After Create: create deposit payment
     */
    protected function afterCreate(): void
    {
        $state = $this->form->getRawState();

        $amountCents = $state['deposit_amount_cents']
            ?? (isset($state['deposit_amount'])
                ? (int) round(((float) preg_replace('/[^\d.]/', '', $state['deposit_amount'])) * 100)
                : null);

        if ($amountCents && $amountCents > 0) {
            Payment::create([
                'job_id'       => $this->record->id,
                'type'         => 'booking_deposit',
                'amount_cents' => $amountCents,
                'currency'     => $state['currency'] ?? 'NZD',
                'status'       => 'succeeded',
                'mechanism'    => 'manual',
                'metadata'     => [
                    'note' => 'Created automatically from CreateJob form (auto_create_deposit).',
                ],
            ]);
        }
    }

    protected function getRedirectUrl(): string
    {
        return $this->getResource()::getUrl('view', ['record' => $this->record]);
    }

    protected function handleRecordCreation(array $data): Model
    {
        return static::getModel()::create($data);
    }
}
