<?php

namespace App\Livewire;

use App\Enums\AssociationType;
use App\Models\Association;
use App\Models\AssociationRegistration;
use App\Models\User;
use App\Services\OtpService;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Livewire\Attributes\On;
use Livewire\Component;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Ysfkaya\FilamentPhoneInput\Forms\PhoneInput;
use Ysfkaya\FilamentPhoneInput\PhoneInputNumberType;

class RegisterAssociation extends Component implements HasForms
{
    use InteractsWithForms;

    public ?AssociationRegistration $registration = null;

    public ?string $email = null; // convenience binding

    public array $data = [];

    public function mount(): void
    {
        // Resume existing draft from session if available
        $draftId = session('association_registration_draft_id');
        if ($draftId) {
            $existing = AssociationRegistration::where('id', $draftId)
                ->where('status', '!=', AssociationRegistration::STATUS_COMPLETED)
                ->first();
            if ($existing) {
                $this->registration = $existing;
            }
        }

        if (! $this->registration) {
            $this->registration = AssociationRegistration::create([
                'status' => AssociationRegistration::STATUS_PENDING_VERIFICATION,
            ]);
            session(['association_registration_draft_id' => $this->registration->id]);
        }

        $this->email = $this->registration->email;
        $this->form->fill($this->registration->only([
            'name',
            'type',
            'license_number',
            'license_expiration_date',
            'representative_full_name',
            'representative_position',
            'phone_number',
            'email',
        ]));
    }

    public function form(Form $form): Form
    {
        return $form
            ->schema([
                TextInput::make('name')
                    ->label(__('association.name'))
                    ->placeholder(__('association.name_placeholder'))
                    ->maxLength(255)
                    ->required(),

                Select::make('type')
                    ->label(__('association.type_label'))
                    ->options(AssociationType::getOptions())
                    ->default(AssociationType::ASSOCIATION->value)
                    ->required()
                    ->native(false),

                SpatieMediaLibraryFileUpload::make('logo')
                    ->collection('logo')
                    ->label(__('association.logo'))
                    ->image()
                    ->acceptedFileTypes(['image/png', 'image/jpeg'])
                    ->maxSize(2048)
                    ->required(),

                TextInput::make('license_number')
                    ->label(__('association.license_number'))
                    ->placeholder(__('association.license_number_placeholder'))
                    ->maxLength(255)
                    ->numeric()
                    ->rules(['regex:/^[1-9][0-9]*$/'])
                    ->validationMessages([
                        'regex' => __('association.license_number_no_leading_zero'),
                    ])
                    ->required(),

                DatePicker::make('license_expiration_date')
                    ->label(__('association.license_expiration_date'))
                    ->required()
                    ->after('today'),

                TextInput::make('representative_full_name')
                    ->label(__('association.representative'))
                    ->placeholder(__('association.representative_placeholder'))
                    ->required()
                    ->maxLength(255)
                    ->columnSpanFull(),

                TextInput::make('representative_position')
                    ->label(__('association.position'))
                    ->placeholder(__('association.position_placeholder'))
                    ->required()
                    ->maxLength(255)
                    ->columnSpanFull(),

                PhoneInput::make('phone_number')
                    ->label(__('association.phone_number'))
                    ->defaultCountry('SA')
                    ->onlyCountries(['sa'])
                    ->validateFor('SA')
                    ->displayNumberFormat(PhoneInputNumberType::NATIONAL)
                    ->inputNumberFormat(PhoneInputNumberType::E164)
                    ->separateDialCode(true)
                    ->formatAsYouType()
                    ->disallowDropdown()
                    ->extraAttributes([
                        'dir' => 'ltr',
                        'style' => 'direction: ltr; text-align: left;',
                    ]),

                TextInput::make('email')
                    ->label(__('association.email'))
                    ->placeholder(__('association.email_placeholder'))
                    ->email()
                    ->required()
                    ->maxLength(255)
                    ->live(onBlur: true)
                    ->afterStateUpdated(function ($state) {
                        $this->email = $state;
                    })
                    ->extraAttributes([
                        'dir' => 'ltr',
                        'style' => 'direction: ltr; text-align: left;',
                    ]),

                SpatieMediaLibraryFileUpload::make('authorization_letter')
                    ->collection('authorization_letter')
                    ->label(__('association.authorization_letter_upload'))
                    ->helperText(
                        new \Illuminate\Support\HtmlString(
                            ' <a href="'.'https://sekaya-prod-api.fra1.digitaloceanspaces.com/sekaya-templates/%D8%AE%D8%B7%D8%A7%D8%A8_%D8%AA%D9%81%D9%88%D9%8A%D8%B6_v1.docx'.'" target="_blank" class="text-primary-600 hover:text-primary-500 underline">'.__('association.download_guidance').'</a>'
                        )
                    )
                    ->acceptedFileTypes(['application/pdf', 'image/png', 'image/jpeg'])
                    ->maxSize(5120)
                    ->required(),

                SpatieMediaLibraryFileUpload::make('license_certificate')
                    ->collection('license_certificate')
                    ->label(__('association.license_upload'))
                    ->acceptedFileTypes(['application/pdf', 'image/png', 'image/jpeg'])
                    ->maxSize(5120)
                    ->required(),
            ])
            ->model($this->registration)
            ->statePath('data')
            ->columns(2);
    }

