<?php

namespace App\Http\Requests\Api\Auth;

use App\Models\Datmas\Indentitas;
use App\Models\Datmas\Siswa;
use Illuminate\Foundation\Http\FormRequest;

class RegisterStudentRequest extends FormRequest
{
    protected ?bool $nisHasAccount = null;

    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        if ($this->nisHasAccount()) {
            return [
                'nis' => 'required|string|exists:mai2.tsiswa,nis',
                'nouid' => 'nullable|string',
            ];
        }

        return [
            'nis' => 'required|string|exists:mai2.tsiswa,nis',
            'nouid' => 'nullable|string',
            'nama' => 'required|string|max:100',
            'warneg' => 'required|string|max:10',
            'warnegName' => 'required|string|max:100',
            'nik' => 'nullable|numeric|digits:16',
            'kk' => 'nullable|numeric|digits:16',
            'ktpFile' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
            'ktp_file' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
            'paspor' => 'nullable|string|max:50',
            'pasporFile' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
            'paspor_file' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
            'alamat1' => 'required|array',
            'alamat1.addr' => 'required|string|max:255',
            'alamat1.rt' => 'required|string|max:10',
            'alamat1.rw' => 'required|string|max:10',
            'alamat1.kec' => 'required|string|max:20',
            'alamat1.desa' => 'required|string|max:20',
            'alamat1.kodpos' => 'required|string|max:10',
            'alamat1.prov' => 'required|string|max:10',
            'alamat1.kab' => 'required|string|max:10',
            'alamat1.kabName' => 'required|string|max:100',
            'temtin' => 'required|boolean',
            'alamat2' => 'required_if:temtin,1|array|nullable',
            'alamat2.addr' => 'required_if:temtin,1|string|max:255',
            'alamat2.rt' => 'required_if:temtin,1|string|max:10',
            'alamat2.rw' => 'required_if:temtin,1|string|max:10',
            'alamat2.kec' => 'required_if:temtin,1|string|max:20',
            'alamat2.desa' => 'required_if:temtin,1|string|max:20',
            'alamat2.kodpos' => 'required_if:temtin,1|string|max:10',
            'alamat2.prov' => 'required_if:temtin,1|string|max:10',
            'alamat2.kab' => 'required_if:temtin,1|string|max:10',
            'hub' => 'required|string|in:0,1,2',
            'tel' => 'required|string|max:16|regex:/^[0-9]+$/',
            'email' => 'required|email:rfc,dns|max:100',
            'sign' => 'nullable|string|size:64',
            'payload' => 'nullable|string',
        ];
    }

    public function messages(): array
    {
        return [
            'nis.exists' => 'NIS tidak valid.',
        ];
    }

    public function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            if ($this->nisHasAccount()) {
                return;
            }

            $warneg = $this->string('warneg')->toString();

            if ($warneg === 'ID') {
                if (!$this->filled('nik')) {
                    $validator->errors()->add('nik', 'NIK wajib diisi untuk WNI.');
                }

                if (!$this->filled('kk')) {
                    $validator->errors()->add('kk', 'Nomor KK wajib diisi untuk WNI.');
                }

                if (!$this->hasFile('ktpFile') && !$this->hasFile('ktp_file')) {
                    $validator->errors()->add('ktpFile', 'Foto KTP wajib diunggah untuk WNI.');
                }
            } else {
                if (!$this->filled('paspor')) {
                    $validator->errors()->add('paspor', 'Nomor paspor wajib diisi untuk WNA.');
                }

                if (!$this->hasFile('pasporFile') && !$this->hasFile('paspor_file')) {
                    $validator->errors()->add('pasporFile', 'Foto paspor wajib diunggah untuk WNA.');
                }
            }

            if ($this->filled('nouid')) {
                $requestedId = $this->string('nouid')->toString();
                $identity = Indentitas::query()
                    ->with('siswa')
                    ->where('nouid', $requestedId)
                    ->first();

                if ($identity && $identity->siswa?->nis !== $this->string('nis')->toString()) {
                    $validator->errors()->add('nouid', 'NIS tidak cocok dengan nomor identitas siswa.');
                }

                if (! $identity && $requestedId !== $this->string('nis')->toString()) {
                    $validator->errors()->add('nouid', 'Nomor identitas tidak cocok dengan NIS.');
                }
            }
        });
    }

    protected function prepareForValidation(): void
    {
        $identity = null;

        if ($this->filled('nis')) {
            $identity = Siswa::query()
                ->with('indentitas')
                ->where('nis', $this->string('nis')->toString())
                ->first();
        }

        $alamat1 = $this->input('alamat1', []);
        $kabName = data_get($alamat1, 'kabName') ?? $this->input('kabName');

        if ($kabName !== null) {
            data_set($alamat1, 'kabName', $kabName);
        }

        $this->merge([
            'nouid' => $this->input('nouid') ?? $identity?->indentitas?->nouid,
            'warnegName' => $this->input('warnegName')
                ?? $this->input('warneg_name')
                ?? ($this->input('warneg') === 'ID' ? 'Indonesia' : null),
            'alamat1' => $alamat1,
        ]);
    }

    protected function nisHasAccount(): bool
    {
        if ($this->nisHasAccount !== null) {
            return $this->nisHasAccount;
        }

        if (! $this->filled('nis')) {
            return $this->nisHasAccount = false;
        }

        $siswa = Siswa::query()
            ->where('nis', $this->string('nis')->toString())
            ->first(['nis', 'pin']);

        return $this->nisHasAccount = (bool) $siswa?->has_pin;
    }
}
