<?php
Session::init();
$ver = (Session::get('rol') == 1 or Session::get('rol') == 2 or Session::get('rol') == 3 or Session::get('rol') == 5 or Session::get('rol') == 7) ? '' : header('location: ' . URL . 'err/danger');
$ver = (Session::get('bloqueo') == 0 or Session::get('bloqueo') == null) ? '' : header('location: ' . URL . 'err/bloqueo');
?>
<?php
require_once 'public/lib/print/num_letras.php';
require_once 'models/ajuste_model.php';
require_once 'controllers/Notificacion.php';
class Venta extends Controller
{

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

    private function autoEnvioSunatHabilitado(int $tipoDoc): bool
    {
        return (int) (Session::get('sunat') ?? 0) === 1
            && (int) (Session::get('envios_auto') ?? 0) === 1
            && $tipoDoc !== 3;
    }

    private function responderJsonInmediato(string $body, int $statusCode = 200): void
    {
        if (function_exists('ignore_user_abort')) {
            @ignore_user_abort(true);
        }

        if (session_status() === PHP_SESSION_ACTIVE) {
            @session_write_close();
        }

        if (!headers_sent()) {
            http_response_code($statusCode);
            header('Content-Type: application/json; charset=utf-8');
            header('Connection: close');
            header('X-Accel-Buffering: no');
            header('Content-Length: ' . strlen($body));
        }

        echo $body;

        $nivelesBuffer = ob_get_level();
        for ($i = 0; $i < $nivelesBuffer; $i++) {
            @ob_end_flush();
        }

        @flush();

        if (function_exists('fastcgi_finish_request')) {
            @fastcgi_finish_request();
        }
    }

    private function firmarEnvioSunatAsync(int $idVenta, int $tipoDoc, int $timestamp): string
    {
        return hash_hmac('sha256', $idVenta . '|' . $tipoDoc . '|' . $timestamp, HASH_GENERAL_KEY);
    }

    private function despacharEnvioSunatAsync(int $idVenta, int $tipoDoc): bool
    {
        $url = rtrim(URL, '/') . '/venta/procesarEnvioSunatAsync';
        $partes = parse_url($url);

        if (!is_array($partes) || empty($partes['host'])) {
            error_log('[Venta][AsyncSunat] URL invalida para despacho: ' . $url);
            return false;
        }

        $timestamp = time();
        $payload = http_build_query([
            'id_venta' => $idVenta,
            'tipo_doc' => $tipoDoc,
            'ts' => $timestamp,
            'signature' => $this->firmarEnvioSunatAsync($idVenta, $tipoDoc, $timestamp),
        ], '', '&');

        $host = $partes['host'];
        $scheme = strtolower($partes['scheme'] ?? 'http');
        $port = (int) ($partes['port'] ?? ($scheme === 'https' ? 443 : 80));
        $path = ($partes['path'] ?? '/');
        if (!empty($partes['query'])) {
            $path .= '?' . $partes['query'];
        }

        $endpoint = $scheme === 'https' ? 'ssl://' . $host : $host;
        $errno = 0;
        $errstr = '';
        $fp = @fsockopen($endpoint, $port, $errno, $errstr, 1.5);

        if (!$fp) {
            error_log("[Venta][AsyncSunat] No se pudo abrir socket {$endpoint}:{$port} - {$errstr} ({$errno})");
            return false;
        }

        stream_set_timeout($fp, 1);

        $cookieHeader = '';
        $sessionName = function_exists('session_name') ? session_name() : '';
        $sessionId = function_exists('session_id') ? session_id() : '';
        if ($sessionName !== '' && $sessionId !== '') {
            $cookieHeader = "Cookie: {$sessionName}={$sessionId}\r\n";
        }

        $request = "POST {$path} HTTP/1.1\r\n";
        $request .= "Host: {$host}\r\n";
        $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $request .= "Content-Length: " . strlen($payload) . "\r\n";
        $request .= "Connection: Close\r\n";
        $request .= "User-Agent: RESTDARTECH-AsyncSUNAT/1.0\r\n";
        $request .= $cookieHeader;
        $request .= "\r\n";
        $request .= $payload;

        $ok = @fwrite($fp, $request) !== false;
        @fclose($fp);

        if (!$ok) {
            error_log("[Venta][AsyncSunat] No se pudo despachar request para id_venta={$idVenta}");
        }

        return $ok;
    }

