<?php

namespace App\Services;

use App\Models\Attendee;
use App\Models\Order;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;
use Illuminate\Support\Facades\File;

/**
 * Genera archivos PNG de códigos QR para el correo de confirmación de compra.
 *
 * Por qué archivos en disco y no base64 en el HTML del correo:
 * - Muchos clientes de correo truncan o rompen URLs data:image muy largas.
 * - Los PNG se sirven desde `public/` y el correo solo incluye `<img src="https://...">`.
 *
 * Librería: Endroid QR Code con escritor PNG basado en GD (no depende de Imagick).
 *
 * Estructura de rutas:
 * - `public/images/qr/{user_id}/attendee-{id}.png` si la orden tiene usuario.
 * - `public/images/qr/guest-order-{order_id}/...` si la orden aún no tenía usuario al generar (caso residual).
 *
 * @todo Limpieza periódica de PNG antiguos si el disco crece (job programado o política de retención).
 */
final class OrderConfirmationQrImageService
{
    /**
     * Genera un PNG por cada asistente de la orden y devuelve las URLs públicas para la vista del correo.
     *
     * @return array<int, string> Mapa attendee id => URL absoluta (helper `asset()`).
     */
    public function publicUrlsForOrder(Order $order): array
    {
        $urls = [];
        foreach ($order->attendees as $attendee) {
            $urls[$attendee->id] = $this->writePngAndUrl($order, $attendee);
        }

        return $urls;
    }

    /**
     * Codifica el `security_code` del asistente en QR, guarda el PNG y devuelve la URL pública.
     *
     * Sobrescribe el archivo si ya existe (mismo comprador reenvía correo).
     */
    public function writePngAndUrl(Order $order, Attendee $attendee): string
    {
        $relative = $this->relativePath($order, $attendee);
        $fullPath = public_path($relative);
        File::makeDirectory(\dirname($fullPath), 0755, true, true);

        $qrCode = QrCode::create((string) $attendee->security_code)
            ->setSize(200)
            ->setMargin(2);

        $writer = new PngWriter;
        $result = $writer->write($qrCode);
        File::put($fullPath, $result->getString());

        return asset(str_replace(\DIRECTORY_SEPARATOR, '/', $relative));
    }

    /**
     * Ruta relativa desde la carpeta `public/` hasta el archivo PNG del QR.
     */
    private function relativePath(Order $order, Attendee $attendee): string
    {
        $folder = $order->user_id !== null
            ? (string) $order->user_id
            : 'guest-order-'.$order->id;

        return 'images/qr/'.$folder.'/attendee-'.$attendee->id.'.png';
    }
}
