<?php

namespace App\Support;

use App\Models\OrdenLavanderia;
use App\Models\OrdenLavanderiaBolsa;

/**
 * Resuelve una orden a partir de lo que envía un lector (folio, codigo_qr, URL, bolsa LMSB…).
 */
final class LaundryScanResolver
{
    public static function barcodePayloadForOrder(OrdenLavanderia $orden): string
    {
        return LaundryScanCode::barcodePayload((string) ($orden->folio_unico ?? ''));
    }

    public static function findOrden(string $raw): ?OrdenLavanderia
    {
        $input = LaundryScanInput::normalize($raw);
        if ($input === '') {
            return null;
        }

        $bolsa = self::findBolsa($input);
        if ($bolsa !== null) {
            return OrdenLavanderia::query()->find($bolsa->orden_lavanderia_id);
        }

        $folioFromPayload = self::folioFromStoredQrPayload($input);
        if ($folioFromPayload !== null) {
            $byFolio = self::findOrdenByFolio($folioFromPayload);
            if ($byFolio !== null) {
                return $byFolio;
            }
        }

        return self::findOrdenByFolio($input);
    }

    public static function findOrdenByFolio(string $folio): ?OrdenLavanderia
    {
        $folio = trim($folio);
        if ($folio === '') {
            return null;
        }

        foreach (LaundryScanCode::lookupCandidates($folio) as $candidate) {
            $orden = OrdenLavanderia::query()->where('folio_unico', $candidate)->first();
            if ($orden !== null) {
                return $orden;
            }
        }

        $compact = LaundryScanCode::compact($folio);
        if ($compact === '') {
            return null;
        }

        return OrdenLavanderia::query()
            ->whereRaw("REPLACE(REPLACE(folio_unico, '-', ''), ' ', '') = ?", [$compact])
            ->orWhere('codigo_qr', $folio)
            ->first();
    }

    private static function findBolsa(string $input): ?OrdenLavanderiaBolsa
    {
        foreach (LaundryScanCode::lookupCandidates($input) as $candidate) {
            $bolsa = OrdenLavanderiaBolsa::query()->where('codigo', $candidate)->first();
            if ($bolsa !== null) {
                return $bolsa;
            }
        }

        $compact = LaundryScanCode::compact($input);
        if ($compact === '') {
            return null;
        }

        return OrdenLavanderiaBolsa::query()
            ->whereRaw("REPLACE(REPLACE(codigo, '-', ''), ' ', '') = ?", [$compact])
            ->first();
    }

    /**
     * Decodifica codigo_qr legacy (base64 JSON con clave folio).
     */
    public static function folioFromStoredQrPayload(string $input): ?string
    {
        $decoded = base64_decode($input, true);
        if ($decoded === false || $decoded === '') {
            return null;
        }

        $json = json_decode($decoded, true);
        if (! is_array($json) || empty($json['folio'])) {
            return null;
        }

        return trim((string) $json['folio']);
    }
}
