<?php

namespace App\Livewire;

use App\Models\Otp;
use App\Models\User;
use App\Services\OtpService;
use Filament\Facades\Filament;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Livewire\Attributes\On;
use Livewire\Component;
use Propaganistas\LaravelPhone\PhoneNumber;

class AdminsOtpLogin extends Component implements HasForms
{
    use InteractsWithForms;

    public ?string $identifier; // Can be email or phone

    public ?User $association_admin;

    public function mount(): void
    {
        $this->form->fill();
    }

    public function form(Form $form): Form
    {
        return $form
            ->schema([
                TextInput::make('identifier')
                    ->hiddenLabel()
                    ->placeholder(__('auth.email_or_phone_placeholder'))
                    ->required()
                    ->extraInputAttributes(['dir' => 'ltr'])
                    ->dehydrateStateUsing(fn ($state) => trim($state))
                    ->rules([
                        function () {
                            return function (string $attribute, $value, \Closure $fail) {

                                // trim the identifier
                                $value = trim($value);

                                // Check if it's a valid email
                                $isEmail = filter_var($value, FILTER_VALIDATE_EMAIL);

                                if (! $isEmail) {
                                    // Check if it's a valid phone number for Saudi Arabia
                                    try {
                                        $phoneNumber = new PhoneNumber($value, 'SA');
                                        if (! $phoneNumber->isValid()) {
                                            $fail(__('auth.invalid_email_or_phone'));
                                        }
                                    } catch (\Exception $e) {
                                        $fail(__('auth.invalid_email_or_phone'));
                                    }
                                }
                            };
                        },
                    ]),
            ]);
    }

    public function submit()
    {
        // Validate the identifier input
        $data = $this->form->getState();
        $identifier = strtolower($data['identifier']); // Removed trim() since it's handled by the form

        // Determine if identifier is email or phone
        $isEmail = filter_var($identifier, FILTER_VALIDATE_EMAIL);

        if ($isEmail) {
            // Search by email (exact match, case-insensitive)
            $this->association_admin = User::where('email', 'ILIKE', $identifier)->first();
        } else {
            // Normalize phone number for search using PhoneNumber library
            try {
                $normalizedPhone = $this->normalizePhoneNumber($identifier);
                $this->association_admin = User::where('phone_number', $normalizedPhone)->first();
            } catch (\Exception $e) {
                $this->addError('identifier', __('auth.invalid_email_or_phone'));

                return;
            }
        }

        // If the user does not exist, add an error message
        if (! $this->association_admin) {
            $errorKey = $isEmail ? 'auth.email_not_found' : 'auth.phone_not_found';
            $this->addError('identifier', __($errorKey));

            return;
        }

        // Send OTP using the OtpService
        $otpService = app(OtpService::class);

        if ($isEmail) {
            $otpService->sendOtp(['email' => $identifier]);
        } else {
            $otpService->sendOtp(['phone' => $this->normalizePhoneNumber($identifier)]);
        }

        // Dispatch an event to open the OTP modal
        $this->dispatch('open-modal', id: 'otp-modal');

        // Dispatch an event to set the association admin identifier on the OTP modal component
        $this->dispatch('setAssociationAdminEmail', identifier: $identifier);
    }

    /**
     * Normalize phone number using PhoneNumber library
     */
    private function normalizePhoneNumber(string $phone): string
    {
        try {
            $phoneNumber = new PhoneNumber($phone, 'SA');

            return $phoneNumber->formatE164(); // Returns format like +966501234567
        } catch (\Exception $e) {
            throw new \InvalidArgumentException('Invalid phone number format');
        }
    }

    #[On('otpConfirmed')]
    public function otpConfirmed()
    {
        // Log in the user
        Filament::auth()->login($this->association_admin);

        // Regenerate the session to prevent session fixation attacks
        session()->regenerate();

        // Redirect to the association admin dashboard
        return redirect('/admin');
    }

    public function render()
    {
        return view('livewire.admins-otp-login');
    }
}
