<?php

namespace App\Support;

use App\Models\Area;
use App\Models\Impresora;
use App\Models\User;

/**
 * Resuelve qué impresora usar según el área del usuario o contexto.
 */
final class ImpresoraResolver
{
    /** Área de respaldo cuando el usuario no tiene area_id (p. ej. recepcionista solo POS). */
    public static function fallbackTicketAreaCode(): string
    {
        return (string) config('lavanderia.pos_ticket_area_code', 'reception');
    }

    /**
     * Impresora de ticket de venta para el usuario autenticado (POS / reimpresión).
     */
    public static function forVentaTicket(?User $user = null, ?int $impresoraId = null): ?Impresora
    {
        if ($impresoraId !== null) {
            return Impresora::query()->whereKey($impresoraId)->where('activa', true)->first();
        }

        if ($user?->area_id !== null) {
            $byUserArea = self::forAreaId((int) $user->area_id, Impresora::TIPO_VENTA);
            if ($byUserArea !== null) {
                return $byUserArea;
            }
        }

        return self::forAreaCode(self::fallbackTicketAreaCode(), Impresora::TIPO_VENTA)
            ?? self::legacyDefault();
    }

    /**
     * Impresora de ticket de venta del POS: siempre el área de recepción (sin área del usuario ni legacy).
     */
    public static function forPosReceptionTicket(?int $impresoraId = null): ?Impresora
    {
        if ($impresoraId !== null) {
            return Impresora::query()->whereKey($impresoraId)->where('activa', true)->first();
        }

        return self::forAreaCode(self::fallbackTicketAreaCode(), Impresora::TIPO_VENTA);
    }

    /**
     * @return array{configured: bool, area_code: string, impresora: array{id: int, nombre: string, nombre_sistema: string}|null}
     */
    public static function posReceptionPrinterStatus(): array
    {
        $impresora = self::forPosReceptionTicket(null);

        return [
            'configured' => $impresora !== null,
            'area_code' => self::fallbackTicketAreaCode(),
            'impresora' => $impresora === null ? null : [
                'id' => (int) $impresora->id,
                'nombre' => (string) $impresora->nombre,
                'nombre_sistema' => (string) $impresora->nombre_sistema,
            ],
        ];
    }

    /** @deprecated Use forVentaTicket() */
    public static function forPosVenta(?int $impresoraId = null): ?Impresora
    {
        return self::forVentaTicket(null, $impresoraId);
    }

    /** @deprecated Use fallbackTicketAreaCode() */
    public static function posTicketAreaCode(): string
    {
        return self::fallbackTicketAreaCode();
    }

    public static function forAreaCode(string $areaCode, ?string $tipoTicket = Impresora::TIPO_VENTA): ?Impresora
    {
        $area = Area::query()->where('code', $areaCode)->first();
        if ($area === null) {
            return null;
        }

        return self::forAreaId((int) $area->id, $tipoTicket);
    }

    public static function forAreaId(int $areaId, ?string $tipoTicket = Impresora::TIPO_VENTA): ?Impresora
    {
        $query = Impresora::query()
            ->where('area_id', $areaId)
            ->where('activa', true);

        if ($tipoTicket !== null) {
            $query->where('tipo_ticket', $tipoTicket);
        }

        return $query
            ->orderByDesc('es_por_defecto')
            ->orderBy('id')
            ->first();
    }

    public static function clearDefaultForArea(int $areaId, ?int $exceptId = null): void
    {
        Impresora::query()
            ->where('area_id', $areaId)
            ->when($exceptId !== null, fn ($q) => $q->where('id', '!=', $exceptId))
            ->update(['es_por_defecto' => false]);
    }

    private static function legacyDefault(): ?Impresora
    {
        return Impresora::query()->where('activa', true)->where('es_por_defecto', true)->first()
            ?? Impresora::query()->where('activa', true)->where('tipo_ticket', Impresora::TIPO_VENTA)->first()
            ?? Impresora::query()->where('activa', true)->first();
    }
}
