<?php

namespace App\Livewire\Forms\Auth;

use App\Enums\Gender;
use App\Enums\UserStatus;
use App\Models\Customer;
use App\Models\Membership;
use App\Models\ReferralCode;
use App\Models\ReferralUsage;
use App\Models\Tier;
use App\Models\User;
use App\Rules\PhoneNumber;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;
use Livewire\Form;

class RegisterForm extends Form
{
    public string $email = '';

    public string $username = '';

    public string $password = '';

    public string $name = '';

    public string $phone_number = '';

    public string $gender = '';

    public string $referral_code = '';

    public function rulesStep1(): array
    {
        return [
            'email' => ['required', 'email', 'max:100', Rule::unique('users', 'email')],
            'username' => ['required', 'alpha_num', 'min:5', 'max:20', Rule::unique('users', 'username')],
            'password' => [
                'required',
                'string',
                'min:8',
                Password::min(8)->letters()->mixedCase()
                    ->numbers()
                    ->symbols()
                    ->uncompromised(),
            ],
        ];
    }

    public function rulesStep2(): array
    {
        return [
            'name' => ['required', 'string', 'max:50'],
            'phone_number' => ['required', 'string', new PhoneNumber],
            'gender' => ['required', Rule::in(Gender::values())],
            'referral_code' => ['nullable', 'string', Rule::exists('referral_codes', 'code')],
        ];
    }

    public function validateStep1()
    {
        $this->validate($this->rulesStep1());
    }

    public function validateStep2()
    {
        $this->validate($this->rulesStep2());
    }

    public function validateAll()
    {
        $this->validate(array_merge(
            $this->rulesStep1(),
            $this->rulesStep2()
        ));
    }

    public function validationAttributes(): array
    {
        return [
            'username' => 'nama pengguna',
            'password' => 'kata sandi',
            'name' => 'nama',
            'phone_number' => 'nomor telepon',
            'gender' => 'jenis kelamin',
        ];
    }

    public function auth()
    {
        $this->validateAll();

        $tier = Tier::orderBy('min_points')->first();
        $maxUser = User::max('id') + 1;
        $referralCode = ReferralCode::where('code', $this->referral_code)->first();

        DB::transaction(function () use ($tier, $maxUser, $referralCode) {
            $user = User::create([
                'email' => $this->email,
                'username' => $this->username,
                'password' => Hash::make($this->password),
                'status' => UserStatus::ACTIVE,
            ]);

            Customer::create([
                'user_id' => $user->id,
                'name' => $this->name,
                'phone_number' => $this->phone_number,
                'gender' => $this->gender,
            ]);

            Membership::create([
                'user_id' => $user->id,
                'tier_id' => $tier->id,
                'total_points' => 0,
            ]);

            ReferralCode::create([
                'user_id' => $user->id,
                'code' => generateReferralCode($this->username, $maxUser),
            ]);

            if ($this->referral_code) {
                ReferralUsage::create([
                    'user_id' => $user->id,
                    'referral_code_id' => $referralCode->id,
                ]);

                $referralCode->update(['uses_count', $referralCode->uses_count + 1]);
            }

            auth()->login($user);

            $user->sendEmailVerificationNotification();
        });
    }
}
