<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Cotizaciones extends MY_Controller {

    public function __construct() {
        parent::__construct();
        $this->load->model('ventas/Cotizacion_model');
        $this->load->model('ventas/Orden_pedido_model');
    }

    protected function validar_permiso_ajax($slug) {
        if (!tiene_permiso($slug)) {
            echo json_encode(array(
                'status' => false,
                'message' => 'No tienes permisos para esta acción'
            ));
            exit;
        }
    }

    private function normalizarTexto($texto) {
        return strtoupper(trim($texto));
    }

    private function calcular_precio_por_cantidad($producto, $cantidad) {
        $cantidad = (float)$cantidad;

        if ($cantidad >= 1000) {
            return (float)$producto->precio_millar;
        } elseif ($cantidad >= 100) {
            return (float)$producto->precio_cien;
        } elseif ($cantidad >= 50) {
            return (float)$producto->precio_cincuenta;
        } elseif ($cantidad >= 25) {
            return (float)$producto->precio_veinticinco;
        } elseif ($cantidad >= 12) {
            return (float)$producto->precio_doce;
        } else {
            return (float)$producto->precio_unidad;
        }
    }

    public function index() {
        $this->validar_permiso('cotizaciones_ver');

        $estado_id = $this->input->get('estado_id', TRUE);
        if ($estado_id === null || $estado_id === '') {
            // Por defecto mostrar estado EMITIDO
            $estado_emitido = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('COTIZACION', 'E');
            $estado_id = $estado_emitido ? $estado_emitido->id : null;
        }

        $data['titulo']       = 'Cotizaciones';
        $data['cotizaciones'] = $this->Cotizacion_model->listar($estado_id);
        $data['estados']      = $this->Cotizacion_model->listar_estados();
        $data['estado_id']    = $estado_id;

        $this->layout('ventas/cotizaciones/index', $data);
    }

    public function create() {
        $this->validar_permiso('cotizaciones_crear');

        $tributo = $this->Cotizacion_model->obtener_tributo_igv();
        $estado_emitido = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('COTIZACION', 'E');

        $data['titulo'] = 'Nueva Cotización';
        $data['formas_pago'] = $this->Cotizacion_model->obtener_formas_pago();
        $data['tipos_comprobante'] = $this->Cotizacion_model->obtener_tipos_comprobante_venta();
        $data['tributo_igv'] = $tributo;
        $data['estado_emitido'] = $estado_emitido;
        $data['almacenes'] = $this->Cotizacion_model->obtener_almacenes_activos();

        $this->layout('ventas/cotizaciones/create', $data);
    }

    public function buscar_cliente() {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $term = trim($this->input->get('term', TRUE));

        if (strlen($term) < 2) {
            echo json_encode(array());
            return;
        }

        $clientes = $this->Cotizacion_model->buscar_cliente($term);
        $resultado = array();

        foreach ($clientes as $item) {
            $cliente = $this->Cotizacion_model->obtener_cliente($item->id);

            $resultado[] = array(
                'id' => $item->id,
                'label' => $item->razon_social . ' | ' . $item->nro_documento,
                'value' => $item->razon_social,
                'razon_social' => $item->razon_social,
                'nro_documento' => $item->nro_documento,
                'fp_id' => $item->fp_id,
                'fp_descripcion' => $item->fp_descripcion,
                'forma_pago_nombre' => $cliente ? $cliente->forma_pago_nombre : '',
                'vendedor_id' => $item->vendedor_id,
                'vendedor_nombre' => $cliente ? $cliente->vendedor_nombre : ''
            );
        }

        echo json_encode($resultado);
    }

    public function contactos_cliente($cliente_id) {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $items = $this->Cotizacion_model->obtener_contactos_cliente($cliente_id);
        $data = array();

        foreach ($items as $item) {
            $data[] = array(
                'id' => $item->id,
                'nombre' => $item->nombre,
                'celular' => $item->celular,
                'email' => $item->email,
                'cargo' => $item->cargo
            );
        }

        echo json_encode($data);
    }

    public function locales_cliente($cliente_id) {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $items = $this->Cotizacion_model->obtener_locales_cliente($cliente_id);
        $data = array();

        foreach ($items as $item) {
            $data[] = array(
                'id' => $item->id,
                'direccion' => $item->direccion
            );
        }

        echo json_encode($data);
    }

    public function buscar_producto() {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $term = trim($this->input->get('term', TRUE));
        $almacen_id = $this->input->get('almacen_id', TRUE);

        if (strlen($term) < 2) {
            echo json_encode(array());
            return;
        }

        $productos = $this->Cotizacion_model->buscar_producto($term, $almacen_id);
        $resultado = array();

        foreach ($productos as $item) {
            $resultado[] = array(
                'id' => $item->id,
                'label' => $item->codigo . ' | ' . $item->nombre,
                'value' => $item->nombre,
                'codigo' => $item->codigo,
                'nombre' => $item->nombre,
                'descripcion' => $item->descripcion,
                'unidad_nombre' => $item->unidad_nombre,
                'unidad_abreviado' => $item->unidad_abreviado,
                'stock' => (float)$item->cantidad_stock,
                'precio_unidad' => (float)$item->precio_unidad,
                'precio_doce' => (float)$item->precio_doce,
                'precio_veinticinco' => (float)$item->precio_veinticinco,
                'precio_cincuenta' => (float)$item->precio_cincuenta,
                'precio_cien' => (float)$item->precio_cien,
                'precio_millar' => (float)$item->precio_millar
            );
        }

        echo json_encode($resultado);
    }

    public function estado_historial($ctc_id) {
        $this->validar_permiso_ajax('cotizaciones_ver');

        $historial = $this->Cotizacion_model->obtener_historial_estados($ctc_id);
        echo json_encode($historial);
    }

    public function obtener_contacto_ajax($id) {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $contacto = $this->Cotizacion_model->obtener_contacto($id);

        if (!$contacto) {
            echo json_encode(array(
                'status' => false,
                'message' => 'Contacto no encontrado'
            ));
            return;
        }

        echo json_encode(array(
            'status' => true,
            'data' => $contacto
        ));
    }

    public function obtener_local_ajax($id) {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $local = $this->Cotizacion_model->obtener_local($id);

        if (!$local) {
            echo json_encode(array(
                'status' => false,
                'message' => 'Local no encontrado'
            ));
            return;
        }

        echo json_encode(array(
            'status' => true,
            'data' => $local
        ));
    }

    public function obtener_producto_ajax($id) {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $almacen_id = $this->input->get('almacen_id', TRUE);
        $producto = $this->Cotizacion_model->obtener_producto($id, $almacen_id);

        if (!$producto) {
            echo json_encode(array(
                'status' => false,
                'message' => 'Producto no encontrado'
            ));
            return;
        }

        echo json_encode(array(
            'status' => true,
            'data' => array(
                'id' => $producto->id,
                'codigo' => $producto->codigo,
                'nombre' => $producto->nombre,
                'descripcion' => $producto->descripcion,
                'unidad_nombre' => $producto->unidad_nombre,
                'unidad_abreviado' => $producto->unidad_abreviado,
                'stock' => (float)$producto->cantidad_stock,
                'precio_unidad' => (float)$producto->precio_unidad,
                'precio_doce' => (float)$producto->precio_doce,
                'precio_veinticinco' => (float)$producto->precio_veinticinco,
                'precio_cincuenta' => (float)$producto->precio_cincuenta,
                'precio_cien' => (float)$producto->precio_cien,
                'precio_millar' => (float)$producto->precio_millar
            )
        ));
    }

    public function calcular_precio_ajax() {
        $this->validar_permiso_ajax('cotizaciones_crear');

        $producto_id = $this->input->post('producto_id', TRUE);
        $cantidad = $this->input->post('cantidad', TRUE);
        $almacen_id = $this->input->post('almacen_id', TRUE);

        if (empty($producto_id) || empty($cantidad)) {
            echo json_encode(array(
                'status' => false,
                'message' => 'Producto y cantidad son obligatorios'
            ));
            return;
        }

        $producto = $this->Cotizacion_model->obtener_producto($producto_id, $almacen_id);

        if (!$producto) {
            echo json_encode(array(
                'status' => false,
                'message' => 'Producto no encontrado'
            ));
            return;
        }

        $precio = $this->calcular_precio_por_cantidad($producto, $cantidad);

        echo json_encode(array(
            'status' => true,
            'precio_unitario' => number_format($precio, 4, '.', '')
        ));
    }


    public function store() {
        $this->validar_permiso('cotizaciones_crear');

        $this->form_validation->set_rules('cliente_id', 'Cliente', 'required');
        $this->form_validation->set_rules('ctc_fecha', 'Fecha', 'required');
        $this->form_validation->set_rules('ctc_tiempo_entrega', 'Tiempo de entrega', 'required|integer');
        $this->form_validation->set_rules('comprobante_id', 'Tipo de comprobante', 'required');
        $this->form_validation->set_rules('almacen_id', 'Almacén', 'required');
        $this->form_validation->set_rules('tributo_id', 'Tributo', 'required');
        $this->form_validation->set_rules('estado_id', 'Estado', 'required');

        if ($this->form_validation->run() == FALSE) {
            $this->create();
            return;
        }

        $cliente_id = $this->input->post('cliente_id', TRUE);
        $contacto_id = $this->input->post('contacto_id', TRUE);
        $local_id = $this->input->post('local_id', TRUE);
        $vendedor_id = $this->input->post('vendedor_id', TRUE);
        $ctc_fecha = $this->input->post('ctc_fecha', TRUE);
        $ctc_ordcomp_cliente = trim($this->input->post('ctc_ordcomp_cliente', TRUE));
        $ctc_comentarios = trim($this->input->post('ctc_comentarios', TRUE));
        $ctc_tiempo_entrega = (int)$this->input->post('ctc_tiempo_entrega', TRUE);
        $fp_id = $this->input->post('fp_id', TRUE);
        $ctc_fpdetalle = trim($this->input->post('ctc_fpdetalle', TRUE));
        $comprobante_id = $this->input->post('comprobante_id', TRUE);
        $ctc_tipo_coti = $this->input->post('ctc_tipo_coti', TRUE) ?: 'C';
        $tributo_id = $this->input->post('tributo_id', TRUE);
        $modo_tributo = (int)$this->input->post('modo_tributo', TRUE);
        $estado_id = $this->input->post('estado_id', TRUE);
        $detalle = $this->input->post('detalle');

        if (empty($detalle) || !is_array($detalle)) {
            $this->session->set_flashdata('error', 'Debes agregar al menos un producto al detalle');
            redirect('ventas/cotizaciones/create');
        }

        $tributo = $this->Cotizacion_model->obtener_tributo_igv();
        if (!$tributo) {
            $this->session->set_flashdata('error', 'No se encontró la configuración del tributo IGV');
            redirect('ventas/cotizaciones/create');
        }

        $igvPorcentaje = (float)$tributo->valor_porcentual;

        $detalleInsert = array();
        $sumaTotales = 0;

        foreach ($detalle as $item) {
            $producto_id = isset($item['producto_id']) ? (int)$item['producto_id'] : 0;
            $descripcion = isset($item['ctcd_descripcion']) ? trim($item['ctcd_descripcion']) : '';
            $solped = isset($item['ctcd_solped']) ? trim($item['ctcd_solped']) : '';
            $cantidad = isset($item['ctcd_cantidad']) ? (float)$item['ctcd_cantidad'] : 0;
            $precio_unitario = isset($item['ctcd_precio_unitario']) ? (float)$item['ctcd_precio_unitario'] : 0;
            $porcentaje_descuento = isset($item['ctcd_porcentaje_descuento']) ? (float)$item['ctcd_porcentaje_descuento'] : 0;

            if ($producto_id <= 0 || $cantidad <= 0) {
                continue;
            }

            if ($descripcion === '') {
                $producto = $this->Cotizacion_model->obtener_producto($producto_id, $this->input->post('almacen_id', TRUE));
                $descripcion = $producto ? $producto->nombre : '';
            }

            if ($porcentaje_descuento < 0) {
                $porcentaje_descuento = 0;
            }

            $precio_unitario_descontado = $precio_unitario;
            if ($porcentaje_descuento > 0) {
                $precio_unitario_descontado = $precio_unitario - ($precio_unitario * ($porcentaje_descuento / 100));
            }

            $precio_unitario_descontado = round($precio_unitario_descontado, 4);
            $total = round($cantidad * $precio_unitario_descontado, 2);

            $sumaTotales += $total;

            $detalleInsert[] = array(
                'producto_id' => $producto_id,
                'ctcd_descripcion' => $descripcion,
                'ctcd_solped' => $solped !== '' ? $solped : null,
                'ctcd_cantidad' => $cantidad,
                'ctcd_precio_unitario' => round($precio_unitario, 4),
                'ctcd_porcentaje_descuento' => round($porcentaje_descuento, 2),
                'ctcd_precio_unitario_descontado' => $precio_unitario_descontado,
                'ctcd_total' => $total,
                'created_by' => $this->session->userdata('id')
            );
        }

        if (empty($detalleInsert)) {
            $this->session->set_flashdata('error', 'No hay detalle válido para registrar');
            redirect('ventas/cotizaciones/create');
        }

        if ($modo_tributo === 1) {
            $ctc_total = round($sumaTotales, 2);
            $ctc_subtotal = round($ctc_total / (1 + ($igvPorcentaje / 100)), 2);
            $ctc_igv = round($ctc_total - $ctc_subtotal, 2);
        } else {
            $ctc_subtotal = round($sumaTotales, 2);
            $ctc_igv = round($ctc_subtotal * ($igvPorcentaje / 100), 2);
            $ctc_total = round($ctc_subtotal + $ctc_igv, 2);
        }

        $cabecera = array(
            'cliente_id' => $cliente_id,
            'contacto_id' => $contacto_id ? $contacto_id : null,
            'local_id' => $local_id ? $local_id : null,
            'vendedor_id' => $vendedor_id ? $vendedor_id : null,
            'ctc_fecha' => $ctc_fecha,
            'ctc_ordcomp_cliente' => $ctc_ordcomp_cliente !== '' ? $ctc_ordcomp_cliente : null,
            'ctc_comentarios' => $ctc_comentarios !== '' ? $ctc_comentarios : null,
            'ctc_tiempo_entrega' => $ctc_tiempo_entrega,
            'ctc_subtotal' => $ctc_subtotal,
            'ctc_igv_porcentaje' => round($igvPorcentaje, 4),
            'ctc_igv' => $ctc_igv,
            'ctc_total' => $ctc_total,
            'fp_id' => $fp_id ? $fp_id : null,
            'ctc_fpdetalle' => $ctc_fpdetalle !== '' ? $ctc_fpdetalle : null,
            'comprobante_id' => $comprobante_id,
            'ctc_tipo_coti' => $ctc_tipo_coti,
            'tributo_id' => $tributo_id,
            'modo_tributo' => $modo_tributo,
            'estado_id' => $estado_id,
            'created_by' => $this->session->userdata('id')
        );

        $this->db->trans_begin();

        $ctc_id = $this->Cotizacion_model->insertar_cabecera($cabecera);

        if (!$ctc_id) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'No se pudo registrar la cotización');
            redirect('ventas/cotizaciones/create');
        }

        foreach ($detalleInsert as &$d) {
            $d['ctc_id'] = $ctc_id;
        }
        unset($d);

        $this->Cotizacion_model->insertar_detalle_batch($detalleInsert);

        $this->Cotizacion_model->insertar_estado(array(
            'ctc_id' => $ctc_id,
            'estado_id' => $estado_id,
            'ctc_fechaestado' => date('Y-m-d H:i:s'),
            'usuario_id' => $this->session->userdata('id')
        ));

        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'Ocurrió un error al guardar la cotización');
            redirect('ventas/cotizaciones/create');
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Cotización registrada correctamente');
        redirect('ventas/cotizaciones');
    }

    public function ver($id) {
        $this->validar_permiso('cotizaciones_ver');

        $cotizacion = $this->db
            ->select('
                c.*,
                cli.razon_social,
                cli.nro_documento,
                con.nombre as contacto_nombre,
                con.celular as contacto_celular,
                con.email as contacto_email,
                loc.direccion as local_direccion,
                fp.nombre as forma_pago,
                tc.nombre as comprobante,
                tc.nombre_corto as comprobante_corto,
                t.nombre as tributo_nombre,
                t.abreviado as tributo_abreviado,
                e.nombre as estado_nombre,
                e.codigo as estado_codigo,
                CONCAT(IFNULL(v.apellidos, ""), " ", IFNULL(v.nombres, "")) as vendedor_nombre,
                u.usuario as usuario_creador
            ')
            ->from('vt_cotizacion c')
            ->join('vt_cliente cli', 'cli.id = c.cliente_id')
            ->join('vt_cliente_contacto con', 'con.id = c.contacto_id', 'left')
            ->join('vt_cliente_local loc', 'loc.id = c.local_id', 'left')
            ->join('mt_forma_pago fp', 'fp.id = c.fp_id', 'left')
            ->join('mt_tipo_comprobante tc', 'tc.id = c.comprobante_id')
            ->join('mt_tributo t', 't.id = c.tributo_id')
            ->join('estado e', 'e.id = c.estado_id')
            ->join('rh_empleado v', 'v.id = c.vendedor_id', 'left')
            ->join('usuarios u', 'u.id = c.created_by', 'left')
            ->where('c.id', $id)
            ->get()
            ->row();

        if (!$cotizacion) {
            show_404();
        }

        $detalle = $this->Cotizacion_model->obtener_detalle($id);
        $historial = $this->Cotizacion_model->obtener_historial_estados($id);

        $data['titulo'] = 'Detalle de Cotización';
        $data['cotizacion'] = $cotizacion;
        $data['detalle'] = $detalle;
        $data['historial'] = $historial;

        $this->layout('ventas/cotizaciones/ver', $data);
    }


    public function print($id) {
        $this->validar_permiso('cotizaciones_ver');
 
        $cotizacion = $this->db
            ->select('
                c.*,
                cli.razon_social,
                cli.nro_documento,
                cli.domicilio_fiscal,
                con.nombre as contacto_nombre,
                con.celular as contacto_celular,
                con.email as contacto_email,
                loc.direccion as local_direccion,
                fp.nombre as forma_pago_nombre,
                tc.nombre as comprobante_nombre,
                tc.nombre_corto as comprobante_corto,
                t.nombre as tributo_nombre,
                t.abreviado as tributo_abreviado,
                e.nombre as estado_nombre,
                e.codigo as estado_codigo,
                CONCAT(IFNULL(v.apellidos, ""), " ", IFNULL(v.nombres, "")) as vendedor_nombre,
                u.usuario as usuario_creador
            ')
            ->from('vt_cotizacion c')
            ->join('vt_cliente cli', 'cli.id = c.cliente_id')
            ->join('vt_cliente_contacto con', 'con.id = c.contacto_id', 'left')
            ->join('vt_cliente_local loc', 'loc.id = c.local_id', 'left')
            ->join('mt_forma_pago fp', 'fp.id = c.fp_id', 'left')
            ->join('mt_tipo_comprobante tc', 'tc.id = c.comprobante_id')
            ->join('mt_tributo t', 't.id = c.tributo_id')
            ->join('estado e', 'e.id = c.estado_id')
            ->join('rh_empleado v', 'v.id = c.vendedor_id', 'left')
            ->join('usuarios u', 'u.id = c.created_by', 'left')
            ->where('c.id', $id)
            ->get()
            ->row();
 
        if (!$cotizacion) {
            show_404();
        }
 
        $detalle = $this->Cotizacion_model->obtener_detalle($id);
 
        // Datos de la empresa (igual que en otros módulos)
        $empresa = $this->db->get('empresa')->row();
 
        // Cuentas bancarias activas
        $cuentas = $this->db
            ->select('
                bc.*,
                b.nombre as banco_nombre,
                m.abreviado as moneda_abreviado,
                m.nombre as moneda_nombre
            ')
            ->from('mt_banco_cuenta bc')
            ->join('mt_banco b', 'b.id = bc.banco_id')
            ->join('mt_moneda m', 'm.id = bc.moneda_id')
            ->where('bc.estado', 1)
            ->order_by('b.nombre', 'ASC')
            ->get()
            ->result();
 
        $data['cotizacion'] = $cotizacion;
        $data['detalle']    = $detalle;
        $data['empresa']    = $empresa;
        $data['cuentas']    = $cuentas;
 
        // Vista standalone (sin layout)
        $this->load->view('ventas/cotizaciones/print', $data);
    }



    public function edit($id) {
        $this->validar_permiso('cotizaciones_editar');

        $cotizacion = $this->Cotizacion_model->obtener_completo($id);

        if (!$cotizacion) {
            show_404();
        }

        if ($cotizacion->estado_codigo == 'N') {
            $this->session->set_flashdata('error', 'No se puede editar una cotización anulada');
            redirect('ventas/cotizaciones');
        }

        $orden = $this->Cotizacion_model->obtener_orden_pedido_por_cotizacion($id);

        if ($orden) {
            $estadoOrden = $this->db
                ->where('id', $orden->estado_id)
                ->get('estado')
                ->row();

            if ($estadoOrden && in_array($estadoOrden->codigo, array('TNE', 'ENF', 'FAC', 'ANU'))) {
                $this->session->set_flashdata('error', 'La cotización ya no puede modificarse porque su orden de pedido está en un estado no editable');
                redirect('ventas/cotizaciones');
            }
        }

        $tributo = $this->Cotizacion_model->obtener_tributo_igv();

        $data['titulo']             = 'Editar Cotización';
        $data['cotizacion']         = $cotizacion;
        $data['detalle']            = $this->Cotizacion_model->obtener_detalle($id);
        $data['formas_pago']        = $this->Cotizacion_model->obtener_formas_pago();
        $data['tipos_comprobante']  = $this->Cotizacion_model->obtener_tipos_comprobante_venta();
        $data['tributo_igv']        = $tributo;
        $data['almacenes']          = $this->Cotizacion_model->obtener_almacenes_activos();
        $data['orden_asociada']     = $orden;

        $this->layout('ventas/cotizaciones/edit', $data);
    }

    public function update($id) {
        $this->validar_permiso('cotizaciones_editar');

        $cotizacion = $this->Cotizacion_model->obtener($id);

        if (!$cotizacion) {
            show_404();
        }

        $estadoCotizacion = $this->db
            ->where('id', $cotizacion->estado_id)
            ->get('estado')
            ->row();

        if ($estadoCotizacion && $estadoCotizacion->codigo == 'N') {
            $this->session->set_flashdata('error', 'No se puede editar una cotización anulada');
            redirect('ventas/cotizaciones');
        }

        $orden = $this->Cotizacion_model->obtener_orden_pedido_por_cotizacion($id);

        if ($orden) {
            $estadoOrden = $this->db
                ->where('id', $orden->estado_id)
                ->get('estado')
                ->row();

            if ($estadoOrden && in_array($estadoOrden->codigo, array('TNE', 'ENF', 'FAC', 'ANU'))) {
                $this->session->set_flashdata('error', 'La cotización ya no puede modificarse porque su orden de pedido está en un estado no editable');
                redirect('ventas/cotizaciones');
            }
        }

        $this->form_validation->set_rules('cliente_id', 'Cliente', 'required');
        $this->form_validation->set_rules('ctc_fecha', 'Fecha', 'required');
        $this->form_validation->set_rules('ctc_tiempo_entrega', 'Tiempo de entrega', 'required|integer');
        $this->form_validation->set_rules('comprobante_id', 'Tipo de comprobante', 'required');
        $this->form_validation->set_rules('almacen_id', 'Almacén', 'required');
        $this->form_validation->set_rules('tributo_id', 'Tributo', 'required');

        if ($this->form_validation->run() == FALSE) {
            $this->edit($id);
            return;
        }

        $cliente_id = $this->input->post('cliente_id', TRUE);
        $contacto_id = $this->input->post('contacto_id', TRUE);
        $local_id = $this->input->post('local_id', TRUE);
        $vendedor_id = $this->input->post('vendedor_id', TRUE);
        $ctc_fecha = $this->input->post('ctc_fecha', TRUE);
        $ctc_ordcomp_cliente = trim($this->input->post('ctc_ordcomp_cliente', TRUE));
        $ctc_comentarios = trim($this->input->post('ctc_comentarios', TRUE));
        $ctc_tiempo_entrega = (int)$this->input->post('ctc_tiempo_entrega', TRUE);
        $fp_id = $this->input->post('fp_id', TRUE);
        $ctc_fpdetalle = trim($this->input->post('ctc_fpdetalle', TRUE));
        $comprobante_id = $this->input->post('comprobante_id', TRUE);
        $ctc_tipo_coti = $this->input->post('ctc_tipo_coti', TRUE) ?: 'C';
        $tributo_id = $this->input->post('tributo_id', TRUE);
        $modo_tributo = (int)$this->input->post('modo_tributo', TRUE);
        $detalle = $this->input->post('detalle');
        $almacen_id = $this->input->post('almacen_id', TRUE);

        if (empty($detalle) || !is_array($detalle)) {
            $this->session->set_flashdata('error', 'Debes agregar al menos un producto al detalle');
            redirect('ventas/cotizaciones/edit/'.$id);
        }

        $tributo = $this->Cotizacion_model->obtener_tributo_igv();
        if (!$tributo) {
            $this->session->set_flashdata('error', 'No se encontró la configuración del tributo IGV');
            redirect('ventas/cotizaciones/edit/'.$id);
        }

        $igvPorcentaje = (float)$tributo->valor_porcentual;

        $detalleInsert = array();
        $detalleOrdenInsert = array();
        $sumaTotales = 0;

        foreach ($detalle as $item) {
            $producto_id = isset($item['producto_id']) ? (int)$item['producto_id'] : 0;
            $descripcion = isset($item['ctcd_descripcion']) ? trim($item['ctcd_descripcion']) : '';
            $solped = isset($item['ctcd_solped']) ? trim($item['ctcd_solped']) : '';
            $cantidad = isset($item['ctcd_cantidad']) ? (float)$item['ctcd_cantidad'] : 0;
            $precio_unitario = isset($item['ctcd_precio_unitario']) ? (float)$item['ctcd_precio_unitario'] : 0;
            $porcentaje_descuento = isset($item['ctcd_porcentaje_descuento']) ? (float)$item['ctcd_porcentaje_descuento'] : 0;

            if ($producto_id <= 0 || $cantidad <= 0) {
                continue;
            }

            if ($descripcion === '') {
                $producto = $this->Cotizacion_model->obtener_producto($producto_id, $almacen_id);
                $descripcion = $producto ? $producto->nombre : '';
            }

            if ($porcentaje_descuento < 0) {
                $porcentaje_descuento = 0;
            }

            $precio_unitario_descontado = $precio_unitario;
            if ($porcentaje_descuento > 0) {
                $precio_unitario_descontado = $precio_unitario - ($precio_unitario * ($porcentaje_descuento / 100));
            }

            $precio_unitario_descontado = round($precio_unitario_descontado, 4);
            $total = round($cantidad * $precio_unitario_descontado, 2);

            $sumaTotales += $total;

            $detalleInsert[] = array(
                'ctc_id' => $id,
                'producto_id' => $producto_id,
                'ctcd_descripcion' => $descripcion,
                'ctcd_solped' => $solped !== '' ? $solped : null,
                'ctcd_cantidad' => $cantidad,
                'ctcd_precio_unitario' => round($precio_unitario, 4),
                'ctcd_porcentaje_descuento' => round($porcentaje_descuento, 2),
                'ctcd_precio_unitario_descontado' => $precio_unitario_descontado,
                'ctcd_total' => $total,
                'created_by' => $this->session->userdata('id')
            );

            if ($orden) {
                $detalleOrdenInsert[] = array(
                    'orp_id' => $orden->id,
                    'producto_id' => $producto_id,
                    'orpd_descripcion' => $descripcion,
                    'orpd_cantidad' => $cantidad,
                    'orpd_precio_unitario' => $precio_unitario_descontado,
                    'orpd_total' => $total,
                    'estado_id' => $orden->estado_id,
                    'orpd_saldo' => $cantidad,
                    'ctc_id' => $id,
                    'created_by' => $this->session->userdata('id')
                );
            }
        }

        if (empty($detalleInsert)) {
            $this->session->set_flashdata('error', 'No hay detalle válido para actualizar');
            redirect('ventas/cotizaciones/edit/'.$id);
        }

        if ($modo_tributo === 1) {
            $ctc_total = round($sumaTotales, 2);
            $ctc_subtotal = round($ctc_total / (1 + ($igvPorcentaje / 100)), 2);
            $ctc_igv = round($ctc_total - $ctc_subtotal, 2);
        } else {
            $ctc_subtotal = round($sumaTotales, 2);
            $ctc_igv = round($ctc_subtotal * ($igvPorcentaje / 100), 2);
            $ctc_total = round($ctc_subtotal + $ctc_igv, 2);
        }

        $cabecera = array(
            'cliente_id' => $cliente_id,
            'contacto_id' => $contacto_id ? $contacto_id : null,
            'local_id' => $local_id ? $local_id : null,
            'vendedor_id' => $vendedor_id ? $vendedor_id : null,
            'ctc_fecha' => $ctc_fecha,
            'ctc_ordcomp_cliente' => $ctc_ordcomp_cliente !== '' ? $ctc_ordcomp_cliente : null,
            'ctc_comentarios' => $ctc_comentarios !== '' ? $ctc_comentarios : null,
            'ctc_tiempo_entrega' => $ctc_tiempo_entrega,
            'ctc_subtotal' => $ctc_subtotal,
            'ctc_igv_porcentaje' => round($igvPorcentaje, 4),
            'ctc_igv' => $ctc_igv,
            'ctc_total' => $ctc_total,
            'fp_id' => $fp_id ? $fp_id : null,
            'ctc_fpdetalle' => $ctc_fpdetalle !== '' ? $ctc_fpdetalle : null,
            'comprobante_id' => $comprobante_id,
            'ctc_tipo_coti' => $ctc_tipo_coti,
            'tributo_id' => $tributo_id,
            'modo_tributo' => $modo_tributo,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $this->session->userdata('id')
        );

        $this->db->trans_begin();

        $this->Cotizacion_model->actualizar($id, $cabecera);
        $this->Cotizacion_model->eliminar_detalle($id);
        $this->Cotizacion_model->insertar_detalle_batch($detalleInsert);

        if ($orden) {
            $orp_fecha_entrega = date('Y-m-d', strtotime($orden->orp_fecha . ' + ' . (int)$ctc_tiempo_entrega . ' days'));

            $this->Orden_pedido_model->actualizar($orden->id, array(
                'orp_ordcomp_cliente' => $ctc_ordcomp_cliente !== '' ? $ctc_ordcomp_cliente : null,
                'cliente_id' => $cliente_id,
                'contacto_id' => $contacto_id ? $contacto_id : null,
                'local_id' => $local_id ? $local_id : null,
                'orp_fecha_entrega' => $orp_fecha_entrega,
                'orp_comentarios' => $ctc_comentarios !== '' ? $ctc_comentarios : null,
                'orp_total' => $ctc_total,
                'comprobante_id' => $comprobante_id,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));

            $this->Orden_pedido_model->eliminar_detalle($orden->id);
            $this->Orden_pedido_model->insertar_detalle_batch($detalleOrdenInsert);
        }

        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'No se pudo actualizar la cotización');
            redirect('ventas/cotizaciones/edit/'.$id);
        }

        $this->db->trans_commit();

        if ($orden) {
            $this->session->set_flashdata('success', 'Cotización actualizada y sincronizada con la orden de pedido');
        } else {
            $this->session->set_flashdata('success', 'Cotización actualizada correctamente');
        }

        redirect('ventas/cotizaciones');
    }

    public function anular($id) {
        $this->validar_permiso('cotizaciones_anular');

        $cotizacion = $this->Cotizacion_model->obtener($id);

        if (!$cotizacion) {
            show_404();
        }

        $estadoActual = $this->db
            ->where('id', $cotizacion->estado_id)
            ->get('estado')
            ->row();

        if ($estadoActual && $estadoActual->codigo == 'N') {
            $this->session->set_flashdata('error', 'La cotización ya se encuentra anulada');
            redirect('ventas/cotizaciones');
        }

        if ($estadoActual && $estadoActual->codigo == 'A') {
            $this->session->set_flashdata('error', 'No se puede anular una cotización atendida');
            redirect('ventas/cotizaciones');
        }

        $estadoAnulado = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('COTIZACION', 'N');

        if (!$estadoAnulado) {
            $this->session->set_flashdata('error', 'No se encontró el estado ANULADO para cotización');
            redirect('ventas/cotizaciones');
        }

        $this->db->trans_begin();

        $this->Cotizacion_model->actualizar($id, array(
            'estado_id' => $estadoAnulado->id,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $this->session->userdata('id')
        ));

        $this->Cotizacion_model->insertar_estado(array(
            'ctc_id' => $id,
            'estado_id' => $estadoAnulado->id,
            'ctc_fechaestado' => date('Y-m-d H:i:s'),
            'usuario_id' => $this->session->userdata('id')
        ));

        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'No se pudo anular la cotización');
            redirect('ventas/cotizaciones');
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Cotización anulada correctamente');
        redirect('ventas/cotizaciones');
    }

    public function visar($id) {
        $this->validar_permiso('cotizaciones_visar');

        $cotizacion = $this->Cotizacion_model->obtener($id);

        if (!$cotizacion) {
            show_404();
        }

        $accion = $this->input->post('accion', TRUE);
        $orp_ordcomp_cliente = trim($this->input->post('orp_ordcomp_cliente', TRUE));
        $orp_prioridad = (int)$this->input->post('orp_prioridad', TRUE);

        if (!in_array($accion, array('visar', 'visar_generar'))) {
            $this->session->set_flashdata('error', 'Acción no válida');
            redirect('ventas/cotizaciones');
        }

        $estadoActual = $this->db
            ->where('id', $cotizacion->estado_id)
            ->get('estado')
            ->row();

        if (!$estadoActual) {
            $this->session->set_flashdata('error', 'No se encontró el estado actual de la cotización');
            redirect('ventas/cotizaciones');
        }

        if ($estadoActual->codigo == 'N') {
            $this->session->set_flashdata('error', 'No se puede visar una cotización anulada');
            redirect('ventas/cotizaciones');
        }

        if ($estadoActual->codigo == 'A' && $accion == 'visar_generar') {
            $this->session->set_flashdata('error', 'La cotización ya fue atendida');
            redirect('ventas/cotizaciones');
        }

        $estadoVisado = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('COTIZACION', 'V');
        $estadoAtendido = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('COTIZACION', 'A');
        $estadoPedidoGenerado = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('ORDEN PEDIDO', 'GEN');

        if (!$estadoVisado) {
            $this->session->set_flashdata('error', 'No se encontró el estado VISADO');
            redirect('ventas/cotizaciones');
        }

        if ($accion == 'visar_generar' && (!$estadoAtendido || !$estadoPedidoGenerado)) {
            $this->session->set_flashdata('error', 'No se encontraron los estados necesarios para generar pedido');
            redirect('ventas/cotizaciones');
        }

        $detalle = $this->Cotizacion_model->obtener_detalle($id);

        if (empty($detalle)) {
            $this->session->set_flashdata('error', 'La cotización no tiene detalle');
            redirect('ventas/cotizaciones');
        }

        $this->db->trans_begin();

        if ($estadoActual->codigo != 'V' && $estadoActual->codigo != 'A') {
            $this->Cotizacion_model->actualizar($id, array(
                'estado_id' => $estadoVisado->id,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));

            $this->Cotizacion_model->insertar_estado(array(
                'ctc_id' => $id,
                'estado_id' => $estadoVisado->id,
                'ctc_fechaestado' => date('Y-m-d H:i:s'),
                'usuario_id' => $this->session->userdata('id')
            ));
        }

        if ($accion == 'visar_generar') {
            $orp_fecha = date('Y-m-d');
            $diasEntrega = (int)$cotizacion->ctc_tiempo_entrega;
            $orp_fecha_entrega = date('Y-m-d', strtotime($orp_fecha . ' + ' . $diasEntrega . ' days'));

            $orp_id = $this->Orden_pedido_model->insertar_cabecera(array(
                'orp_ordcomp_cliente' => $orp_ordcomp_cliente !== '' ? $orp_ordcomp_cliente : $cotizacion->ctc_ordcomp_cliente,
                'cliente_id' => $cotizacion->cliente_id,
                'contacto_id' => $cotizacion->contacto_id,
                'local_id' => $cotizacion->local_id,
                'orp_fecha' => $orp_fecha,
                'orp_fecha_entrega' => $orp_fecha_entrega,
                'orp_comentarios' => $cotizacion->ctc_comentarios,
                'orp_total' => $cotizacion->ctc_total,
                'comprobante_id' => $cotizacion->comprobante_id,
                'orp_prioridad' => $orp_prioridad,
                'orp_tipo_entrega' => 'TOTAL',
                'ctc_id' => $cotizacion->id,
                'estado_id' => $estadoPedidoGenerado->id,
                'created_by' => $this->session->userdata('id')
            ));

            if (!$orp_id) {
                $this->db->trans_rollback();
                $this->session->set_flashdata('error', 'No se pudo generar la orden de pedido');
                redirect('ventas/cotizaciones');
            }

            $detallePedido = array();

            foreach ($detalle as $item) {
                $detallePedido[] = array(
                    'orp_id' => $orp_id,
                    'producto_id' => $item->producto_id,
                    'orpd_descripcion' => $item->ctcd_descripcion,
                    'orpd_cantidad' => $item->ctcd_cantidad,
                    'orpd_precio_unitario' => $item->ctcd_precio_unitario_descontado,
                    'orpd_total' => $item->ctcd_total,
                    'estado_id' => $estadoPedidoGenerado->id,
                    'orpd_saldo' => $item->ctcd_cantidad,
                    'ctc_id' => $cotizacion->id,
                    'created_by' => $this->session->userdata('id')
                );
            }

            $this->Orden_pedido_model->insertar_detalle_batch($detallePedido);

            $this->Orden_pedido_model->insertar_estado(array(
                'orp_id' => $orp_id,
                'estado_id' => $estadoPedidoGenerado->id,
                'orp_fechaestado' => date('Y-m-d H:i:s'),
                'usuario_id' => $this->session->userdata('id')
            ));

            $this->Cotizacion_model->actualizar($id, array(
                'estado_id' => $estadoAtendido->id,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));

            $this->Cotizacion_model->insertar_estado(array(
                'ctc_id' => $id,
                'estado_id' => $estadoAtendido->id,
                'ctc_fechaestado' => date('Y-m-d H:i:s'),
                'usuario_id' => $this->session->userdata('id')
            ));
        }

        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'Ocurrió un error en el proceso');
            redirect('ventas/cotizaciones');
        }

        $this->db->trans_commit();

        if ($accion == 'visar_generar') {
            $this->session->set_flashdata('success', 'Cotización visada y orden de pedido generada correctamente');
        } else {
            $this->session->set_flashdata('success', 'Cotización visada correctamente');
        }

        redirect('ventas/cotizaciones');
    }

    public function generar_pedido($id) {
        $this->validar_permiso('cotizaciones_visar');

        $cotizacion = $this->Cotizacion_model->obtener($id);

        if (!$cotizacion) {
            show_404();
        }

        $estadoActual = $this->db
            ->where('id', $cotizacion->estado_id)
            ->get('estado')
            ->row();

        if (!$estadoActual) {
            $this->session->set_flashdata('error', 'No se encontró el estado actual de la cotización');
            redirect('ventas/cotizaciones');
        }

        if ($estadoActual->codigo != 'V') {
            $this->session->set_flashdata('error', 'Solo se puede generar pedido desde una cotización VISADA');
            redirect('ventas/cotizaciones');
        }

        $orp_ordcomp_cliente = trim($this->input->post('orp_ordcomp_cliente', TRUE));
        $orp_prioridad = (int)$this->input->post('orp_prioridad', TRUE);

        $estadoAtendido = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('COTIZACION', 'A');
        $estadoPedidoGenerado = $this->Cotizacion_model->obtener_estado_por_tipo_codigo('ORDEN PEDIDO', 'GEN');

        if (!$estadoAtendido || !$estadoPedidoGenerado) {
            $this->session->set_flashdata('error', 'No se encontraron los estados necesarios para generar el pedido');
            redirect('ventas/cotizaciones');
        }

        $detalle = $this->Cotizacion_model->obtener_detalle($id);

        if (empty($detalle)) {
            $this->session->set_flashdata('error', 'La cotización no tiene detalle');
            redirect('ventas/cotizaciones');
        }

        $this->db->trans_begin();

        $orp_fecha = date('Y-m-d');
        $diasEntrega = (int)$cotizacion->ctc_tiempo_entrega;
        $orp_fecha_entrega = date('Y-m-d', strtotime($orp_fecha . ' + ' . $diasEntrega . ' days'));

        $orp_id = $this->Orden_pedido_model->insertar_cabecera(array(
            'orp_ordcomp_cliente' => $orp_ordcomp_cliente !== '' ? $orp_ordcomp_cliente : $cotizacion->ctc_ordcomp_cliente,
            'cliente_id' => $cotizacion->cliente_id,
            'contacto_id' => $cotizacion->contacto_id,
            'local_id' => $cotizacion->local_id,
            'orp_fecha' => $orp_fecha,
            'orp_fecha_entrega' => $orp_fecha_entrega,
            'orp_comentarios' => $cotizacion->ctc_comentarios,
            'orp_total' => $cotizacion->ctc_total,
            'comprobante_id' => $cotizacion->comprobante_id,
            'orp_prioridad' => $orp_prioridad,
            'orp_tipo_entrega' => 'TOTAL',
            'ctc_id' => $cotizacion->id,
            'estado_id' => $estadoPedidoGenerado->id,
            'created_by' => $this->session->userdata('id')
        ));

        if (!$orp_id) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'No se pudo generar la orden de pedido');
            redirect('ventas/cotizaciones');
        }

        $detallePedido = array();

        foreach ($detalle as $item) {
            $detallePedido[] = array(
                'orp_id' => $orp_id,
                'producto_id' => $item->producto_id,
                'orpd_descripcion' => $item->ctcd_descripcion,
                'orpd_cantidad' => $item->ctcd_cantidad,
                'orpd_precio_unitario' => $item->ctcd_precio_unitario_descontado,
                'orpd_total' => $item->ctcd_total,
                'estado_id' => $estadoPedidoGenerado->id,
                'orpd_saldo' => $item->ctcd_cantidad,
                'ctc_id' => $cotizacion->id,
                'created_by' => $this->session->userdata('id')
            );
        }

        $this->Orden_pedido_model->insertar_detalle_batch($detallePedido);

        $this->Orden_pedido_model->insertar_estado(array(
            'orp_id' => $orp_id,
            'estado_id' => $estadoPedidoGenerado->id,
            'orp_fechaestado' => date('Y-m-d H:i:s'),
            'usuario_id' => $this->session->userdata('id')
        ));

        $this->Cotizacion_model->actualizar($id, array(
            'estado_id' => $estadoAtendido->id,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $this->session->userdata('id')
        ));

        $this->Cotizacion_model->insertar_estado(array(
            'ctc_id' => $id,
            'estado_id' => $estadoAtendido->id,
            'ctc_fechaestado' => date('Y-m-d H:i:s'),
            'usuario_id' => $this->session->userdata('id')
        ));

        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'Ocurrió un error al generar la orden de pedido');
            redirect('ventas/cotizaciones');
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Orden de pedido generada correctamente desde la cotización');
        redirect('ventas/orden-pedido/ver/' . $orp_id);
    }


    
}