<?php

namespace App\Http\Requests;

use App\Http\Controllers\CheckoutController;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

/**
 * Validación HTTP del primer paso del checkout público (crear orden pendiente + asistentes).
 *
 * Payload esperado (JSON o form):
 * - `attendees`: matriz por tipo de entrada → filas de asistentes con nombre, email y metadatos de custom fields.
 * - `checkout_email`: obligatorio solo si el visitante **no** está autenticado; identifica la cuenta RegiTicket post-pago.
 * - `idempotency_key`: opcional; el frontend envía una clave por carga para evitar órdenes duplicadas por doble envío.
 *
 * Nota: Las reglas de custom fields **requeridos** por ticket no están aquí; las aplica
 * {@see CheckoutController::store()} porque necesita el modelo `TicketType` en servidor.
 *
 * @todo Si se añaden más campos de facturación (NIF, dirección), centralizar reglas aquí o en un FormRequest hijo.
 */
class StoreCheckoutOrderRequest extends FormRequest
{
    /**
     * El checkout público no exige usuario logueado.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Reglas de validación estáticas del payload.
     *
     * `checkout_email`: con invitado es obligatorio (Rule::requiredIf); con sesión se rellena en
     * {@see prepareForValidation()} con el email del usuario si el cliente no lo envía explícito.
     */
    public function rules(): array
    {
        return [
            'idempotency_key' => ['nullable', 'string', 'max:64'],
            'checkout_email' => [
                Rule::requiredIf(fn () => $this->user() === null),
                'nullable',
                'string',
                'email:rfc',
                'max:160',
            ],
            'attendees' => ['required', 'array', 'min:1'],
            'attendees.*' => ['array'],
            'attendees.*.*.holder_name' => ['nullable', 'string', 'max:120'],
            'attendees.*.*.holder_email' => ['nullable', 'email:rfc', 'max:160'],
            'attendees.*.*.meta' => ['nullable', 'array'],
            'attendees.*.*.meta.*' => ['nullable', 'string', 'max:500'],
        ];
    }

    /**
     * Mensajes personalizados para errores de validación (UX en español).
     */
    public function messages(): array
    {
        return [
            'attendees.required' => __('Debes seleccionar al menos una entrada.'),
            'checkout_email.required' => __('Indica el correo con el que quieres acceder a tus entradas.'),
            'checkout_email.email' => __('El correo de compra no es válido.'),
            'attendees.*.*.holder_email.email' => __('El correo electrónico no es válido.'),
        ];
    }

    /**
     * Normaliza `checkout_email` antes de validar:
     * - Usuario logueado: si no mandó campo, se usa su email de cuenta (minúsculas).
     * - Invitado: recorta y pasa a minúsculas para comparaciones consistentes en BD.
     */
    protected function prepareForValidation(): void
    {
        $raw = $this->input('checkout_email');
        if ($this->user() !== null) {
            $merged = is_string($raw) && trim($raw) !== ''
                ? strtolower(trim($raw))
                : strtolower(trim((string) $this->user()->email));
            $this->merge(['checkout_email' => $merged]);
        } elseif (is_string($raw)) {
            $this->merge(['checkout_email' => strtolower(trim($raw))]);
        }
    }

    /**
     * Transforma el array `attendees` validado en una estructura lista para persistir asistentes.
     *
     * @return array<int, array<int, array{holder_name: string, holder_email: string, meta: array<string, mixed>}>>
     */
    public function attendeesPayload(): array
    {
        $payload = $this->validated()['attendees'] ?? [];
        $clean = [];

        foreach ($payload as $ticketId => $rows) {
            $ticketId = (int) $ticketId;
            if ($ticketId <= 0 || ! is_array($rows)) {
                continue;
            }

            foreach ($rows as $row) {
                if (! is_array($row)) {
                    continue;
                }

                $clean[$ticketId][] = [
                    'holder_name' => trim((string) ($row['holder_name'] ?? '')),
                    'holder_email' => trim((string) ($row['holder_email'] ?? '')),
                    'meta' => is_array($row['meta'] ?? null) ? $row['meta'] : [],
                ];
            }
        }

        return $clean;
    }
}
