<?php Session::init(); ?>
<?php

class Produccion_Model extends Model
{
    private $detalleResponsableDisponible = null;

    public function __construct()
    {
        parent::__construct();
    }

    private function detallePedidoTieneResponsableOperativo(): bool
    {
        if ($this->detalleResponsableDisponible !== null) {
            return $this->detalleResponsableDisponible;
        }

        try {
            $stm = $this->db->prepare("SHOW COLUMNS FROM tm_detalle_pedido LIKE 'id_responsable'");
            $stm->execute();
            $this->detalleResponsableDisponible = (bool) $stm->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            $this->detalleResponsableDisponible = false;
        }

        return $this->detalleResponsableDisponible;
    }

    private function buildDetalleResponsableKey($item): string
    {
        $idPedido = isset($item->id_pedido) ? (int) $item->id_pedido : 0;
        $idPres = isset($item->id_pres) ? (int) $item->id_pres : 0;
        $fechaPedido = isset($item->fecha_pedido) ? (string) $item->fecha_pedido : '';
        $comentario = isset($item->comentario) ? trim((string) $item->comentario) : '';

        return $idPedido . '|' . $idPres . '|' . $fechaPedido . '|' . $comentario;
    }

    private function hidratarResponsablesDetalle(array $items): array
    {
        if (empty($items)) {
            return $items;
        }

        $usaCampoResponsable = $this->detallePedidoTieneResponsableOperativo();
        $campoResponsableSql = $usaCampoResponsable
            ? "COALESCE(dp.id_responsable, dp.id_usu)"
            : "dp.id_usu";

        $pedidoIds = [];
        foreach ($items as $item) {
            $idPedido = isset($item->id_pedido) ? (int) $item->id_pedido : 0;
            if ($idPedido > 0) {
                $pedidoIds[$idPedido] = $idPedido;
            }
        }

        if (empty($pedidoIds)) {
            return $items;
        }

        $placeholders = implode(',', array_fill(0, count($pedidoIds), '?'));
        $sql = "SELECT 
                    dp.id_pedido,
                    dp.id_pres,
                    dp.fecha_pedido,
                    COALESCE(dp.comentario, '') AS comentario,
                    {$campoResponsableSql} AS id_responsable,
                    COALESCE(tu.nombres, '') AS nombres,
                    COALESCE(tu.ape_paterno, '') AS ape_paterno,
                    COALESCE(tu.ape_materno, '') AS ape_materno
                FROM tm_detalle_pedido dp
                LEFT JOIN tm_usuario tu ON tu.id_usu = {$campoResponsableSql}
                WHERE dp.id_pedido IN ($placeholders)
                  AND dp.estado <> 'z'";

        $stm = $this->db->prepare($sql);
        $stm->execute(array_values($pedidoIds));
        $rows = $stm->fetchAll(PDO::FETCH_OBJ);

        $responsables = [];
        foreach ($rows as $row) {
            $key = $this->buildDetalleResponsableKey($row);
            $responsables[$key] = $row;
        }

        foreach ($items as $index => $item) {
            $key = $this->buildDetalleResponsableKey($item);
            if (!isset($responsables[$key])) {
                continue;
            }

            $items[$index]->id_responsable = $responsables[$key]->id_responsable;
            $items[$index]->nombres = $responsables[$key]->nombres;
            $items[$index]->ape_paterno = $responsables[$key]->ape_paterno;
            $items[$index]->ape_materno = $responsables[$key]->ape_materno;
        }

        return $items;
    }

