<?php

namespace WMS\Controllers;

use WMS\Core\Request;
use WMS\Core\Response;
use WMS\Middleware\AuthMiddleware;
use WMS\Services\DispatchService;
use WMS\Repositories\DispatchRepository;
use WMS\Helpers\Validator;

class DispatchController
{
    /**
     * POST /api/dispatch
     * Crea un nuevo despacho.
     * Body: { warehouse_id, carrier?, vehicle_plate?, driver_name?, route?, scheduled_date?, notes? }
     */
    public static function create(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))->required(['warehouse_id']);

        if (!$v->passes()) {
            Response::error('Datos inválidos', 422, $v->errors());
            return;
        }

        try {
            $service = new DispatchService();
            $result = $service->createDispatch($body, AuthMiddleware::userId());
            Response::success($result, 'Despacho creado', 201);
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * GET /api/dispatch/{id}
     */
    public static function show(array $params): void
    {
        $repo = new DispatchRepository();
        $doc = $repo->getWithLines((int) $params['id']);
        if (!$doc) {
            Response::error('Despacho no encontrado', 404);
            return;
        }
        Response::success($doc);
    }

    /**
     * GET /api/dispatch/open/{warehouse_id}
     */
    public static function openDispatches(array $params): void
    {
        $repo = new DispatchRepository();
        Response::success($repo->getOpenByWarehouse((int) $params['warehouse_id']));
    }

    /**
     * POST /api/dispatch/{id}/assign
     * Asigna una orden de empaque al despacho.
     * Body: { packing_order_id }
     */
    public static function assignOrder(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))->required(['packing_order_id']);

        if (!$v->passes()) {
            Response::error('Datos inválidos', 422, $v->errors());
            return;
        }

        try {
            $service = new DispatchService();
            $result = $service->assignOrder(
                (int) $params['id'],
                $body,
                AuthMiddleware::userId()
            );
            Response::success($result, 'Orden asignada al despacho');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * POST /api/dispatch/{id}/scan-container
     * Escanea un contenedor para verificación de carga.
     * Body: { container_code }
     */
    public static function scanContainer(array $params): void
    {
        $body = Request::body();

        try {
            $service = new DispatchService();
            $result = $service->scanContainer(
                (int) $params['id'],
                $body,
                AuthMiddleware::userId()
            );
            Response::success($result, 'Contenedor verificado');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * POST /api/dispatch/{id}/close
     * Cierra el despacho y crea DeliveryNotes en SAP si corresponde.
     */
    public static function close(array $params): void
    {
        try {
            $service = new DispatchService();
            $result = $service->closeDispatch(
                (int) $params['id'],
                AuthMiddleware::userId()
            );
            Response::success($result, 'Despacho cerrado');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * GET /api/dispatch/{id}/packing-list
     * Genera el packing list del despacho con items agrupados por cliente.
     */
    public static function packingList(array $params): void
    {
        try {
            $service = new DispatchService();
            $result = $service->generatePackingList((int) $params['id']);
            Response::success($result, 'Packing list generado');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }
}
