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

class Comprobante_model extends CI_Model {

    public function listar($grupo = 'comprobantes') {
        $this->db
            ->select('
                c.*,
                tc.nombre as tipo_comprobante_nombre,
                tc.codigo as tipo_comprobante_codigo,
                cli.razon_social as cliente_nombre,
                e.nombre as estado_nombre
            ')
            ->from('vt_comprobante c')
            ->join('mt_tipo_comprobante tc', 'tc.id = c.comprobante_id')
            ->join('vt_cliente cli', 'cli.id = c.cliente_id')
            ->join('estado e', 'e.id = c.estado_id', 'left');

        if ($grupo === 'comprobantes') {
            $this->db->where_in('c.comprobante_id', array(1, 2));
        } elseif ($grupo === 'nota_venta') {
            $this->db->where('c.comprobante_id', 10);
        }
        // si es 'todos' no aplica filtro

        return $this->db
            ->order_by('c.id', 'DESC')
            ->get()
            ->result();
    }

    public function listar_tipos_comprobante_venta() {
        return $this->db
            ->where_in('id', array(1, 2, 10))
            ->where('estado', 1)
            ->where('grupo', 'VENTA')
            ->order_by('id', 'ASC')
            ->get('mt_tipo_comprobante')
            ->result();
    }

    public function listar_formas_pago() {
        return $this->db
            ->where('estado', 1)
            ->order_by('nombre', 'ASC')
            ->get('mt_forma_pago')
            ->result();
    }

    public function obtener_tributo_igv() {
        return $this->db
            ->where('id', 2)
            ->where('estado', 1)
            ->get('mt_tributo')
            ->row();
    }

    public function obtener_tipo_comprobante($id) {
        return $this->db
            ->where('id', $id)
            ->where('estado', 1)
            ->get('mt_tipo_comprobante')
            ->row();
    }

    public function obtener_tipo_comprobante_for_update($id) {
        return $this->db->query("SELECT * FROM mt_tipo_comprobante WHERE id = ? AND estado = 1 FOR UPDATE", array($id))->row();
    }

    public function actualizar_correlativo_tipo_comprobante($id, $nuevoCorrelativo) {
        return $this->db
            ->where('id', $id)
            ->update('mt_tipo_comprobante', array(
                'correlativo_actual' => $nuevoCorrelativo
            ));
    }

    public function obtener_forma_pago($id) {
        return $this->db
            ->where('id', $id)
            ->where('estado', 1)
            ->get('mt_forma_pago')
            ->row();
    }

    public function obtener_cliente($id) {
        return $this->db
            ->where('id', $id)
            ->get('vt_cliente')
            ->row();
    }

    public function buscar_clientes($term) {
        return $this->db
            ->select('
                c.*,
                m.nombre as moneda_nombre,
                CONCAT(IFNULL(v.apellidos, ""), " ", IFNULL(v.nombres, "")) as vendedor_nombre,
                r.porcentaje as retencion_porcentaje,
                r.monto_minimo as retencion_monto_minimo
            ')
            ->from('vt_cliente c')
            ->join('mt_moneda m', 'm.id = c.moneda_id', 'left')
            ->join('rh_empleado v', 'v.id = c.vendedor_id', 'left')
            ->join('vt_cliente_retencion r', 'r.cliente_id = c.id AND r.estado = 1', 'left')
            ->group_start()
                ->like('c.razon_social', $term)
                ->or_like('c.nro_documento', $term)
            ->group_end()
            ->where('c.estado', 1)
            ->order_by('c.razon_social', 'ASC')
            ->limit(20)
            ->get()
            ->result();
    }

    public function buscar_productos($term) {
        return $this->db
            ->select('
                p.*,
                um.abreviado as um_abreviado,
                IFNULL(SUM(pa.cantidad_stock), 0) as stock,
                d.codigo as detraccion_codigo,
                d.nombre as detraccion_nombre,
                d.porcentaje as detraccion_porcentaje,
                d.monto_minimo as detraccion_monto_minimo
            ')
            ->from('vt_producto p')
            ->join('mt_unidad_medida um', 'um.id = p.um_id_venta', 'left')
            ->join('vt_producto_almacen pa', 'pa.producto_id = p.id', 'left')
            ->join('mt_detraccion d', 'd.id = p.detraccion_id', 'left')
            ->group_start()
                ->like('p.nombre', $term)
                ->or_like('p.codigo', $term)
            ->group_end()
            ->where('p.estado', 1)
            ->where('p.activo_venta', 1)
            ->group_by('p.id')
            ->order_by('p.nombre', 'ASC')
            ->limit(20)
            ->get()
            ->result();
    }

    public function obtener_producto($id) {
        return $this->db
            ->select('
                p.*,
                d.codigo as detraccion_codigo,
                d.nombre as detraccion_nombre,
                d.porcentaje as detraccion_porcentaje,
                d.monto_minimo as detraccion_monto_minimo
            ')
            ->from('vt_producto p')
            ->join('mt_detraccion d', 'd.id = p.detraccion_id', 'left')
            ->where('p.id', $id)
            ->get()
            ->row();
    }

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

        if ($cantidad >= 1 && $cantidad <= 11) {
            return (float)$producto->precio_unidad;
        }

        if ($cantidad >= 12 && $cantidad <= 24) {
            return (float)$producto->precio_doce;
        }

        if ($cantidad >= 25 && $cantidad <= 49) {
            return (float)$producto->precio_veinticinco;
        }

        if ($cantidad >= 50 && $cantidad <= 99) {
            return (float)$producto->precio_cincuenta;
        }

        if ($cantidad >= 100 && $cantidad <= 999) {
            return (float)$producto->precio_cien;
        }

        if ($cantidad >= 1000) {
            return (float)$producto->precio_millar;
        }

        return (float)$producto->precio_unidad;
    }

    public function insertar($data) {
        $this->db->insert('vt_comprobante', $data);
        return $this->db->insert_id();
    }

    public function insertar_detalle($data) {
        return $this->db->insert('vt_comprobante_detalle', $data);
    }

    public function insertar_cuota($data) {
        return $this->db->insert('vt_comprobante_cuota', $data);
    }

    public function insertar_estado($data) {
        return $this->db->insert('vt_comprobante_estado', $data);
    }

    public function obtener_retencion_cliente($cliente_id) {
        return $this->db
            ->where('cliente_id', $cliente_id)
            ->where('estado', 1)
            ->get('vt_cliente_retencion')
            ->row();
    }

    public function insertar_retencion($data) {
        return $this->db->insert('vt_comprobante_retencion', $data);
    } 

    public function obtener_detraccion($id) {
        return $this->db
            ->where('id', $id)
            ->where('estado', 1)
            ->get('mt_detraccion')
            ->row();
    }   

    public function insertar_detraccion($data) {
        return $this->db->insert('vt_comprobante_detraccion', $data);
    }

    public function obtener_completo($id) {
        return $this->db
            ->select('
                c.*,
                tc.nombre as tipo_comprobante_nombre,
                tc.nombre_corto as tipo_comprobante_corto,
                tc.codigo as tipo_comprobante_codigo,
                cli.razon_social as cliente_nombre,
                cli.nro_documento as cliente_nro_documento,
                cli.domicilio_fiscal as cliente_domicilio_fiscal,
                m.nombre as moneda_nombre,
                m.abreviado as moneda_abreviado,
                fp.nombre as forma_pago_nombre,
                fp.codigo as forma_pago_codigo,
                CONCAT(IFNULL(v.apellidos, ""), " ", IFNULL(v.nombres, "")) as vendedor_nombre,
                e.nombre as estado_nombre
            ')
            ->from('vt_comprobante c')
            ->join('mt_tipo_comprobante tc', 'tc.id = c.comprobante_id')
            ->join('vt_cliente cli', 'cli.id = c.cliente_id')
            ->join('mt_moneda m', 'm.id = c.moneda_id', 'left')
            ->join('mt_forma_pago fp', 'fp.id = c.fp_id', 'left')
            ->join('rh_empleado v', 'v.id = c.vendedor_id', 'left')
            ->join('estado e', 'e.id = c.estado_id', 'left')
            ->where('c.id', $id)
            ->get()
            ->row();
    }

    public function obtener_detalle($comprob_id) {
        return $this->db
            ->select('
                d.*,
                p.codigo as producto_codigo,
                p.nombre as producto_nombre,
                um.abreviado as unidad_abreviada
            ')
            ->from('vt_comprobante_detalle d')
            ->join('vt_producto p', 'p.id = d.producto_id', 'left')
            ->join('mt_unidad_medida um', 'um.id = p.um_id_venta', 'left')
            ->where('d.comprob_id', $comprob_id)
            ->order_by('d.id', 'ASC')
            ->get()
            ->result();
    }
    public function obtener_cuotas($comprob_id) {
        return $this->db
            ->where('comprob_id', $comprob_id)
            ->order_by('nro_cuota', 'ASC')
            ->get('vt_comprobante_cuota')
            ->result();
    }

    public function obtener_retencion_por_comprobante($comprob_id) {
        return $this->db
            ->where('comprob_id', $comprob_id)
            ->get('vt_comprobante_retencion')
            ->row();
    }

    public function obtener_detraccion_por_comprobante($comprob_id) {
        return $this->db
            ->select('
                d.*,
                md.codigo as detraccion_codigo,
                md.nombre as detraccion_nombre
            ')
            ->from('vt_comprobante_detraccion d')
            ->join('mt_detraccion md', 'md.id = d.detraccion_id', 'left')
            ->where('d.comprob_id', $comprob_id)
            ->get()
            ->row();
    }

    public function obtener_historial_estados($comprob_id) {
        return $this->db
            ->select('
                ce.*,
                e.nombre as estado_nombre,
                u.usuario
            ')
            ->from('vt_comprobante_estado ce')
            ->join('estado e', 'e.id = ce.estado_id', 'left')
            ->join('usuarios u', 'u.id = ce.usuario_id', 'left')
            ->where('ce.comprob_id', $comprob_id)
            ->order_by('ce.id', 'ASC')
            ->get()
            ->result();
    }   

    public function insertar_relacion_orden($data) {
        return $this->db->insert('vt_comprobante_orp', $data);
    }

    public function obtener_total_anticipos_orden($orp_id) {
        $row = $this->db
            ->select('IFNULL(SUM(monto_aplicado), 0) as total_anticipos')
            ->from('vt_comprobante_orp')
            ->where('orp_id', $orp_id)
            ->where('tipo_relacion', 'ANTICIPO')
            ->where('estado', 1)
            ->get()
            ->row();

        return $row ? (float)$row->total_anticipos : 0;
    }

    public function obtener_anticipos_orden($orp_id) {
        return $this->db
            ->select('
                r.*,
                c.serie,
                c.numero,
                c.fecha,
                c.total,
                c.estado_id
            ')
            ->from('vt_comprobante_orp r')
            ->join('vt_comprobante c', 'c.id = r.comprob_id')
            ->where('r.orp_id', $orp_id)
            ->where('r.tipo_relacion', 'ANTICIPO')
            ->where('r.estado', 1)
            ->order_by('r.id', 'ASC')
            ->get()
            ->result();
    }

    public function insertar_relacion_orden_detalle($data) {
        return $this->db->insert('vt_comprobante_orp_detalle', $data);
    }

    public function obtener_total_facturado_detalle_orden($orpd_id) {
        $row = $this->db
            ->select('IFNULL(SUM(cantidad_facturada), 0) as total_facturado')
            ->from('vt_comprobante_orp_detalle')
            ->where('orpd_id', $orpd_id)
            ->where('estado', 1)
            ->get()
            ->row();

        return $row ? (float)$row->total_facturado : 0;
    }

    public function obtener($id) {
        return $this->db
            ->where('id', $id)
            ->get('vt_comprobante')
            ->row();
    }

    public function actualizar($id, $data) {
        return $this->db
            ->where('id', $id)
            ->update('vt_comprobante', $data);
    }

    public function obtener_relacion_orden($comprob_id) {
        return $this->db
            ->where('comprob_id', $comprob_id)
            ->where('estado', 1)
            ->get('vt_comprobante_orp')
            ->row();
    }

    public function desactivar_relacion_orden($comprob_id) {
        return $this->db
            ->where('comprob_id', $comprob_id)
            ->update('vt_comprobante_orp', array(
                'estado' => 0,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));
    }

    public function obtener_relaciones_orden_detalle($comprob_id) {
        return $this->db
            ->where('comprob_id', $comprob_id)
            ->where('estado', 1)
            ->get('vt_comprobante_orp_detalle')
            ->result();
    }

    public function desactivar_relacion_orden_detalle($comprob_id) {
        return $this->db
            ->where('comprob_id', $comprob_id)
            ->update('vt_comprobante_orp_detalle', array(
                'estado' => 0
            ));
    }

    public function listar_almacenes() {
        return $this->db->where('estado', 1)->order_by('nombre', 'ASC')->get('mt_almacen')->result();
    }
}