<?php

namespace App\Livewire\Traits;

trait HasClientValidation
{
    /**
     * Obtiene el ID del cliente para la regla unique (null para Create)
     */
    protected function getClientId(): ?int
    {
        return $this->client->id ?? null;
    }

    /**
     * Obtiene las reglas de validación para clientes
     */
    protected function getClientValidationRules(): array
    {
        $clientId = $this->getClientId();
        $uniqueShortname = $clientId 
            ? "unique:clients,shortname,{$clientId}"
            : 'unique:clients,shortname';
        $uniqueCrmId = $clientId
            ? "unique:clients,crm_id,{$clientId}"
            : 'unique:clients,crm_id';

        return [
            'name' => 'required|string|max:200',
            'shortname' => "required|string|max:50|{$uniqueShortname}",
            'crm_id' => "nullable|string|max:100|{$uniqueCrmId}",
            'cif' => 'nullable|string|max:20',
            'razon_social' => 'nullable|string|max:200',
            'fecha_inicio_relacion' => 'nullable|date',
            'contacts' => 'array',
            // **`required` a secas, y funciona porque las filas vacías ya no llegan**:
            // `limpiarContactosVacios()` se pasa antes de validar. Era
            // `required_with:contacts.*`, que expandido a la fila actual apunta al
            // propio array: siempre está presente, así que el nombre era **siempre**
            // obligatorio. Pulsar «Añadir contacto» y no rellenarlo —lo más normal del
            // mundo— impedía guardar el cliente, con un «The contacts.0.name field is
            // required when contacts.0 is present». Y el filtro de vacíos existía
            // desde el principio, pero corría DESPUÉS de la validación, así que no
            // llegaba a actuar nunca.
            'contacts.*.name' => 'required|string|max:200',
            'contacts.*.email' => 'nullable|email|max:200',
            'contacts.*.phone' => 'nullable|string|max:50',
            'description' => 'nullable|string',
            'jira' => 'nullable|string|max:200',
            // `boolean` y no `accepted`: con `accepted` desmarcar la casilla daba «The
            // actived field must be accepted» y el cliente se quedaba activo, o sea que
            // **no se podía dar de baja a ninguno**. Mismo fallo que en Entornos.
            'actived' => 'boolean',
            'observation' => 'nullable|string',
        ];
    }

    /**
     * Mensajes de las reglas del cliente.
     *
     * Explícitos porque **este proyecto no tiene carpeta `lang/`** —decisión
     * documentada— así que sin esto los errores salen en inglés y con el nombre
     * técnico del campo en medio de un panel en castellano.
     *
     * @return array<string, string>
     */
    protected function getClientValidationMessages(): array
    {
        return [
            'name.required' => 'El nombre del cliente es obligatorio.',
            // **Se nombra la papelera.** `Client` tiene borrado lógico y el índice de
            // la base no distingue borrados, así que el shortname de un cliente dado
            // de baja sigue ocupado — y sin decirlo el error señala una fila que no se
            // ve en ninguna pantalla. Mismo caso que en los tipos de entorno.
            'shortname.required' => 'El shortname es obligatorio: es el identificador corto del cliente.',
            'shortname.unique' => 'Ese shortname ya está en uso, y sigue ocupado aunque el cliente que lo tenía esté dado de baja.',
            'crm_id.unique' => 'Ese identificador de CRM ya está en otro cliente, y sigue ocupado aunque ese cliente esté dado de baja.',
            'contacts.*.name.required' => 'Cada contacto necesita un nombre. Si no lo vas a rellenar, quita la fila.',
            'contacts.*.email.email' => 'Ese correo de contacto no tiene una forma válida.',
            'fecha_inicio_relacion.date' => 'La fecha de inicio de la relación no es una fecha válida.',
        ];
    }

    /**
     * Quita las filas de contacto **completamente vacías**, antes de validar.
     *
     * «Añadir contacto» mete una fila en blanco, y dejarla sin rellenar es lo que pasa
     * cuando alguien la añade y cambia de idea. No es un error del usuario: es una fila
     * que no dice nada, y lo que hay que hacer con ella es tirarla.
     *
     * **Antes de validar, y ahí está la diferencia**: el filtrado ya existía en
     * `normalizeContacts()`, pero después, o sea cuando la validación ya había
     * rechazado el formulario.
     */
    protected function limpiarContactosVacios(): void
    {
        if (empty($this->contacts)) {
            return;
        }

        $this->contacts = array_values(array_filter(
            $this->contacts,
            // Una fila con algo escrito **sí** se valida: si tiene el correo puesto y
            // el nombre en blanco, eso es un error de verdad y hay que decirlo.
            fn ($contacto) => trim((string) ($contacto['name'] ?? '')) !== ''
                || trim((string) ($contacto['email'] ?? '')) !== ''
                || trim((string) ($contacto['phone'] ?? '')) !== ''
        ));
    }

    /**
     * Filtra y normaliza los contactos antes de guardar
     */
    protected function normalizeContacts(array $validated): array
    {
        // Filtrar contactos vacíos
        if (!empty($validated['contacts'])) {
            $validated['contacts'] = array_filter($validated['contacts'], function($contact) {
                return !empty($contact['name']) || !empty($contact['email']) || !empty($contact['phone']);
            });
            $validated['contacts'] = array_values($validated['contacts']); // Reindexar
        }

        // Si no hay contactos válidos, establecer como null
        if (empty($validated['contacts'])) {
            $validated['contacts'] = null;
        }

        return $validated;
    }

    /**
     * Agrega un nuevo contacto al array
     */
    public function addContact()
    {
        $this->contacts[] = [
            'name' => '',
            'email' => '',
            'phone' => '',
        ];
    }

    /**
     * Elimina un contacto del array
     */
    public function removeContact($index)
    {
        unset($this->contacts[$index]);
        $this->contacts = array_values($this->contacts); // Reindexar array
    }
}