    private function obtenerMapaCategoriasPorPresentacion(array $items): array
    {
        if (empty($items)) {
            return [];
        }

        $presentaciones = [];
        foreach ($items as $item) {
            $idPres = isset($item->id_pres) ? (int) $item->id_pres : 0;
            if ($idPres > 0) {
                $presentaciones[$idPres] = $idPres;
            }
        }

        if (empty($presentaciones)) {
            return [];
        }

        $placeholders = implode(',', array_fill(0, count($presentaciones), '?'));
        $sql = "SELECT id_pres, pro_cat FROM v_productos WHERE id_pres IN ($placeholders)";
        $stm = $this->db->prepare($sql);
        $stm->execute(array_values($presentaciones));
        $rows = $stm->fetchAll(PDO::FETCH_ASSOC);

        $mapaCategorias = [];
        foreach ($rows as $row) {
            $idPres = (int) $row['id_pres'];
            if (!isset($mapaCategorias[$idPres])) {
                $mapaCategorias[$idPres] = (object) ['pro_cat' => $row['pro_cat']];
            }
        }

        return $mapaCategorias;
    }

    private function hidratarCategoriasProducto(array $items): array
    {
        if (empty($items)) {
            return $items;
        }

        $mapaCategorias = $this->obtenerMapaCategoriasPorPresentacion($items);
        $categoriaDefault = (object) ['pro_cat' => ''];

        foreach ($items as $indice => $item) {
            $idPres = isset($item->id_pres) ? (int) $item->id_pres : 0;
            $items[$indice]->Producto = $mapaCategorias[$idPres] ?? $categoriaDefault;
        }

        return $items;
    }

    private function construirTotalPendienteDesdeLista(array $items): object
    {
        $total = count($items);
        return (object) ['nro_p' => $total > 0 ? $total : ''];
    }

    private function asignarTotalPendientePorLista(array $items): array
    {
        if (empty($items)) {
            return $items;
        }

        $totalPendiente = $this->construirTotalPendienteDesdeLista($items);
        foreach ($items as $indice => $item) {
            $items[$indice]->Total = clone $totalPendiente;
        }

        return $items;
    }

    private function enriquecerListaCanal(array $items): array
    {
        if (empty($items)) {
            return $items;
        }

        $items = $this->hidratarCategoriasProducto($items);
        return $this->asignarTotalPendientePorLista($items);
    }

