<?php

namespace WMS\Controllers;

use WMS\Core\Request;
use WMS\Core\Response;
use WMS\Middleware\AuthMiddleware;
use WMS\Services\PutawayService;
use WMS\Helpers\Validator;
use WMS\Core\Database;

class PutawayController
{
    /**
     * GET /api/putaway/stats?warehouse_id=X&days=30
     * KPIs de putaway: distribución por estrategia, override rate, top bins, volumen.
     */
    public static function stats(array $params): void
    {
        try {
            $db = Database::getConnection();
            $wh = (int)(Request::query('warehouse_id') ?? 0);
            $days = max(1, min(365, (int)(Request::query('days') ?? 30)));

            $whereWh    = $wh ? "AND warehouse_id = {$wh}" : '';
            $whereWhWt  = $wh ? "AND wt.warehouse_id = {$wh}" : '';

            // KPIs
            $kpis = $db->query(
                "SELECT
                  SUM(status = 'COMPLETED') AS completed,
                  SUM(status = 'PENDING')   AS pending,
                  SUM(status = 'ASSIGNED')  AS assigned,
                  SUM(status = 'IN_PROGRESS') AS in_progress,
                  COUNT(*) AS total
                 FROM warehouse_tasks
                 WHERE task_type = 'PUTAWAY' {$whereWh}"
            )->fetch();

            // Distribución por estrategia (últimos N días, completed)
            $byStrategy = $db->query(
                "SELECT COALESCE(putaway_strategy, 'UNTRACKED') AS strategy, COUNT(*) AS cnt
                 FROM warehouse_tasks
                 WHERE task_type = 'PUTAWAY' AND status = 'COMPLETED'
                   AND completed_at >= (NOW() - INTERVAL {$days} DAY)
                   {$whereWh}
                 GROUP BY putaway_strategy ORDER BY cnt DESC"
            )->fetchAll();

            $totalPeriod = array_sum(array_column($byStrategy, 'cnt')) ?: 1;

            // Override rate: tasks con strategy=OVERRIDE / completados en período
            $overrideCount = (int)($db->query(
                "SELECT COUNT(*) FROM warehouse_tasks
                 WHERE task_type='PUTAWAY' AND status='COMPLETED'
                   AND putaway_strategy='OVERRIDE'
                   AND completed_at >= (NOW() - INTERVAL {$days} DAY)
                   {$whereWh}"
            )->fetchColumn());

            // Top 10 bins más usados como destino
            $topBins = $db->query(
                "SELECT b.code AS bin_code, COUNT(*) AS uses
                 FROM warehouse_tasks wt
                 JOIN bins b ON b.id = wt.to_bin_id
                 WHERE wt.task_type = 'PUTAWAY' AND wt.status = 'COMPLETED'
                   AND wt.completed_at >= (NOW() - INTERVAL {$days} DAY)
                   {$whereWhWt}
                 GROUP BY wt.to_bin_id, b.code
                 ORDER BY uses DESC LIMIT 10"
            )->fetchAll();

            // Top operadores
            $topOperators = $db->query(
                "SELECT u.username, u.full_name, COUNT(*) AS cnt
                 FROM warehouse_tasks wt
                 LEFT JOIN users u ON u.id = wt.assigned_to
                 WHERE wt.task_type='PUTAWAY' AND wt.status='COMPLETED'
                   AND wt.completed_at >= (NOW() - INTERVAL {$days} DAY)
                   {$whereWhWt}
                 GROUP BY wt.assigned_to, u.username, u.full_name
                 ORDER BY cnt DESC LIMIT 5"
            )->fetchAll();

            Response::success([
                'days'           => $days,
                'warehouse_id'   => $wh ?: null,
                'totals'         => $kpis,
                'by_strategy'    => array_map(fn($r) => $r + ['pct' => round($r['cnt'] * 100 / $totalPeriod, 1)], $byStrategy),
                'override_rate'  => round($overrideCount * 100 / $totalPeriod, 1),
                'override_count' => $overrideCount,
                'top_bins'       => $topBins,
                'top_operators'  => $topOperators,
            ]);
        } catch (\Throwable $e) {
            Response::error('Error: ' . $e->getMessage(), 500);
        }
    }

    /**
     * POST /api/putaway/grouped
     * Putaway de toda una etiqueta de transferencia a un solo bin.
     * Body: { label_id, to_bin_id }
     */
    public static function grouped(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))->required(['label_id', 'to_bin_id']);

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

        try {
            $service = new PutawayService();
            $result = $service->groupedPutaway(
                (int) $body['label_id'],
                (int) $body['to_bin_id'],
                AuthMiddleware::userId()
            );
            Response::success($result, 'Putaway agrupado completado');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * GET /api/putaway/suggest/{item_id}?warehouse_id=
     * Sugiere el mejor bin para guardar un artículo.
     */
    public static function suggest(array $params): void
    {
        $warehouseId = Request::query('warehouse_id');
        if (!$warehouseId) {
            Response::error('warehouse_id es requerido', 422);
            return;
        }

        try {
            $service = new PutawayService();
            $result = $service->suggestBin(
                (int) $params['item_id'],
                (int) $warehouseId
            );
            Response::success($result, 'Sugerencia de ubicación');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * POST /api/putaway/by-location
     * Mueve todo el stock de un bin a otro.
     * Body: { from_bin_id, to_bin_id }
     */
    public static function byLocation(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))->required(['from_bin_id', 'to_bin_id']);

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

        try {
            $service = new PutawayService();
            $result = $service->putawayByLocation(
                (int) $body['from_bin_id'],
                (int) $body['to_bin_id'],
                AuthMiddleware::userId()
            );
            Response::success($result, 'Putaway por ubicación completado');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * POST /api/putaway/free
     * Modo libre: mover un item/cantidad específico entre bins.
     * Body: { item_id, batch_id?, from_bin_id, to_bin_id, quantity }
     */
    public static function free(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))
            ->required(['item_id', 'from_bin_id', 'to_bin_id', 'quantity'])
            ->positiveNumber('quantity');

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

        try {
            $service = new PutawayService();
            $result = $service->freePutaway($body, AuthMiddleware::userId());
            Response::success($result, 'Putaway libre completado');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * POST /api/putaway
     * Crea tarea de putaway manual.
     * Body: { warehouse_id, item_id, batch_id?, from_bin_id, quantity }
     */
    public static function create(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))
            ->required(['warehouse_id', 'item_id', 'from_bin_id', 'quantity'])
            ->positiveNumber('quantity');

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

        try {
            $service = new PutawayService();
            $taskId = $service->createPutawayTask(
                (int) $body['warehouse_id'],
                (int) $body['item_id'],
                isset($body['batch_id']) ? (int) $body['batch_id'] : null,
                (int) $body['from_bin_id'],
                (float) $body['quantity'],
                null,
                AuthMiddleware::userId()
            );
            Response::success(['task_id' => $taskId], 'Tarea de putaway creada', 201);
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }

    /**
     * POST /api/putaway/{task_id}/confirm
     * Confirma putaway.
     * Body: { to_bin_id, confirmed_qty? }
     */
    public static function confirm(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))->required(['to_bin_id']);

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

        try {
            $service = new PutawayService();
            $result = $service->confirmPutaway(
                (int) $params['task_id'],
                $body,
                AuthMiddleware::userId()
            );
            Response::success($result, 'Putaway confirmado');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage());
        }
    }
}
