<?php

declare(strict_types=1);

namespace App\Http\Requests\User;

use App\Support\ApiResponse;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Validation\Rule;

class UpdateProfileRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user() !== null;
    }

    protected function prepareForValidation(): void
    {
        $payload = [];

        if ($this->has('cellphone')) {
            $cellphone = preg_replace('/\D+/', '', (string) $this->input('cellphone'));

            if (str_starts_with((string) $cellphone, '98') && strlen((string) $cellphone) === 12) {
                $cellphone = '0' . substr((string) $cellphone, 2);
            }

            $payload['cellphone'] = $cellphone;
        }

        foreach (['password', 'password_confirmation', 'current_password'] as $field) {
            if ($this->exists($field) && blank($this->input($field))) {
                $payload[$field] = null;
            }
        }

        if ($payload !== []) {
            $this->merge($payload);
        }
    }

    public function rules(): array
    {
        $userId = $this->route('routeUser') instanceof \App\Models\User
            ? $this->route('routeUser')->id
            : $this->user()->id;
        $changingPassword = filled($this->input('password'));
        $target = $this->route('routeUser') instanceof \App\Models\User
            ? $this->route('routeUser')
            : $this->user();
        $hasPassword = filled($target?->password);

        return [
            'first_name' => ['required', 'string', 'max:100'],
            'last_name' => ['required', 'string', 'max:100'],
            'name' => [
                'required',
                'string',
                'max:50',
                'regex:/^[\p{L}\p{N}_.-]+$/u',
                Rule::unique('users', 'username')->ignore($userId),
            ],
            'cellphone' => [
                'required',
                'string',
                'regex:/^09\d{9}$/',
                Rule::unique('users', 'cellphone')->ignore($userId),
            ],
            'national_code' => [
                'nullable',
                'string',
                'regex:/^\d{10}$/',
                Rule::unique('users', 'national_code')->ignore($userId),
            ],
            'email' => [
                'nullable',
                'email',
                'max:255',
                Rule::unique('users', 'email')->ignore($userId),
            ],
            'phone' => ['nullable', 'string', 'max:20'],
            'dob' => ['nullable', 'date', 'date_format:Y-m-d', 'before:today'],
            'address' => ['nullable', 'string', 'max:2000'],
            'avatar' => ['nullable', 'string', 'max:2048'],
            'password' => ['nullable', 'string', 'min:8', 'confirmed'],
            'password_confirmation' => [$changingPassword ? 'required' : 'nullable', 'string'],
            'current_password' => [$changingPassword && $hasPassword ? 'required' : 'nullable', 'string'],
        ];
    }

    public function messages(): array
    {
        return [
            'first_name.required' => 'نام الزامی است.',
            'last_name.required' => 'نام خانوادگی الزامی است.',
            'name.required' => 'نام کاربری الزامی است.',
            'name.unique' => 'این نام کاربری قبلاً ثبت شده است.',
            'name.regex' => 'نام کاربری فقط می‌تواند شامل حروف، اعداد، خط تیره، نقطه و زیرخط باشد.',
            'cellphone.required' => 'شماره موبایل الزامی است.',
            'cellphone.regex' => 'شماره موبایل باید با 09 شروع شده و ۱۱ رقم باشد.',
            'cellphone.unique' => 'این شماره موبایل قبلاً ثبت شده است.',
            'national_code.regex' => 'کد ملی باید ۱۰ رقم باشد.',
            'national_code.unique' => 'این کد ملی قبلاً ثبت شده است.',
            'email.email' => 'فرمت ایمیل معتبر نیست.',
            'email.unique' => 'این ایمیل قبلاً ثبت شده است.',
            'dob.before' => 'تاریخ تولد باید قبل از امروز باشد.',
            'dob.date_format' => 'تاریخ تولد باید با فرمت YYYY-MM-DD باشد.',
            'password.min' => 'رمز عبور جدید باید حداقل ۸ کاراکتر باشد.',
            'password.confirmed' => 'تکرار رمز عبور مطابقت ندارد.',
            'password_confirmation.required' => 'تکرار رمز عبور الزامی است.',
            'current_password.required' => 'برای تغییر رمز عبور، وارد کردن رمز فعلی الزامی است.',
        ];
    }

    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator): void {
            if (! filled($this->input('password'))) {
                return;
            }

            $target = $this->route('routeUser') instanceof \App\Models\User
                ? $this->route('routeUser')
                : $this->user();

            if (! $target || blank($target->password)) {
                return;
            }

            $current = (string) $this->input('current_password', '');

            if ($current === '' || ! \Illuminate\Support\Facades\Hash::check($current, (string) $target->password)) {
                $validator->errors()->add('current_password', 'رمز عبور فعلی صحیح نیست.');
            }
        });
    }

    protected function failedValidation(Validator $validator): void
    {
        throw new HttpResponseException(
            ApiResponse::response(
                message: 'اطلاعات وارد شده نامعتبر است.',
                status: 422,
                errors: $validator->errors()->toArray()
            )
        );
    }
}
