<?php

namespace App\Http\Requests\Recruitment;

use App\Domain\Identity\Models\User;
use App\Domain\Organization\Models\Branch;
use App\Domain\Recruitment\Enums\ComplianceStatus;
use App\Domain\Recruitment\Models\Employer;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class StoreEmployerRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'company_name' => ['required', 'string', 'max:255'],
            'legal_name' => ['nullable', 'string', 'max:255'],
            'country' => ['required', 'string', 'size:2'],
            'city' => ['nullable', 'string', 'max:100'],
            'address' => ['nullable', 'string', 'max:1000'],

            'registration_number' => ['nullable', 'string', 'max:100'],
            'license_number' => ['nullable', 'string', 'max:100'],
            'license_expiry' => ['nullable', 'date'],
            'industry' => ['nullable', 'string', 'max:120'],
            'website' => ['nullable', 'url', 'max:255'],
            'email' => ['nullable', 'email', 'max:255'],
            'phone' => ['nullable', 'string', 'max:32'],
            'whatsapp' => ['nullable', 'string', 'max:32'],

            'branch_id' => ['nullable', 'uuid', Rule::exists('branches', 'uuid')->whereNull('deleted_at')],
            'account_manager_id' => ['nullable', 'uuid', Rule::exists('users', 'uuid')->whereNull('deleted_at')],

            'compliance_status' => ['nullable', Rule::in(ComplianceStatus::values())],
            'compliance_notes' => ['nullable', 'string', 'max:2000'],

            'agreement_reference' => ['nullable', 'string', 'max:100'],
            'agreement_start_date' => ['nullable', 'date'],
            'agreement_expiry_date' => ['nullable', 'date', 'after_or_equal:agreement_start_date'],
            'credit_terms_days' => ['nullable', 'integer', 'min:0', 'max:365'],
            'billing_currency' => ['nullable', 'string', 'size:3'],

            'rating' => ['nullable', 'integer', 'between:1,5'],
            'preferred_jobs' => ['nullable', 'string', 'max:2000'],
            'notes' => ['nullable', 'string', 'max:5000'],

            'contacts' => ['sometimes', 'array', 'max:20'],
            'contacts.*.id' => ['nullable', 'uuid'],
            'contacts.*.name' => ['required', 'string', 'max:255'],
            'contacts.*.designation' => ['nullable', 'string', 'max:120'],
            'contacts.*.email' => ['nullable', 'email', 'max:255'],
            'contacts.*.phone' => ['nullable', 'string', 'max:32'],
            'contacts.*.whatsapp' => ['nullable', 'string', 'max:32'],
            'contacts.*.language' => ['nullable', 'string', 'max:40'],
            'contacts.*.is_primary' => ['nullable', 'boolean'],
            'contacts.*.notes' => ['nullable', 'string', 'max:1000'],
        ];
    }

    /** Two employers with the same name in the same country are almost always one. */
    public function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            $companyId = $this->user()?->company_id;
            $name = $this->input('company_name');
            $country = $this->input('country');

            if ($companyId === null || blank($name) || blank($country)) {
                return;
            }

            $duplicate = Employer::where('company_id', $companyId)
                ->where('company_name', $name)
                ->where('country', strtoupper($country))
                ->when($this->route('employer'), fn ($q) => $q->whereKeyNot($this->route('employer')->getKey()))
                ->exists();

            if ($duplicate) {
                $validator->errors()->add(
                    'company_name',
                    'An employer with this name already exists for that country.',
                );
            }
        });
    }

    /** @return array<string, mixed> */
    public function modelAttributes(): array
    {
        $data = $this->validated();
        unset($data['contacts']);

        $data['country'] = strtoupper((string) ($data['country'] ?? ''));
        $data['branch_id'] = $this->resolveKey(Branch::class, $data['branch_id'] ?? null);
        $data['account_manager_id'] = $this->resolveKey(User::class, $data['account_manager_id'] ?? null);

        return $data;
    }

    /** @return array<int, array<string, mixed>>|null */
    public function contacts(): ?array
    {
        return $this->has('contacts') ? (array) $this->input('contacts') : null;
    }

    private function resolveKey(string $model, ?string $uuid): ?int
    {
        return $uuid === null ? null : $model::where('uuid', $uuid)->value('id');
    }
}
