<?php

namespace App\Http\Requests\Auth;

use App\Models\Admin;
use App\Models\AdminLoginOtp;
use App\Rules\Turnstile;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class AdminVerifyOtpRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'email' => 'required|string|max:120|email',
            'code' => 'required|digits:6',
            'device' => 'required|array',
            'device.uuid' => 'required|string',
            'device.type' => 'required|string',
            'device.client.name' => 'required|string',
            'device.client.type' => 'required|string',
            'device.os.name' => 'required|string',
            'device.os.platform' => 'required|string',
            'turnstile_token' => ['required', 'string', new Turnstile()],
        ];
    }

    public function messages(): array
    {
        return [
            'email.required' => 'El correo es obligatorio.',
            'email.email' => 'Correo inválido.',
            'code.required' => 'El código OTP es obligatorio.',
            'code.digits' => 'El código OTP debe tener 6 dígitos.',
            'turnstile_token.required' => 'Completá la validación de seguridad.',
        ];
    }

    public function getAdmin(): Admin
    {
        $admin = Admin::query()
            ->where('email', $this->string('email')->toString())
            ->with(['persona'])
            ->select('id', 'username', 'email', 'root', 'email_verified_at', 'persona_id', 'estado')
            ->first();

        if (! $admin || ! $admin->estado) {
            throw ValidationException::withMessages([
                'email' => 'No existe un administrador activo con ese correo.',
            ]);
        }

        return $admin;
    }

    public function getOtpFor(Admin $admin): AdminLoginOtp
    {
        $otp = AdminLoginOtp::query()
            ->where('admin_id', $admin->id)
            ->whereNull('used_at')
            ->where('expires_at', '>', now())
            ->latest('id')
            ->first();

        if (! $otp || ! Hash::check($this->string('code')->toString(), $otp->code)) {
            throw ValidationException::withMessages([
                'code' => 'El código OTP es inválido o expiró.',
            ]);
        }

        return $otp;
    }
}