    function index()
    {
        $this->view->title_page = 'Punto De Venta';
        $this->view->Salon = $this->model->Salon();
        $this->view->Mozo = $this->model->Mozo();
        $this->view->Repartidor = $this->model->Repartidor();
        $this->view->TipoPago = $this->model->TipoPago();
        $this->view->TipoDocumento = $this->model->TipoDocumento();
        $this->view->js = array('venta/js/jquery-ui.min.js', 'venta/js/venta_index.js', 'venta/js/venta_all.js', 'venta/js/venta_cliente.js');
        $this->view->render('venta/index', false);
        $this->view->TipoDocumento = $this->model->TipoDocumento();
    }

    function mesa_list()
    {
        print_r(json_encode($this->model->mesa_list($_POST)));
    }

    function mostrador_list()
    {
        $this->model->mostrador_list($_POST);
    }

    function mostrador_list_c()
    {
        $this->model->mostrador_list_c($_POST);
    }

    function comensal()
    {
        print_r(json_encode($this->model->comensal()));
    }

    function delivery_list()
    {
        $this->model->delivery_list($_POST);
    }

    function delivery_list_c()
    {
        $this->model->delivery_list_c($_POST);
    }

    function pedidoAccion()
    {
        print_r(json_encode($this->model->pedidoAccion($_POST)));
        $this->notificar($_POST['tipo_pedido']);
    }

    function listarPedidos()
    {
        header('Content-Type: application/json; charset=utf-8');
        $resp = $this->model->listarPedidos($_POST);
        if (!is_array($resp)) {
            $resp = [];
        }
        echo json_encode($resp, JSON_UNESCAPED_UNICODE);
    }

    function listarPedidosDetalle()
    {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($this->model->listarPedidosDetalle($_POST), JSON_UNESCAPED_UNICODE);
    }

    function listarUpdatePedidos()
    {
        print_r(json_encode($this->model->listarUpdatePedidos($_POST)));
    }

    function reimpresion_comanda()
    {
        print_r(json_encode($this->model->reimpresion_comanda($_POST)));
    }

    function listarComandas()
    {
        print_r(json_encode($this->model->listarComandas($_POST)));
    }

    function listarPedidosTicket()
    {
        print_r(json_encode($this->model->listarPedidosTicket($_POST)));
    }

    function ComboMesaOri()
    {
        $this->model->ComboMesaOri($_POST);
    }

    function ComboMesaDes()
    {
        $this->model->ComboMesaDes($_POST);
    }

    function subPedido()
    {
        print_r(json_encode($this->model->subPedido($_POST)));
    }

    public function cancelarPedido()
    {
        header('Content-Type: application/json; charset=utf-8');

        $resp = $this->model->cancelarPedido($_POST);

        if (!is_array($resp)) {
            http_response_code(500);
            echo json_encode([
                'success' => false,
                'message' => 'Respuesta invalida al cancelar el pedido.',
                'data' => $resp,
            ], JSON_UNESCAPED_UNICODE);
            return;
        }

        if (!isset($resp['error'])) {
            $response = [
                'success' => true,
                'message' => 'Se cancelaron ' . (int) ($resp['productos_cancelados'] ?? 0) . ' producto(s) correctamente.',
                'data' => $resp,
            ];
   
            $this->notificar($_POST['tipo_pedido'] ?? null);
            echo json_encode($response, JSON_UNESCAPED_UNICODE);
            return;
        }

        $statusCode = (int) ($resp['http_code'] ?? 400);
        if ($statusCode < 400) {
            $statusCode = 400;
        }
        http_response_code($statusCode);
        echo json_encode([
            'success' => false,
            'message' => $resp['message'] ?? 'No se canceló ningún producto.',
            'data' => $resp, // útil para depurar/ver causa
        ], JSON_UNESCAPED_UNICODE);
    }


    public function actualizarDataDelivery()
    {
        // Combinar los datos en uno solo array plano
        $data = $_POST['data'];
        $data['id_pedido'] = $_POST['id_pedido'];

        // Llamar al modelo con la data combinada
        $respuesta = $this->model->actualizarDataDelivery($data);

        // Devolver como JSON
        header('Content-Type: application/json');
        echo json_encode($respuesta);
    }