    public function submit(): void
    {
        $state = $this->form->getState();
        $this->registration->fill($state);
        $this->registration->email = $state['email'] ?? $this->registration->email;
        $this->registration->save();

        // Duplicate checks before sending OTP (prevent wasted OTPs)
        if (User::where('email', 'ILIKE', trim(strtolower($this->registration->email)))->exists()) {
            session()->flash('error', __('association.email_already_registered'));

            return;
        }
        if (! empty($state['phone_number']) && User::where('phone_number', $state['phone_number'])->exists()) {
            session()->flash('error', __('association.phone_number_already_registered'));

            return;
        }

        // check if license_number already exists for this association type
        if (Association::where('license_number', $state['license_number'])
            ->where('type', $state['type'] ?? AssociationType::ASSOCIATION->value)
            ->exists()) {
            session()->flash('error', __('association.license_number_already_registered_for_type'));

            return;
        }

        $otpService = app(OtpService::class);
        $otpService->sendOtp(['email' => $this->registration->email]);
        Log::info('OTP sent (table-based) for association registration draft', ['draft_id' => $this->registration->id]);

        $this->dispatch('open-modal', id: 'otp-modal');
        // Provide identifier to OTP modal (email used currently)
        $this->dispatch('setAssociationAdminEmail', identifier: $this->registration->email);
    }

    #[On('otpConfirmed')]
    public function otpConfirmed(): void
    {
        if (! $this->registration?->exists) {
            session()->flash('error', __('association.system_error'));
            $this->dispatch('close-modal', id: 'otp-modal');

            return;
        }

        // OTP already verified in OtpFormModal via OtpService::verifyOtp (Option B),
        // so we directly proceed with promotion here.

        $data = $this->registration->toArray();

        if (User::where('email', 'ILIKE', trim(strtolower($data['email'])))->exists()) {
            session()->flash('error', __('association.email_already_registered'));
            $this->dispatch('close-modal', id: 'otp-modal');

            return;
        }
        if (User::where('phone_number', $data['phone_number'])->exists()) {
            session()->flash('error', __('association.phone_number_already_registered'));
            $this->dispatch('close-modal', id: 'otp-modal');

            return;
        }

        // check if license_number already exists for this association type
        if (Association::where('license_number', $data['license_number'])
            ->where('type', $data['type'] ?? AssociationType::ASSOCIATION->value)
            ->exists()) {
            session()->flash('error', __('association.license_number_already_registered_for_type'));
            $this->dispatch('close-modal', id: 'otp-modal');

            return;
        }

        try {
            DB::transaction(function () use ($data) {
                // Create admin user
                $admin = User::create([
                    'name' => $data['representative_full_name'],
                    'email' => $data['email'],
                    'phone_number' => $data['phone_number'],
                    'password' => Hash::make(Str::random(16)),
                ]);
                $admin->assignRole('مدير جمعية');

                // Create association
                $association = Association::create([
                    'name' => $data['name'],
                    'type' => $data['type'] ?? AssociationType::ASSOCIATION->value,
                    'license_number' => $data['license_number'],
                    'license_expiration_date' => $data['license_expiration_date'],
                    'representative_full_name' => $data['representative_full_name'],
                    'representative_position' => $data['representative_position'],
                    'phone_number' => $data['phone_number'],
                    'email' => $data['email'],
                    'status' => 'pending',
                    'admin_id' => $admin->id,
                ]);
                $admin->update(['association_id' => $association->id]);

                // Reassign media from draft to association
                Media::where('model_type', AssociationRegistration::class)
                    ->where('model_id', $this->registration->id)
                    ->update([
                        'model_type' => Association::class,
                        'model_id' => $association->id,
                    ]);

                $this->registration->status = AssociationRegistration::STATUS_COMPLETED;
                $this->registration->save();
            });
        } catch (\Exception $e) {
            Log::error('Association promotion failed', [
                'draft_id' => $this->registration->id,
                'error' => $e->getMessage(),
            ]);
            session()->flash('error', __('association.system_error'));
            $this->dispatch('close-modal', id: 'otp-modal');

            return;
        }

        // Clean session draft id
        session()->forget('association_registration_draft_id');

        Log::info('Association registration completed', ['draft_id' => $this->registration->id]);
        $this->dispatch('close-modal', id: 'otp-modal');
        redirect()->route('filament.association-admin.auth.login');
    }

    public function render()
    {
        return view('livewire.register-association');
    }
}
