<?php

use App\Models\OnboardingAudit;
use App\Models\User;
use App\Services\ReferralService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Transition;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Livewire\Component;



new class extends Component {
    #[Url]
    public int $step = 1;

    #[Url]
    public array $formData = [
        'name' => '',
        'username' => '',
        'date_of_birth' => '',
        'gender' => '',
        'marital_status' => '',
        'occupation' => '',
        'dial_code' => '',
        'city' => '',
        'zip_code' => '',
        'address_1' => '',
        'address_2' => '',
        'phone' => '',
        'referral_code' => '',
        'currency' => '',
        'bank_account_type' => '',
        'agreement_accepted' => false,
    ];
    public $password = '';

    public $password_confirmation = '';

    public array $countries = [];

    public array $states = [];

    #[Url]
    public string $country = '';

    #[Url]
    public string $state = '';

    public array $currencies = [];

    public array $bankAccountTypes = [];

    public ?OnboardingAudit $application = null;


    public array $gender = [
        ['value' => 'male', 'label' => 'Male'],
        ['value' => 'female', 'label' => 'Female'],
        ['value' => 'others', 'label' => 'Others'],
    ];

    public array $marital_status = [
        ['value' => 'single', 'label' => 'Single'],
        ['value' => 'married', 'label' => 'Married'],
        ['value' => 'divorced', 'label' => 'Divorced'],
        ['value' => 'widowed', 'label' => 'Widowed'],
        ['value' => 'others', 'label' => 'Others'],
    ];


    public function mount()
    {
        $user = Auth::user();
        // ❌ Redirect if no user
        if (!$user) {
            return redirect()->route('user.register');
        }

        // ❌ Redirect if profile is already complete
        if ($user->isProfileComplete()) {
            return redirect()->route('user.dashboard');
        }

        // ❌ Redirect if email not verified
        if (!$user->hasVerifiedEmail()) {
            return redirect()->route('verification.notice');
        }
        // ✅ STEP 1: Load JSON datasets first
        $dialCodes = collect(json_decode(file_get_contents(resource_path('data/countries.json')), true));
        $statesData = collect(json_decode(file_get_contents(resource_path('data/countrystate.json')), true));
        $currencies = collect(json_decode(file_get_contents(resource_path('data/currencies.json')), true));

        $this->countries = Cache::rememberForever('countries_with_states', function () use ($dialCodes, $statesData) {
            return $dialCodes->map(function ($country) use ($statesData) {
                $match = $statesData->firstWhere('code2', $country['code']);
                return [
                    'name' => $country['name'],
                    'code' => $country['code'],
                    'emoji' => $country['emoji'] ?? '🏳️',
                    'dial_code' => $country['dial_code'],
                    'image' => $country['image'] ?? null,
                    'states' => $match['states'] ?? [],
                ];
            })->sortBy('name')->values()->toArray();
        });

        $this->currencies = Cache::rememberForever('currencies_json', function () {
            return collect(json_decode(file_get_contents(resource_path('data/currencies.json')), true))
                ->sortBy('name')
                ->values()
                ->toArray();
        });


        // Load bank account types
        $this->bankAccountTypes = collect(config('bank.account_types'))
            ->map(fn($v, $k) => ['value' => $k, 'label' => "{$v['emoji']} {$v['label']}"])
            ->values()
            ->toArray();

        // ✅ STEP 2: Now load user application
        $application = OnboardingAudit::where('user_id', $user->id)->first();
        if ($application) {
            $this->step = (int) ($application->current_step ?? 1);

            $data = json_decode($application->data ?? '[]', true);
            if (!is_array($data)) {
                $data = [];
            }
            $this->formData = array_merge($this->formData, $data);

            if (!empty($data['country'])) {
                $this->country = $data['country'];
                $this->updatedCountry($this->country); // populate states list
            }

            if (!empty($data['state'])) {
                $this->state = $data['state'];
            }
        }

        // ✅ STEP 3: Capture referral code
        if (empty($this->formData['referral_code'])) {
            $referralCode = request()->query('ref') ?? session('referral_code');
            if ($referralCode) {
                $this->formData['referral_code'] = $referralCode;
                session(['referral_code' => $referralCode]);
            }
        }
        \Log::info('Mount hydration', [
            'formData' => $this->formData,
            'step' => $this->step,
        ]);
    }

    public function saveProgress()
    {
        $user = Auth::user();
        if (!$user)
            return;

        try {
            // Always work with array
            if (!is_array($this->formData)) {
                $this->formData = [];
            }

            // ✅ Merge top-level props into formData before saving
            $dataToSave = array_merge($this->formData, [
                'country' => $this->country,
                'state' => $this->state,
            ]);

            if (!empty($dataToSave)) {
                OnboardingAudit::updateOrCreate(
                    ['user_id' => $user->id],
                    [
                        'data' => $dataToSave,
                        'current_step' => $this->step,
                    ]
                );

                $this->dispatch('showToast', message: 'Progress saved successfully.', type: 'success');
            } else {
                OnboardingAudit::where('user_id', $user->id)->delete();
                Log::warning("Empty formData detected — progress not saved for user {$user->id}");
            }
        } catch (\Throwable $e) {
            Log::error('Failed to save progress', ['error' => $e->getMessage()]);
            $this->addError('general', 'Unable to save progress right now. Please try again.');
        }
    }



    public function updatedCountry($countryCode)
    {
        Log::info('Selected country code: ' . $countryCode);

        $selected = collect($this->countries)->firstWhere('code', $countryCode);

        Log::info('Country found:', $selected ?? ['none']);

        $this->states = $selected['states'] ?? [];
        $this->state = '';

        // Optional: auto-set country code for phone
        if (empty($this->formData['dial_code'])) {
            $this->formData['dial_code'] = $selected['dial_code'] ?? '';
        }

        Log::info('States set:', $this->states);
    }

    public function updatedState($value)
    {
        Log::info("State selected: $value");
    }

    #[Transition(type: 'forward')]
    public function nextStep(): void
    {
        if ($this->step >= 4) {
            return;
        }

        try {
            $this->validate($this->rules());
        } catch (\Illuminate\Validation\ValidationException $e) {
            \Log::error('Validation failed', $e->errors());
            throw $e;
        }

        $this->step++;
    }


    #[Transition(type: 'backward')]
    public function previousStep(): void
    {
        $this->step = max($this->step - 1, 1);
    }


    public function updated($field)
    {
        if ($this->step === 1 && str_starts_with($field, 'formData.')) {
            $this->validateOnly($field, $this->rules());
        }
    }

    public function clearError($field)
    {
        $this->resetErrorBag($field);
    }

    protected function rules(): array
    {
        return match ($this->step) {
            1 => [
                'formData.name' => 'required|string|max:255',
                'formData.username' => [
                    'required',
                    'string',
                    'max:30',
                    'regex:/^[A-Za-z0-9_]+$/',
                    Rule::unique('profiles', 'username')->ignore(auth()->id(), 'user_id'),
                ],
                'formData.date_of_birth' => 'required|date|before:today',
                'formData.gender' => 'required|in:male,female,others',
                'formData.marital_status' => 'required|in:single,married,divorced,widowed,others',
                'formData.occupation' => 'required|string|max:255',
                'formData.referral_code' => [
                    'nullable',
                    Rule::exists('users', 'referral_code'),
                    function ($attribute, $value, $fail) {
                            $user = auth()->user();
                            if ($user && $user->referral_code === $value) {
                                $fail('You cannot use your own referral code.');
                            }
                        }
                ],
            ],
            2 => [
                'country' => 'required|string|max:3',
                'state' => $this->states
                    ? ['required', 'string', Rule::in(array_column($this->states, 'name'))]
                    : ['required', 'string'],
                'formData.address_1' => 'required|string|max:255',
                'formData.address_2' => 'nullable|string|max:255',
                'formData.city' => 'required|string|max:100',
                'formData.zip_code' => 'required|string|max:20',
                'formData.phone' => 'required|string|regex:/^\+?[0-9\s\-]{7,20}$/',
                'formData.dial_code' => 'required|string|max:5',
            ],
            3 => [
                'formData.bank_account_type' => [
                    'required',
                    Rule::in(array_keys(config('bank.account_types')))
                ],
                'formData.currency' => 'required|string|size:3',
                'password' => [
                    'required',
                    'confirmed',
                    Password::min(8)
                        ->letters()
                        ->mixedCase()
                        ->numbers()
                        ->symbols()
                        ->uncompromised(),
                ],
            ],
            4 => [
                'formData.agreement_accepted' => 'accepted',
            ],
            default => []
        };
    }

    protected function messages(): array
    {
        return match ($this->step) {
            1 => [
                'formData.name.required' => 'Please enter your full name.',
                'formData.username.required' => 'A username is required.',
                'formData.username.max' => 'Usernames cannot exceed 30 characters.',
                'formData.username.regex' => 'Username may only contain letters, numbers, and underscores.',
                'formData.username.unique' => 'This username is already taken.',
                'formData.date_of_birth.required' => 'Please provide your date of birth.',
                'formData.date_of_birth.before' => 'Date of birth must be in the past.',
                'formData.gender.required' => 'Please select your gender.',
                'formData.marital_status.required' => 'Please select your marital status.',
                'formData.occupation.required' => 'Please tell us your occupation.',
            ],
            2 => [
                'formData.phone.required' => 'Your phone number is required.',
                'formData.phone.regex' => 'Please enter a valid phone number. Include country code if needed.',
                'formData.dial_code.required' => 'Please select your country code.',
                'formData.dial_code.max' => 'Invalid country code.',
                'country.required' => 'Please select your country.',
                'state.required' => 'Please select a state/province.',
                'formData.address_1.required' => 'Street address line 1 is required.',
                'formData.city.required' => 'City is required.',
                'formData.zip_code.required' => 'Postal / ZIP code is required.',
            ],
            3 => [
                'formData.bank_account_type.required' => 'Please select a bank account type.',
                'formData.bank_account_type.in' => 'Invalid bank account type selected.',
                'formData.currency.required' => 'Please select a currency.',
                'formData.currency.string' => 'Invalid currency format.',
                'formData.currency.size' => 'Currency code must be 3 letters (e.g. USD, EUR).',
                'formData.password.required' => 'Please create a password.',
                'formData.password.confirmed' => 'Passwords do not match.',
                'formData.password.min' => 'Password must be at least 8 characters.',
                'formData.password.letters' => 'Include at least one letter.',
                'formData.password.mixed' => 'Use both uppercase and lowercase letters.',
                'formData.password.numbers' => 'Include at least one number.',
                'formData.password.symbols' => 'Include at least one symbol.',
                'formData.password.*.uncompromised' => 'This password has appeared in a data leak. Please choose another.',
            ],
            4 => [
                'formData.agreement_accepted.accepted' => 'You must agree to the Terms and Privacy Policy to continue.',
            ],
            default => [
                'required' => 'This field is required.',
                'unique' => 'This value has already been taken.',
                'max' => 'You’ve reached the character limit for this field.',
            ],
        };
    }

    #[Computed]
    public function previewData(): array
    {
        $data = array_merge($this->formData, [
            'country' => $this->country,
            'state' => $this->state,
        ]);
        if (!empty($data['password'])) {
            $data['password'] = str_repeat('*', strlen($data['password']));
            $data['password_confirmation'] = str_repeat('*', strlen($data['password_confirmation']));
        }
        return $data;
    }
    public function goToStep(int $step): void
    {
        $this->step = $step;
    }

    public function submit(ReferralService $referralService)
    {
        $this->validate();
        \Log::info('FormData at submit:', $this->formData);

        $user = auth()->user();
        if (!$user)
            return;

        if ($user->isProfileComplete()) {
            \Log::warning("User {$user->id} attempted to re-submit profile.");
            $this->redirect(route('user.dashboard'));
        }

        try {
            // Step 1: Create profile and account
            DB::transaction(function () use ($user) {
                // Update user
                $user->update([
                    'name' => $this->formData['name'],
                    'password' => $this->password,
                ]);

                // Create profile
                $profile = $user->profile()->create([
                    'username' => $this->formData['username'],
                    'phone' => $this->formData['phone'],
                    'dial_code' => $this->formData['dial_code'],
                    'gender' => $this->formData['gender'],
                    'marital_status' => $this->formData['marital_status'],
                    'date_of_birth' => $this->formData['date_of_birth'],
                    'country' => $this->country,
                    'state' => $this->state,
                    'city' => $this->formData['city'],
                    'address_1' => $this->formData['address_1'],
                    'address_2' => $this->formData['address_2'],
                    'zip_code' => $this->formData['zip_code'],
                    'occupation' => $this->formData['occupation'],
                    'referral_code' => $this->formData['referral_code'] ?? null,
                    'agreement_accepted' => $this->formData['agreement_accepted'] ?? false,
                    'status' => 'active',
                    'currency' => $this->formData['currency'],
                ]);

                // Create primary account
                $profile->accounts()->create([
                    'bank_account_type' => $this->formData['bank_account_type'],
                    'balance' => 0,
                    'reserve_balance' => 0,
                    'is_primary' => true,
                    'is_active' => true,
                ]);
            });

            // After transaction
            $user->refresh(); // Reload user & relations
            $profile = $user->profile; // should now exist
            $profile->load('accounts'); // preload accounts

            if (!empty($this->formData['referral_code'])) {
                $referrer = User::where('referral_code', $this->formData['referral_code'])->first();

                if ($referrer && $referrer->id !== $user->id) {
                    $user->update(['referral_id' => $referrer->id]);
                    $referralService->applyReferralBonus($user, $this->formData['currency']);
                }
            }


            // Step 3: Login & cleanup
            Auth::login($user);
            OnboardingAudit::where('user_id', $user->id)->delete();
            session()->forget('onboarding');
            return redirect()->route('user.dashboard')->with([
                'message' => 'Account Created Successfully!.',
                'type' => 'success',
            ]);

        } catch (\Throwable $e) {
            \Log::error("Onboarding submission failed for user {$user->id}: {$e->getMessage()}");
            $this->dispatch('showToast', 'An error occurred during submission. Please try again.', type: 'error');
        }
    }


};
