<?php

namespace App\Http\Requests\Api\Concerns;

use App\Models\Customer;
use App\Models\Nominee;
use Illuminate\Http\UploadedFile;
use Illuminate\Validation\Rule;

trait ValidatesNominee
{
    /**
     * @return array<string, mixed>
     */
    protected function nomineeRules(bool $required, bool $requireDocuments): array
    {
        return [
            'nominee' => [Rule::requiredIf($required), 'nullable', 'array'],
            'nominee.full_name' => [Rule::requiredIf($required), 'nullable', 'string', 'max:255'],
            'nominee.cnic' => [Rule::requiredIf($required), 'nullable', 'string', 'max:20'],
            'nominee.phone' => ['nullable', 'string', 'max:30'],
            'nominee.email' => ['nullable', 'email', 'max:255'],
            'nominee_documents' => [
                Rule::requiredIf($requireDocuments),
                'nullable',
                'array',
                'min:'.($requireDocuments ? Nominee::MIN_DOCUMENTS : 0),
                'max:'.Nominee::MAX_DOCUMENTS,
            ],
            'nominee_documents.*' => ['file', 'image', 'mimes:jpeg,jpg,png,webp', 'max:5120'],
        ];
    }

    /**
     * @return array{
     *     full_name: string,
     *     cnic: string,
     *     phone: string|null,
     *     email: string|null
     * }|null
     */
    protected function nomineePayload(): ?array
    {
        if (! $this->exists('nominee')) {
            return null;
        }

        /** @var array{
         *     full_name?: string|null,
         *     cnic?: string|null,
         *     phone?: string|null,
         *     email?: string|null
         * } $nominee
         */
        $nominee = $this->safe()->input('nominee', []);

        if (! is_array($nominee) || $nominee === []) {
            return null;
        }

        return [
            'full_name' => (string) ($nominee['full_name'] ?? ''),
            'cnic' => (string) ($nominee['cnic'] ?? ''),
            'phone' => $nominee['phone'] ?? null,
            'email' => $nominee['email'] ?? null,
        ];
    }

    /**
     * @return list<UploadedFile>
     */
    public function nomineeDocuments(): array
    {
        $files = $this->file('nominee_documents', []);

        if ($files instanceof UploadedFile) {
            $files = [$files];
        }

        if (! is_array($files)) {
            return [];
        }

        return array_values(array_filter(
            $files,
            fn (mixed $file): bool => $file instanceof UploadedFile,
        ));
    }

    protected function nomineeIsPresent(): bool
    {
        return $this->filled('nominee.full_name')
            || $this->filled('nominee.cnic')
            || $this->filled('nominee.phone')
            || $this->filled('nominee.email')
            || $this->hasFile('nominee_documents');
    }

    protected function prepareNomineeForValidation(): void
    {
        if (! $this->exists('nominee') || ! is_array($this->input('nominee'))) {
            return;
        }

        $nominee = $this->input('nominee');

        foreach (['full_name', 'cnic', 'phone', 'email'] as $field) {
            if (array_key_exists($field, $nominee) && ! filled($nominee[$field])) {
                $nominee[$field] = null;
            }
        }

        $this->merge(['nominee' => $nominee]);
    }

    protected function customerNeedsNomineeDocuments(?Customer $customer = null): bool
    {
        if ($this->nomineeIsPresent() && $customer === null) {
            return true;
        }

        if (! $this->nomineeIsPresent()) {
            return false;
        }

        $existing = $customer?->nominee?->documents()?->count() ?? 0;

        return ($existing + count($this->nomineeDocuments())) < Nominee::MIN_DOCUMENTS;
    }
}