    function CambiarMesa()
    {
        $row = $this->model->CambiarMesa($_POST);
        if ($row['cod'] == 1) {
            header('location: ' . URL . 'venta');
        } else {
            header('location: ' . URL . 'venta');
        }

        $this->notificar(1);
    }

    function MoverPedidos()
    {
        $row = $this->model->MoverPedidos($_POST);
        if ($row['cod'] == 1) {
            header('location: ' . URL . 'venta');
        } else {
            header('location: ' . URL . 'venta');
        }

        $this->notificar(1);
    }

    function refrescar_mesas()
    {
        $this->model->refrescar_mesas();
        header('location: ' . URL . 'venta');
    }

    // function pedido_create($id){   
    //     $data = $this->model->$id($_POST);
    //     if($data['fil'] == 1){
    //         Session::set('codped', $data['id_pedido']);
    //         //if(Session::get('rol') == 5){
    //         if(Session::get('rol') == 5 && $id == 'pc1'){
    //             print_r(json_encode($data));
    //         } else{
    //             $this->notificar();
    //             header('location: ' . URL . 'venta/orden/'.$data['id_pedido']);
    //         }                     
    //     } else {
    //         if(Session::get('rol') == 5){
    //             print_r(json_encode(0));
    //         } else{
    //             header('location: ' . URL . 'venta');
    //         }            
    //     }        
    // }

    function pedido_create()
    {
        try {
            $method = $_POST['codtipoped'];
            $pedido = $_POST['pedido'];
            $detalle = $_POST['detalle'];
            $pedidoCreadoAhora = false;


            if ($detalle['cod_ped'] == 0) {
                $data = $this->model->$method($pedido);

                if ($data['fil'] != 1) {
                    echo json_encode([
                        'status' => 'error',
                        'message' => $data
                    ]);
                    exit;
                }
                $detalle['cod_ped'] = $data['id_pedido'];
                $pedidoCreadoAhora = true;
            }

            $validar = $this->model->ValidarEstadoPedido($detalle['cod_ped']);
            if ($validar['cod'] != 1) {
                echo json_encode([
                    'status' => 'error',
                    'message' => 'El pedido no está en estado válido para su registro.'
                ]);
                exit;
            }

            $tipoPedidoDetalle = isset($detalle['codtipoped']) ? (int) $detalle['codtipoped'] : 0;
            if ($tipoPedidoDetalle === 1) {
                $idMesaEsperada = (is_array($pedido) && isset($pedido['id_mesa'])) ? (int) $pedido['id_mesa'] : 0;
                $checkMesa = $this->model->validarConsistenciaPedidoMesa((int) $detalle['cod_ped'], $idMesaEsperada);

                if (empty($checkMesa['ok'])) {
                    $mensaje = 'No se pudo validar la mesa del pedido.';
                    if (($checkMesa['code'] ?? '') === 'mesa_distinta') {
                        $salon = trim((string) ($checkMesa['desc_salon'] ?? ''));
                        $mesa = trim((string) ($checkMesa['nro_mesa'] ?? ''));
                        if ($salon !== '' || $mesa !== '') {
                            $mensaje = 'El pedido pertenece a ' . $salon . ' - Mesa ' . $mesa . '.';
                        } else {
                            $mensaje = 'El pedido no pertenece a la mesa enviada.';
                        }
                    } elseif (!empty($checkMesa['message'])) {
                        $mensaje = (string) $checkMesa['message'];
                    }

                    echo json_encode([
                        'status' => 'error',
                        'message' => $mensaje,
                        'code' => $checkMesa['code'] ?? 'mesa_inconsistente'
                    ]);
                    exit;
                }
            }

            $canal = isset($_POST['canal']) ? $_POST['canal'] : 'web';
            if (is_array($pedido)) {
                if (isset($pedido['responsable_id'])) {
                    $detalle['responsable_id'] = $pedido['responsable_id'];
                }
                if (isset($pedido['responsable_nombre'])) {
                    $detalle['responsable_nombre'] = $pedido['responsable_nombre'];
                }
                if (isset($pedido['id_mozo'])) {
                    $detalle['id_mozo'] = $pedido['id_mozo'];
                }
            }

            $resp = $this->model->RegistrarPedido($detalle);
            $tieneDetalleActivo = $this->model->pedidoTieneDetalleActivo((int) $detalle['cod_ped']);

            // Si se creo el pedido en esta misma llamada y no se registro ningun item,
            // se desocupa para evitar mesas "colgadas" en estado activo sin detalle.
            if (
                $pedidoCreadoAhora
                && isset($resp['status'])
                && $resp['status'] === 'error'
                && $tieneDetalleActivo === false
            ) {
                $this->model->anular_pedido([
                    'tipo_pedido' => (int) $detalle['codtipoped'],
                    'id_pedido' => (int) $detalle['cod_ped']
                ]);
            }

            $this->notificar($detalle['codtipoped'], $canal);

            echo json_encode($resp);
            exit;

        } catch (Exception $e) {
            echo json_encode([
                'status' => 'error',
                'message' => 'Error en el proceso de pedido.',
                'error' => $e->getMessage()
            ]);
            exit;
        }
    }