    public function mesas_list()
    {
        try
        {   
            $id_areap = Session::get('areaid');
            $stm = $this->db->prepare("SELECT * FROM v_pedidos_agrupados WHERE id_areap = ? AND tipo_atencion = 1 AND estado_pedido <> 'd' AND estado_pedido <> 'z' AND (estado = 'a' OR estado = 'b') ORDER BY fecha_pedido ASC");
            $stm->execute(array($id_areap));
            $c = $stm->fetchAll(PDO::FETCH_OBJ);
            $c = $this->enriquecerListaCanal($c);
            $c = $this->hidratarResponsablesDetalle($c);
            return $c;   
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function mostrador_list()
    {
        try
        {        
            $id_areap = Session::get('areaid');
            
            $stm = $this->db->prepare("SELECT * FROM v_pedidos_agrupados WHERE id_areap = ? AND tipo_atencion = 2 AND estado_pedido <> 'd' AND estado_pedido <> 'z' AND (estado = 'a' OR estado = 'b') ORDER BY fecha_pedido ASC");
            $stm->execute(array($id_areap));
            $c = $stm->fetchAll(PDO::FETCH_OBJ);
            $c = $this->enriquecerListaCanal($c);
            $c = $this->hidratarResponsablesDetalle($c);
            return $c;     
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function delivery_list()
    {
        try
        {        
            $id_areap = Session::get('areaid');
            
            $stm = $this->db->prepare("SELECT * FROM v_pedidos_agrupados WHERE id_areap = ? AND tipo_atencion = 3 AND estado_pedido <> 'd' AND estado_pedido <> 'z' AND (estado = 'a' OR estado = 'b' OR estado = 'y') ORDER BY fecha_pedido ASC");
            $stm->execute(array($id_areap));
            $c = $stm->fetchAll(PDO::FETCH_OBJ);
            $c = $this->enriquecerListaCanal($c);
            $c = $this->hidratarResponsablesDetalle($c);
            return $c;        
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function panel_data()
    {
        try
        {
            $id_areap = Session::get('areaid');
            $sql = "SELECT *
                    FROM v_pedidos_agrupados
                    WHERE id_areap = ?
                      AND estado_pedido <> 'd'
                      AND estado_pedido <> 'z'
                      AND (
                            (tipo_atencion = 1 AND (estado = 'a' OR estado = 'b'))
                         OR (tipo_atencion = 2 AND (estado = 'a' OR estado = 'b'))
                         OR (tipo_atencion = 3 AND (estado = 'a' OR estado = 'b' OR estado = 'y'))
                      )
                    ORDER BY fecha_pedido ASC";

            $stm = $this->db->prepare($sql);
            $stm->execute([$id_areap]);
            $items = $stm->fetchAll(PDO::FETCH_OBJ);

            $items = $this->hidratarCategoriasProducto($items);
            $items = $this->hidratarResponsablesDetalle($items);

            $canales = [
                'mesa' => [],
                'mostrador' => [],
                'delivery' => []
            ];

            foreach ($items as $item) {
                $tipoAtencion = isset($item->tipo_atencion) ? (int) $item->tipo_atencion : 0;
                if ($tipoAtencion === 1) {
                    $canales['mesa'][] = $item;
                    continue;
                }

                if ($tipoAtencion === 2) {
                    $canales['mostrador'][] = $item;
                    continue;
                }

                if ($tipoAtencion === 3) {
                    $canales['delivery'][] = $item;
                }
            }

            $canales['mesa'] = $this->asignarTotalPendientePorLista($canales['mesa']);
            $canales['mostrador'] = $this->asignarTotalPendientePorLista($canales['mostrador']);
            $canales['delivery'] = $this->asignarTotalPendientePorLista($canales['delivery']);

            return $canales;
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function agrupacion_platos_list()
    {
        try
        {        
            $id_areap = Session::get('areaid');
            $stm = $this->db->prepare("SELECT nombre_prod, pres_prod, MIN(fecha_pedido) FROM v_pedidos_agrupados WHERE id_areap = ? AND estado_pedido <> 'd' AND estado_pedido <> 'z' AND (estado = 'a' OR estado = 'b') GROUP BY nombre_prod,pres_prod ORDER BY fecha_pedido ASC");
            $stm->execute(array($id_areap));
            $c = $stm->fetchAll(PDO::FETCH_OBJ);
            return $c;
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function agrupacion_platos_detalle($data)
    {
        try
        {        
            $id_areap = Session::get('areaid');
            $stm = $this->db->prepare("SELECT * FROM v_pedidos_agrupados WHERE id_areap = ? AND nombre_prod = ? AND pres_prod = ? AND estado_pedido <> 'd' AND estado_pedido <> 'z' AND (estado = 'a' OR estado = 'b') ORDER BY fecha_pedido ASC");
            $stm->execute(array($id_areap,$data['nombre_prod'],$data['pres_prod']));
            $c = $stm->fetchAll(PDO::FETCH_OBJ);
            $c = $this->hidratarCategoriasProducto($c);
            $c = $this->hidratarResponsablesDetalle($c);
            return $c;
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function agrupacion_pedidos_list()
    {
        try
        {        
            $id_areap = Session::get('areaid');
            $stm = $this->db->prepare("SELECT id_pedido,id_areap,tipo_atencion,nro_mesa,desc_salon,MIN(fecha_pedido) FROM v_pedidos_agrupados WHERE id_areap = ? AND estado_pedido <> 'd' AND estado_pedido <> 'z' AND (estado = 'a' OR estado = 'b') GROUP BY id_pedido ORDER BY fecha_pedido ASC");
            $stm->execute(array($id_areap));
            $c = $stm->fetchAll(PDO::FETCH_OBJ);
            
            return $c;
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function agrupacion_pedidos_detalle($data)
    {
        try
        {        
            $id_areap = Session::get('areaid');
            $stm = $this->db->prepare("SELECT * FROM v_pedidos_agrupados WHERE id_areap = ? AND id_pedido = ? AND estado_pedido <> 'd' AND estado_pedido <> 'z' AND (estado = 'a' OR estado = 'b') ORDER BY fecha_pedido ASC");
            $stm->execute(array($id_areap,$data['id_pedido']));
            $c = $stm->fetchAll(PDO::FETCH_OBJ);
            $c = $this->hidratarCategoriasProducto($c);
            $c = $this->hidratarResponsablesDetalle($c);
            return $c;
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function preparacion($data)
    {
        try
        {   
            date_default_timezone_set($_SESSION["zona_horaria"]);
            setlocale(LC_ALL,"es_ES@euro","es_ES","esp");
            $fecha = date("Y-m-d H:i:s");
            $sql = "UPDATE tm_detalle_pedido SET estado = 'b', fecha_envio = ? WHERE id_pedido = ? AND id_pres = ? AND fecha_pedido = ? AND estado IN ('a','y')";
            $this->db->prepare($sql)
              ->execute(array(
                $fecha,
                $data['cod_ped'],
                $data['cod_prod'],
                $data['fecha_p']
                ));
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    public function atendido($data)
    {
        try
        {   
            date_default_timezone_set($_SESSION["zona_horaria"]);
            setlocale(LC_ALL,"es_ES@euro","es_ES","esp");
            $fecha = date("Y-m-d H:i:s");
            $sql = "UPDATE tm_detalle_pedido SET estado = 'c', fecha_envio = ? WHERE id_pedido = ? AND id_pres = ? AND fecha_pedido = ? AND estado IN ('a','b','y')";
            $this->db->prepare($sql)
              ->execute(array(
                $fecha,
                $data['cod_ped'],
                $data['cod_prod'],
                $data['fecha_p']
                ));
        }
        catch(Exception $e)
        {
            die($e->getMessage());
        }
    }

    // public function atendidopormesa($data)
    // {
    //     try
    //     {   
    //         date_default_timezone_set($_SESSION["zona_horaria"]);
    //         setlocale(LC_ALL,"es_ES@euro","es_ES","esp");
    //         $fecha = date("Y-m-d H:i:s");
    //         $sql = "UPDATE tm_detalle_pedido SET estado = 'c', fecha_envio = ? WHERE id_pedido = ?";
    //         $this->db->prepare($sql)
    //           ->execute(array(
    //             $fecha,
    //             $data['cod_ped']
    //             ));
    //     }
    //     catch(Exception $e)
    //     {
    //         die($e->getMessage());
    //     }
    // }

    public function atendidopormesa(array $data)
{
    try {
        // 0) Asegúrate de recibir también el id_areap en $data
        if (empty($data['cod_ped']) || empty($data['id_areap'])) {
            return 0;
        }

        // 1) Fecha y zona horaria
        date_default_timezone_set($_SESSION["zona_horaria"]);
        setlocale(LC_ALL, "es_ES@euro","es_ES","esp");
        $fecha = date("Y-m-d H:i:s");

        // 2) Update con JOINs para filtrar sólo los productos de esa área
        $sql = "
            UPDATE tm_detalle_pedido AS dp
              JOIN tm_producto_pres   AS pp ON dp.id_pres = pp.id_pres
              JOIN tm_producto        AS p  ON pp.id_prod = p.id_prod
            SET
              dp.estado     = 'c',
              dp.fecha_envio = ?
            WHERE
              dp.id_pedido = ?
              AND p.id_areap = ?
              AND dp.estado IN ('a','b','y')
        ";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([
            $fecha,
            $data['cod_ped'],
            $data['id_areap']
        ]);

        // Opcional: comprobar cuántas filas afectó
        $updated = $stmt->rowCount();
        if ($updated === 0) {
            // aquí podrías lanzar excepción o simplemente devolver false
            throw new \RuntimeException(
                "No se encontró detalle de pedido para el id_pedido={$data['cod_ped']} "
              . "y id_areap={$data['id_areap']}."
            );
        }

        // Si quieres devolver algo:
        return $updated;
    }
    catch (\Throwable $e) {
        // Manejo de error: log y/o re-lanzar
        error_log("Error en atendidopormesa: " . $e->getMessage());
        return 0;
    }
}
}
