<?php

namespace WMS\Controllers;

use WMS\Core\Request;
use WMS\Core\Response;
use WMS\Helpers\Validator;
use WMS\Repositories\BinRepository;

class BinController
{
    /**
     * GET /api/warehouses/{warehouse_id}/bins
     * Query: ?bin_type=STORAGE&zone_id=5&active=1&q=texto
     */
    public static function index(array $params): void
    {
        $repo = new BinRepository();
        $filters = [
            'bin_type' => Request::query('bin_type'),
            'zone_id'  => Request::query('zone_id'),
            'active'   => Request::query('active'),
            'q'        => Request::query('q'),
        ];
        $bins = $repo->getByWarehouseFiltered((int) $params['warehouse_id'], $filters);
        Response::success($bins);
    }

    /**
     * GET /api/bins
     * Listado global con filtros (todos los almacenes).
     */
    public static function listAll(array $params): void
    {
        $repo = new BinRepository();
        $filters = [
            'warehouse_id' => Request::query('warehouse_id'),
            'bin_type'     => Request::query('bin_type'),
            'zone_id'      => Request::query('zone_id'),
            'active'       => Request::query('active'),
            'q'            => Request::query('q'),
        ];
        Response::success($repo->listAll($filters));
    }

    /**
     * GET /api/bins/{id}
     */
    public static function show(array $params): void
    {
        $repo = new BinRepository();
        $bin = $repo->findByIdFull((int) $params['id']);
        if (!$bin) {
            Response::error('Ubicacion no encontrada', 404);
            return;
        }
        Response::success($bin);
    }

    /**
     * POST /api/bins
     */
    public static function create(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))->required(['warehouse_id', 'code']);
        if (!$v->passes()) {
            Response::error('Datos invalidos', 422, $v->errors());
            return;
        }
        try {
            $repo = new BinRepository();
            $id = $repo->insert([
                'warehouse_id'  => (int) $body['warehouse_id'],
                'zone_id'       => isset($body['zone_id']) && $body['zone_id'] !== '' ? (int) $body['zone_id'] : null,
                'code'          => trim((string) $body['code']),
                'aisle'         => $body['aisle']    ?? null,
                'rack'          => $body['rack']     ?? null,
                'level'         => $body['level']    ?? null,
                'position'      => $body['position'] ?? null,
                'bin_type'      => $body['bin_type'] ?? 'STORAGE',
                'max_weight_kg' => isset($body['max_weight_kg']) && $body['max_weight_kg'] !== '' ? $body['max_weight_kg'] : null,
                'max_volume_m3' => isset($body['max_volume_m3']) && $body['max_volume_m3'] !== '' ? $body['max_volume_m3'] : null,
                'is_active'     => isset($body['is_active']) ? (int) (bool) $body['is_active'] : 1,
                'sap_bin_code'  => $body['sap_bin_code'] ?? null,
            ]);
            $bin = $repo->findById($id);
            Response::success($bin, 'Ubicacion creada');
        } catch (\PDOException $e) {
            if ($e->getCode() == 23000) {
                Response::error('Codigo duplicado dentro del almacen', 409);
                return;
            }
            Response::error('Error al crear ubicacion: ' . $e->getMessage(), 500);
        } catch (\Throwable $e) {
            Response::error('Error al crear ubicacion: ' . $e->getMessage(), 500);
        }
    }

    /**
     * PUT /api/bins/{id}
     */
    public static function update(array $params): void
    {
        $id = (int) ($params['id'] ?? 0);
        if ($id <= 0) { Response::error('id invalido', 422); return; }
        $body = Request::body();
        try {
            $repo = new BinRepository();
            $existing = $repo->findById($id);
            if (!$existing) { Response::error('Ubicacion no encontrada', 404); return; }
            $repo->updateById($id, $body);
            Response::success($repo->findById($id), 'Ubicacion actualizada');
        } catch (\PDOException $e) {
            if ($e->getCode() == 23000) {
                Response::error('Codigo duplicado dentro del almacen', 409);
                return;
            }
            Response::error('Error al actualizar ubicacion: ' . $e->getMessage(), 500);
        } catch (\Throwable $e) {
            Response::error('Error al actualizar ubicacion: ' . $e->getMessage(), 500);
        }
    }

    /**
     * DELETE /api/bins/{id}
     * Soft delete: is_active=0. Si tiene stock referenciado, se rechaza.
     */
    public static function delete(array $params): void
    {
        $id = (int) ($params['id'] ?? 0);
        if ($id <= 0) { Response::error('id invalido', 422); return; }
        try {
            $repo = new BinRepository();
            $bin = $repo->findById($id);
            if (!$bin) { Response::error('Ubicacion no encontrada', 404); return; }
            if ($repo->hasActiveStock($id)) {
                Response::error('No se puede desactivar: la ubicacion tiene stock asignado.', 409);
                return;
            }
            $repo->setActive($id, false);
            Response::success(null, 'Ubicacion desactivada');
        } catch (\Throwable $e) {
            Response::error('Error al desactivar ubicacion: ' . $e->getMessage(), 500);
        }
    }
}