    function orden($id_pedido)
    {
        $this->view->title_page = 'Pedido N° ' . $id_pedido;
        $this->view->TipoDocumento = $this->model->TipoDocumento();

        $ajuste = new Ajuste_Model();
        $this->view->Invoice = $ajuste->limit('invoices');

        $this->view->TipoPago = $this->model->TipoPago();
        $data = $this->model->ValidarEstadoPedido($id_pedido);
        if ($data['cod'] == 1) {
            $this->view->js = array('venta/js/jquery-ui.min.js', 'venta/js/js-render.js', 'venta/js/venta_orden.js', 'venta/js/venta_all.js', 'venta/js/venta_cliente.js');
            Session::set('codped', $id_pedido);
            Session::set('codtipoped', $data['tipo_pedido']);
            $this->view->render('venta/orden', false);
        } else {
            header('location: ' . URL . 'venta');
        }
    }

    function RegistrarPedido()
    {
        $data = $this->model->ValidarEstadoPedido($_POST['cod_ped']);
        if ($data['cod'] == 1) {
            $this->model->RegistrarPedido($_POST);
            print_r(json_encode(1));
        } else {
            print_r(json_encode(2));
        }

        $this->notificar(1);
    }

    /* validad que el pedido siga activo  */
    function ValidarEstadoPedido()
    {
        $data = $this->model->ValidarEstadoPedido($_POST['cod_ped']);
        if ($data['cod'] == 1) {
            print_r(json_encode(1));
        } else {
            print_r(json_encode(2));
        }
    }


