<?php

namespace App\Services;

use App\Models\OrdenLavanderia;
use App\Models\OrderAreaScanEvent;
use Illuminate\Support\Collection;

/**
 * Construye payloads de seguimiento (público y autenticado) con eager load y sin N+1.
 */
class LaundryTrackingPresentationService
{
    /**
     * Carga relaciones mínimas para presencia + envío y últimos escaneos (acotado).
     */
    public function loadRelationsForTracking(OrdenLavanderia $orden): void
    {
        $orden->load([
            'areaPresences' => static function ($q): void {
                $q->orderBy('id');
            },
            'areaPresences.area:id,code,name',
            'areaPresences.loadType:id,code,name',
            'shippingOrder',
            'slaTipoServicio:id,code,name',
        ]);
    }

    /**
     * Últimos eventos de escaneo (orden global por fecha, tope configurable).
     *
     * @return Collection<int, OrderAreaScanEvent>
     */
    public function recentScanEventsForOrder(OrdenLavanderia $orden): Collection
    {
        $limit = max(1, (int) config('lavanderia.tracking_recent_scans_limit', 25));

        return OrderAreaScanEvent::query()
            ->where('orden_lavanderia_id', $orden->id)
            ->with(['area:id,code,name'])
            ->orderByDesc('scanned_at')
            ->orderByDesc('id')
            ->limit($limit)
            ->get(['id', 'orden_lavanderia_id', 'area_id', 'scan_sequence', 'scanned_at']);
    }

    /**
     * Serialización pública (sin PII): presencias + envío + escaneos recientes.
     *
     * @return array<string, mixed>
     */
    public function buildPublicDataArray(OrdenLavanderia $orden): array
    {
        $this->loadRelationsForTracking($orden);

        $presences = $orden->areaPresences->map(function ($p) {
            return [
                'area_code' => $p->area?->code,
                'status' => $p->status,
                'started_at' => $p->started_at?->toIso8601String(),
                'completed_at' => $p->completed_at?->toIso8601String(),
            ];
        });

        $shipping = null;
        if ($orden->shippingOrder !== null) {
            $so = $orden->shippingOrder;
            $shipping = [
                'is_delivery' => (bool) $so->is_delivery,
                'delivery_status' => $so->delivery_status,
            ];
        }

        $priority = null;
        if ($orden->slaTipoServicio !== null) {
            $pl = $orden->slaTipoServicio;
            $priority = [
                'code' => $pl->code,
                'name' => $pl->name,
            ];
        }

        $recentScans = $this->recentScanEventsForOrder($orden)->map(function (OrderAreaScanEvent $e) {
            return [
                'area_code' => $e->area?->code,
                'scan_sequence' => $e->scan_sequence,
                'scanned_at' => $e->scanned_at?->toIso8601String(),
            ];
        })->values()->all();

        return [
            'folio_unico' => $orden->folio_unico,
            'estatus' => $orden->estatus,
            'current_step' => $orden->current_step,
            'created_at' => $orden->created_at?->toIso8601String(),
            'entregado_at' => $orden->entregado_at?->toIso8601String(),
            'priority' => $priority,
            'presences' => $presences,
            'shipping' => $shipping,
            'recent_scans' => $recentScans,
        ];
    }

    /**
     * Escaneos recientes para anexar a respuestas ya armadas (presencia API).
     *
     * @return array<int, array{area_code: ?string, scan_sequence: int, scanned_at: ?string}>
     */
    public function recentScansPayload(OrdenLavanderia $orden): array
    {
        return $this->recentScanEventsForOrder($orden)->map(function (OrderAreaScanEvent $e) {
            return [
                'area_code' => $e->area?->code,
                'scan_sequence' => $e->scan_sequence,
                'scanned_at' => $e->scanned_at?->toIso8601String(),
            ];
        })->values()->all();
    }
}
