<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Concerns\DestroysCatalogItem;
use App\Http\Requests\StoreImpresoraRequest;
use App\Http\Requests\UpdateImpresoraRequest;
use App\Models\Area;
use App\Models\Impresora;
use App\Services\ImpresionService;
use App\Support\CatalogCodeGenerator;
use App\Support\ImpresoraResolver;
use App\Support\ThermalLineWidth;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ImpresoraAdminController extends Controller
{
    use DestroysCatalogItem;

    public function __construct(
        private readonly ImpresionService $impresionService,
    ) {}

    public function index(Request $request): JsonResponse
    {
        if (! $request->user()?->can('administracion.areas')) {
            abort(JsonResponse::HTTP_FORBIDDEN);
        }

        $rows = Impresora::query()
            ->with('area:id,code,name,sort_order')
            ->when($request->filled('area_id'), fn ($q) => $q->where('area_id', (int) $request->input('area_id')))
            ->orderBy('area_id')
            ->orderByDesc('es_por_defecto')
            ->orderBy('nombre')
            ->get();

        $areas = Area::query()->orderBy('sort_order')->get(['id', 'code', 'name', 'sort_order', 'is_active']);

        return response()->json([
            'data' => $rows,
            'meta' => [
                'areas' => $areas,
                'fallback_ticket_area_code' => ImpresoraResolver::fallbackTicketAreaCode(),
            ],
            'errors' => null,
        ], JsonResponse::HTTP_OK);
    }

    public function store(StoreImpresoraRequest $request): JsonResponse
    {
        $data = $request->validated();
        $data['codigo'] = CatalogCodeGenerator::resolve(
            $data['codigo'] ?? null,
            $data['nombre'],
            Impresora::class,
            'codigo',
            'imp',
            prefix: 'imp',
        );
        $data['activa'] = $data['activa'] ?? true;
        $data['es_por_defecto'] = $data['es_por_defecto'] ?? false;
        $data['ancho_papel'] = $data['ancho_papel'] ?? 80;
        $data['puerto'] = $data['puerto'] ?? 9100;

        if ($data['es_por_defecto']) {
            ImpresoraResolver::clearDefaultForArea((int) $data['area_id']);
        }

        $row = Impresora::query()->create($data)->load('area:id,code,name,sort_order');

        return response()->json([
            'data' => $row,
            'meta' => null,
            'errors' => null,
        ], JsonResponse::HTTP_CREATED);
    }

    public function update(UpdateImpresoraRequest $request, Impresora $impresora): JsonResponse
    {
        $data = $request->validated();
        $areaId = (int) ($data['area_id'] ?? $impresora->area_id);

        if (! empty($data['es_por_defecto'])) {
            ImpresoraResolver::clearDefaultForArea($areaId, $impresora->id);
        }

        $impresora->fill($data);
        $impresora->save();

        return response()->json([
            'data' => $impresora->fresh()->load('area:id,code,name,sort_order'),
            'meta' => null,
            'errors' => null,
        ], JsonResponse::HTTP_OK);
    }

    public function destroy(Impresora $impresora): JsonResponse
    {
        if (! request()->user()?->can('administracion.areas')) {
            abort(JsonResponse::HTTP_FORBIDDEN);
        }

        return $this->destroyCatalogItem(null, fn () => $impresora->delete());
    }

    public function testPrint(Request $request, Impresora $impresora): JsonResponse
    {
        if (! $request->user()?->can('administracion.areas')) {
            abort(JsonResponse::HTTP_FORBIDDEN);
        }

        $impresora->load('area:id,code,name');

        $result = $this->impresionService->imprimirEscPosLocal(
            $impresora->nombre_sistema,
            $this->buildTestTicketContent($impresora),
            $impresora->tipo_ticket,
            $impresora,
        );

        $ok = (bool) ($result['success'] ?? false);

        return response()->json([
            'success' => $ok,
            'message' => $result['message'] ?? ($result['error'] ?? null),
            'data' => ['impresora_id' => $impresora->id],
            'meta' => null,
            'errors' => $ok ? null : ['impresion' => [$result['error'] ?? 'No se pudo imprimir.']],
        ], $ok ? JsonResponse::HTTP_OK : JsonResponse::HTTP_UNPROCESSABLE_ENTITY);
    }

    private function buildTestTicketContent(Impresora $impresora): string
    {
        $ancho = ThermalLineWidth::charsFromImpresora($impresora);
        $sep = str_repeat('=', $ancho);
        $fecha = now()->timezone(config('app.timezone'))->format('d/m/Y H:i:s');

        return implode("\n", [
            'ControlLavado',
            'TICKET DE PRUEBA',
            $sep,
            'Impresora: '.$impresora->nombre,
            'Sistema: '.$impresora->nombre_sistema,
            'Area: '.($impresora->area?->name ?? '—'),
            'Tipo: '.$impresora->tipo_ticket,
            'Fecha: '.$fecha,
            $sep,
            'Si lee esto, la impresora responde.',
            '',
        ]);
    }
}