    function RegistrarVenta()
    {
        if (empty($_POST['id_pedido'])) {
            header('Content-Type: application/json; charset=utf-8');
            http_response_code(400);
            echo json_encode(['ok' => false, 'error' => 'Falta id_pedido'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            return;
        }
        try {
            $id_venta = $this->model->RegistrarVenta($_POST);
            $tipoDoc = (int) ($_POST['tipo_doc'] ?? 0);
            $tipoPedido = $_POST['tipo_pedido'] ?? null;
            $this->responderJsonInmediato(json_encode($id_venta));
            if ($this->autoEnvioSunatHabilitado($tipoDoc)) {
                $despachado = $this->despacharEnvioSunatAsync((int) $id_venta, $tipoDoc);
                if (!$despachado) {
                    error_log("[RegistrarVenta][AsyncSunat] Quedo pendiente para cron. id_venta={$id_venta} tipo_doc={$tipoDoc}");
                }
            }
            $this->notificar($tipoPedido);
        } catch (\Throwable $e) {
            if (!headers_sent()) {
                header('Content-Type: application/json; charset=utf-8');
            }
            http_response_code(500);
            echo json_encode(['ok' => false, 'error' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        }
    }

    function TestVenta()
    {


        require_once 'controllers/PseController.php';
        $pse = new PseController();
        $resp = $pse->enviarFactura($_POST['id_venta']);
        header('Content-Type: application/json');
        echo json_encode($resp);

    }

    function anular_pedido()
    {
        print_r(json_encode($this->model->anular_pedido($_POST)));
        require_once 'models/PseModel.php';
        $pseModel = new PseModel();
        $pseModel->reponerStock($_POST['id_pedido']);
        $this->notificar($_POST['tipo_pedido']);

    }

    // function anular_venta()
    // {
    //     try {
    //         $response = $this->model->anular_venta($_POST);

    //         // Si el modelo no retorna nada, crear respuesta por defecto
    //         if ($response === null) {
    //             $response = ['success' => true, 'message' => 'Venta anulada correctamente'];
    //             require_once 'controllers/PseController.php';
    //             $pse = new PseController();
    //             $pse->reponerStock($_POST['id_venta']);

    //         }

    //         header('Content-Type: application/json');
    //         echo json_encode($response);

    //     } catch (Exception $e) {
    //         header('Content-Type: application/json');
    //         echo json_encode(['success' => false, 'message' => 'Error interno del servidor']);
    //     }
    // }

    public function anular_venta()
    {
        header('Content-Type: application/json; charset=utf-8');

        try {
            // 1) Anula la venta con tu modelo
            $response = $this->model->anular_venta($_POST);

            // 2) Si el modelo no retorna nada, asumimos éxito
            if ($response === null) {
                $response = ['success' => true, 'message' => 'Venta anulada correctamente'];

                // ⚠️ No llames a otro CONTROLLER, llama al MODELO que repone stock
                //    (asumiendo que PseModel tiene reponerStock(int $id_venta): array)
                $idVenta = isset($_POST['id_venta']) ? (int) $_POST['id_venta'] : 0;


                require_once 'models/PseModel.php';
                $pseModel = new PseModel();
                $rs = $pseModel->reponerStockVenta($_POST['id_venta']);
                
                // Normaliza posibles formatos de salida del modelo
                if (is_array($rs)) {
                    // Caso legacy: ['skipped' => true, 'msg' => 'Venta sin detalles']
                    if (isset($rs['skipped']) && $rs['skipped'] === true) {
                        // No es error: solo informa que no había nada que reponer
                        $response['message'] .= ' (Sin reposición: ' . ($rs['msg'] ?? 'venta sin detalles') . ')';
                    }
                    // Caso moderno: { ok: true|false, ... }
                    elseif (array_key_exists('ok', $rs)) {
                        if ($rs['ok'] === false) {
                            // Si deseas considerar esto como error global:
                            http_response_code(500);
                            echo json_encode([
                                'success' => false,
                                'message' => $rs['message'] ?? 'Error al reponer stock',
                                'data' => $rs,
                            ], JSON_UNESCAPED_UNICODE);
                            return;
                        }
                        // ok === true → opcionalmente agrega info al mensaje
                        if (!empty($rs['message'])) {
                            $response['message'] .= ' — ' . $rs['message'];
                        }
                    }
                    // Otro formato inesperado → adjunta como data informativa
                    else {
                        $response['data'] = $rs;
                    }
                }

                $this->notificar(1);

                // IMPORTANTE: asegura que anular_venta() terminó su transacción (commit/rollback)
                // antes de llamar a reponerStock() para evitar "There is already an active transaction".


            }

            echo json_encode($response, JSON_UNESCAPED_UNICODE);

        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode([
                'success' => false,
                'message' => 'Error interno del servidor',
                'error' => $e->getMessage(), // opcional para depurar
            ], JSON_UNESCAPED_UNICODE);
        }
    }

    function defaultdata()
    {
        print_r(json_encode($this->model->defaultdata($_POST)));
    }

    function listarCategorias()
    {
        print_r(json_encode($this->model->listarCategorias($_POST)));
    }

    function listarProdsMasVend()
    {
        print_r(json_encode($this->model->listarProdsMasVend($_POST)));
    }

    function listarProductos()
    {
        print_r(json_encode($this->model->listarProductos($_POST)));
    }

    function buscar_producto()
    {
        print_r(json_encode($this->model->buscar_producto($_POST)));
    }

    function ListarDetallePed()
    {
        print_r(json_encode($this->model->ListarDetallePed($_POST)));
    }

    function marcarDetalleHotelero()
    {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($this->model->marcarDetalleHotelero($_POST), JSON_UNESCAPED_UNICODE);
    }

    function cliente_crud()
    {
        if ($_POST['id_cliente'] != '') {
            print_r(json_encode($this->model->cliente_crud_update($_POST)));
        } else {
            print_r(json_encode($this->model->cliente_crud_create($_POST)));
        }
    }

    function buscar_cliente()
    {
        print_r(json_encode($this->model->buscar_cliente(API_TOKEN, $_POST)));
    }

    function buscar_cliente_telefono()
    {
        print_r(json_encode($this->model->buscar_cliente_telefono($_POST)));
    }

    function pedido_edit()
    {
        $this->model->pedido_edit($_POST);
    }

    function pedido_crud()
    {
        print_r(json_encode($this->model->pedido_crud_update($_POST)));
    }

    function pedido_delete()
    {
        $this->model->pedido_delete($_POST);
        $this->notificar($_POST['tipo_pedido']);
    }

    function venta_edit()
    {
        $this->model->venta_edit($_POST);
    }

    function venta_edit_pago()
    {
        print_r(json_encode($this->model->venta_edit_pago($_POST)));
    }

    function venta_edit_documento()
    {
        $response = json_encode($this->model->venta_edit_documento($_POST));
        $this->responderJsonInmediato($response);
        $idTipoDocumento = (int) ($_POST['id_tipo_documento'] ?? 0);
        $idVenta = (int) ($_POST['id_venta'] ?? 0);
        if ($idVenta > 0 && $this->autoEnvioSunatHabilitado($idTipoDocumento)) {
            $despachado = $this->despacharEnvioSunatAsync($idVenta, $idTipoDocumento);
            if (!$despachado) {
                error_log("[venta_edit_documento][AsyncSunat] Quedo pendiente para cron. id_venta={$idVenta} tipo_doc={$idTipoDocumento}");
            }
        }
    }

    public function procesarEnvioSunatAsync()
    {
        header('Content-Type: application/json; charset=utf-8');
        if (function_exists('ignore_user_abort')) {
            @ignore_user_abort(true);
        }
        if (session_status() === PHP_SESSION_ACTIVE) {
            @session_write_close();
        }
        $idVenta = (int) ($_POST['id_venta'] ?? 0);
        $tipoDoc = (int) ($_POST['tipo_doc'] ?? 0);
        $timestamp = (int) ($_POST['ts'] ?? 0);
        $signature = (string) ($_POST['signature'] ?? '');
        if ($idVenta <= 0 || !in_array($tipoDoc, [1, 2], true) || $timestamp <= 0 || $signature === '') {
            http_response_code(400);
            echo json_encode(['ok' => false, 'error' => 'Parametros invalidos'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            return;
        }
        if (abs(time() - $timestamp) > 300) {
            http_response_code(408);
            echo json_encode(['ok' => false, 'error' => 'Solicitud expirada'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            return;
        }
        $firmaEsperada = $this->firmarEnvioSunatAsync($idVenta, $tipoDoc, $timestamp);
        if (!hash_equals($firmaEsperada, $signature)) {
            http_response_code(403);
            echo json_encode(['ok' => false, 'error' => 'Firma invalida'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            return;
        }
        require_once 'controllers/PseController.php';
        $pse = new PseController();
        try {
            $resp = $tipoDoc === 1
                ? $pse->resumenBoleta($idVenta, 1)
                : $pse->enviarFactura($idVenta);
            if (!is_array($resp) || empty($resp['ok'])) {
                $msg = is_array($resp)
                    ? ($resp['message'] ?? $resp['mensaje'] ?? $resp['error'] ?? 'Error al enviar el comprobante')
                    : 'Respuesta invalida del proceso PSE';
                $http = is_array($resp) ? (int) ($resp['http'] ?? 0) : 0;
                error_log("[Venta][AsyncSunat] Error id_venta={$idVenta} tipo_doc={$tipoDoc} http={$http} msg={$msg}");
                http_response_code(202);
                echo json_encode([
                    'ok' => false,
                    'id_venta' => $idVenta,
                    'message' => $msg,
                    'http' => $http,
                ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                return;
            }
            echo json_encode([
                'ok' => true,
                'id_venta' => $idVenta,
                'tipo_doc' => $tipoDoc,
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        } catch (\Throwable $e) {
            error_log("[Venta][AsyncSunat][ex] id_venta={$idVenta} tipo_doc={$tipoDoc} error=" . $e->getMessage());
            http_response_code(500);
            echo json_encode([
                'ok' => false,
                'id_venta' => $idVenta,
                'error' => $e->getMessage(),
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        }
    }

    function tags_list()
    {
        print_r(json_encode($this->model->tags_list($_POST)));
    }

    function tags_crud()
    {
        print_r(json_encode($this->model->tags_crud($_POST)));
    }

    /* INICIO COMPROBANTE SIN ENVIAR SUNAT */

    function contadorSunatSinEnviar()
    {
        print_r(json_encode($this->model->contadorSunatSinEnviar()));
    }

    /* FIN COMPROBANTE SIN ENVIAR SUNAT */

    /* INICIO PEDIDOS PREPARADOS */

    function contadorPedidosPreparados()
    {
        print_r(json_encode($this->model->contadorPedidosPreparados()));
    }

    function listarPedidosPreparados()
    {
        $this->model->listarPedidosPreparados();
    }

    function pedidoEntregado()
    {
        print_r(json_encode($this->model->pedidoEntregado($_POST)));
        $tipoPedido = isset($_POST['tipo_pedido']) ? (int) $_POST['tipo_pedido'] : 1;
        $canal = isset($_POST['canal']) ? (string) $_POST['canal'] : 'web';
        $this->notificar($tipoPedido, $canal);
    }

    function pedido_estado_update()
    {
        print_r(json_encode($this->model->pedido_estado_update($_POST)));

        $this->notificar(1);
    }

    function menu_categoria_list()
    {
        $this->model->menu_categoria_list($_POST);
    }

    function menu_plato_list()
    {
        $this->model->menu_plato_list($_POST);
    }

    function menu_plato_estado()
    {
        print_r(json_encode($this->model->menu_plato_estado($_POST)));
    }

    function impresion_precuenta($id_pedido)
    {
        if (Session::get('print_pre') == 1) {
            $dato = $this->model->impresion_precuenta($id_pedido);
            header('location: http://' . Session::get('pc_ip') . '/imprimir/pre_cuenta.php?data=' . urlencode(json_encode($dato)));
        } else {
            $this->view->dato = $this->model->impresion_precuenta($id_pedido);
            $this->view->render('venta/imprimir/precuenta', true);
        }
    }
    // pdf reparto 
    function impresion_reparto($id_venta)
    {
        if (Session::get('print_cpe') == 1) {
            $dato = $this->model->impresion_reparto($id_venta);
            header('location: http://' . Session::get('pc_ip') . '/imprimir/ticket_reparto.php?data=' . json_encode($dato));
        } else {
            $this->view->dato = $this->model->impresion_reparto($id_venta);
            $this->view->render('venta/imprimir/ticketreparto', true);
        }
    }

    function impresion_reparto_pedido($id_pedido)
    {
        if (Session::get('print_cpe') == 1) {
            $dato = $this->model->impresion_reparto_pedido($id_pedido);
            header('location: http://' . Session::get('pc_ip') . '/imprimir/ticket_reparto.php?data=' . json_encode($dato));
        } else {
            $this->view->dato = $this->model->impresion_reparto_pedido($id_pedido);
            $this->view->render('venta/imprimir/ticketreparto', true);
        }
    }

    function impresion_comanda()
    {
        $this->view->render('venta/imprimir/comanda', true);
    }


    function contador_comanda()
    {
        print_r(json_encode($this->model->contador_comanda($_POST)));
    }

    function Personal()
    {
        print_r(json_encode($this->model->Personal()));
    }

    function alert_pedidos_programados()
    {
        print_r(json_encode($this->model->alert_pedidos_programados()));
    }

    /* FIN PEDIDOS PREPARADOS */
    function control_stock_pedido()
    {
        print_r(json_encode($this->model->control_stock_pedido($_POST)));
    }

    function notificar($tipo_pedido, $canal = "web")
    {

        //echo "Notificando tipo_pedido: $tipo_pedido, canal: $canal\n"; // Línea de depuración

        $notifier = new Notificacion();
        try {

            if ($tipo_pedido == 1) {
                $notifier->enviarNotificacion();
            } elseif ($tipo_pedido == 2 && $canal != 'venta_rapida') {
                $notifier->enviarNotificacionMostrador();
            } elseif ($tipo_pedido == 3) {
                $notifier->enviarNotificacionDelivery();
            } elseif ($tipo_pedido == 2 && $canal == 'venta_rapida') {
                $notifier->enviarNotificacionVentaRapida();
            }

            // stock-update: broadcast global a TODOS los canales (mesa, mostrador, delivery, venta rápida)
            // Permite que cualquier terminal actualice su stock en tiempo real sin recargar
            $notifier->notificarReposicionStock(['timestamp' => time(), 'canal' => $canal]);
            $notifier->notificarProduccionTiempoReal([
                'timestamp' => time(),
                'canal' => $canal,
                'tipo_pedido' => (int) $tipo_pedido
            ]);

        } catch (\Exception $e) {
            error_log("Error al notificar: " . $e->getMessage());
        }
    }


}
