-- ============================================
-- MIGRACIÓN: Actualizar stored procedure para guardar snapshot
-- Fecha: 2026-01-21
-- ============================================

DROP PROCEDURE IF EXISTS calulo_boleta;

DELIMITER //

CREATE PROCEDURE `calulo_boleta`(IN socio INT, IN lant INT, IN lact INT)
BEGIN
    DECLARE total_mes_actual INT(11);
    DECLARE subsidio_total INT(11);
    DECLARE consumo INT(11);
    DECLARE subsidio_consumo INT(11);
    DECLARE consumo_M3 INT(11);
    DECLARE estado_cocio INT(11);
    DECLARE prox_id_boletas INT(11);
    DECLARE saldo_anteriores INT(11);
    DECLARE total_boletas INT(11);
    DECLARE total_multas INT(11);
    DECLARE Multa_Atrasos INT(11);
    DECLARE porcentaje_impuesto INT(11);
    DECLARE counter INT(11);
    DECLARE precio_cuotas INT(11);
    DECLARE cant_cuotas INT(11);
    DECLARE ult_repac_fac INT(11);
    
    DECLARE tramo_uno INT(11);
    DECLARE tramo_dos INT(11);
    DECLARE tramo_tres INT(11);
    DECLARE valor_uno INT(11);
    DECLARE valor_metro3 INT(11);
    DECLARE metraje_base INT(11) DEFAULT 0;
    DECLARE metraje_tramo1 INT(11) DEFAULT 0;
    DECLARE metraje_tramo2 INT(11) DEFAULT 0;
    DECLARE metraje_tramo3 INT(11) DEFAULT 0;
    
    DECLARE lim_sub INT(11);
    DECLARE cargo_mortuoria INT(11);
    DECLARE subsidio_cargo_fijo INT(11);
    DECLARE fecha_venc VARCHAR(20);
    DECLARE cargo_fijos INT(11);
    DECLARE alcantarillados INT(11);
    
    DECLARE porcent_multa INT(11);
    DECLARE tipo_de_multa INT(11);
    DECLARE estado_atraso INT(11);
    DECLARE estado_corte INT(11);
    DECLARE estado_matriz INT(11);
    
    DECLARE tipo_doctos INT(11);
    DECLARE numero_del_medidor VARCHAR(50);
    DECLARE fecha_ing_lectura DATE;
    DECLARE comuna_clie INT(11);
    
    -- Variables para snapshot
    DECLARE cliente_nombre VARCHAR(255);
    DECLARE cliente_rut VARCHAR(50);
    DECLARE cliente_direccion VARCHAR(255);
    DECLARE cliente_ciudad VARCHAR(100);
    DECLARE cliente_sector_nombre VARCHAR(100);
    DECLARE apr_nombre VARCHAR(255);
    DECLARE apr_rut VARCHAR(50);
    DECLARE apr_direccion VARCHAR(255);
    DECLARE apr_comuna VARCHAR(100);
    DECLARE apr_telefono VARCHAR(50);
    DECLARE apr_representante VARCHAR(255);
    DECLARE apr_telefono_rep VARCHAR(50);
    
    SET consumo_M3 = lact - lant;
    
    SELECT fecha_ingreso_lectura INTO fecha_ing_lectura 
    FROM lecturas_clie_mensual 
    WHERE id_cliente = socio AND estado_pago = 0 
    LIMIT 1;

    SELECT inicio1 INTO tramo_uno FROM vista_ingreso_lecturas WHERE Id_cliente = socio;

    IF tramo_uno > 1 THEN
        SELECT inicio2 INTO tramo_dos FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
        SELECT inicio3 INTO tramo_tres FROM vista_ingreso_lecturas WHERE Id_cliente = socio;

        IF 0 < consumo_M3 THEN
            SELECT precio_metro_cubico * (lact - lant) INTO metraje_base 
            FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
        END IF;

        SELECT precio_metro_cubico INTO valor_metro3 FROM vista_ingreso_lecturas WHERE Id_cliente = socio;

        IF tramo_uno <= consumo_M3 THEN
            SELECT sobreconsumo1 INTO valor_uno FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
            SET metraje_base = (tramo_uno - 1) * valor_metro3;
            SET metraje_tramo1 = (consumo_M3 + 1 - tramo_uno) * valor_uno;
        ELSE
            SET metraje_tramo1 = 0;
        END IF;

        SET consumo = metraje_base + metraje_tramo1 + metraje_tramo2 + metraje_tramo3;
    END IF;

    -- Obtener datos del cliente para snapshot
    SELECT c.nombre_cliente, c.rut_cliente, c.direccion, ci.nombre_ciudad, s.nombre_sector, c.id_ciudad, c.id_tipo_documento, c.numero_medidor
        INTO cliente_nombre, cliente_rut, cliente_direccion, cliente_ciudad, cliente_sector_nombre, comuna_clie, tipo_doctos, numero_del_medidor
    FROM clientes c
    LEFT JOIN ciudades ci ON c.id_ciudad = ci.Id_ciudades
    LEFT JOIN sectores s ON c.sector = s.id_sector
    WHERE c.Id_cliente = socio;

    -- Obtener datos del APR para snapshot
    SELECT da.Nombre_servicio, da.rut_servicio, da.Direccion, co.nombre_comuna, da.telefono_oficina, da.Representante_legal, da.fono_contacto
        INTO apr_nombre, apr_rut, apr_direccion, apr_comuna, apr_telefono, apr_representante, apr_telefono_rep
    FROM datos_apr da
    LEFT JOIN comunas co ON da.Id_comunas = co.Id_comunas
    LIMIT 1;

    SELECT limite_subisidio INTO lim_sub FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
    SELECT (cuota_mortuoria * valor_cuota_mortuoria) INTO cargo_mortuoria FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
    SELECT (cargo_fijo_caneria * (porcentaje_subsidio) / 100) INTO subsidio_cargo_fijo FROM vista_ingreso_lecturas WHERE Id_cliente = socio;

    SELECT CONCAT(MID(DATE_ADD(NOW(), INTERVAL 1 MONTH),1,8),fecha_facturacion) INTO fecha_venc FROM datos_apr;
    SELECT cargo_fijo_caneria INTO cargo_fijos FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
    SELECT alcantarillado INTO alcantarillados FROM vista_ingreso_lecturas WHERE Id_cliente = socio;

    IF consumo_M3 <= lim_sub THEN
        SELECT TRUNCATE((consumo_M3 * (porcentaje_subsidio) / 100) * precio_metro_cubico, 0) INTO subsidio_consumo 
        FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
    ELSE
        SELECT TRUNCATE((limite_subisidio * (porcentaje_subsidio) / 100) * precio_metro_cubico, 0) INTO subsidio_consumo 
        FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
    END IF;

    IF tramo_uno > 1 THEN
        SET total_mes_actual = (consumo - subsidio_consumo) + alcantarillados + cargo_mortuoria + (cargo_fijos - subsidio_cargo_fijo);
    ELSE
        SELECT TRUNCATE((precio_metro_cubico * consumo_M3 - subsidio_consumo) + alcantarillado + cargo_mortuoria + (cargo_fijo_caneria - (cargo_fijo_caneria * (porcentaje_subsidio) / 100)),0) 
        INTO total_mes_actual FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
    END IF;

    SET subsidio_total = subsidio_cargo_fijo + subsidio_consumo;

    SELECT COUNT(fecha) INTO saldo_anteriores FROM deudas 
    WHERE Id_cliente = socio 
    AND EXTRACT(YEAR_MONTH FROM fecha) = EXTRACT(YEAR_MONTH FROM DATE_SUB(CURDATE(),INTERVAL 1 MONTH)) 
    AND estado_deuda = 5;

    IF saldo_anteriores > 0 THEN
        SELECT monto INTO saldo_anteriores FROM deudas 
        WHERE Id_cliente = socio 
        AND EXTRACT(YEAR_MONTH FROM fecha) = EXTRACT(YEAR_MONTH FROM DATE_SUB(CURDATE(),INTERVAL 1 MONTH)) 
        AND estado_deuda = 5;
    END IF;

    SELECT porcentaje_multa, tipo_multa INTO porcent_multa, tipo_de_multa FROM datos_apr;
    SELECT multa_atraso, multa_corte, multa_matriz INTO estado_atraso, estado_corte, estado_matriz 
    FROM multas_socio WHERE Id_multas = socio;
    
    IF tipo_de_multa = 0 THEN
        SELECT (multa_atraso * estado_atraso) + (corte_reposicion * estado_corte) + (corte_matriz * estado_matriz) 
        INTO total_multas FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
        SELECT (multa_atraso * estado_atraso) INTO Multa_Atrasos FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
    ELSE
        SELECT (TRUNCATE((saldo_anteriores * porcent_multa / 100),0) * estado_atraso) + (corte_reposicion * estado_corte) + (corte_matriz * estado_matriz) 
        INTO total_multas FROM vista_ingreso_lecturas WHERE Id_cliente = socio;
        SET Multa_Atrasos = (saldo_anteriores * porcent_multa / 100) * estado_atraso;
    END IF;

    SET total_mes_actual = total_mes_actual + Multa_Atrasos;
    SET total_boletas = total_mes_actual + saldo_anteriores;

    SELECT impuesto INTO porcentaje_impuesto FROM vista_ingreso_lecturas, tipo_documento 
    WHERE Id_cliente = socio AND Id_doc = id_tipo_documento;
    
    IF porcentaje_impuesto > 0 THEN
        SET total_mes_actual = total_mes_actual + (total_mes_actual * porcentaje_impuesto / 100);
    END IF;

    SELECT AUTO_INCREMENT INTO prox_id_boletas 
    FROM information_schema.TABLES 
    WHERE TABLE_SCHEMA='071_bsaires' AND TABLE_NAME='boletas';

    UPDATE lecturas_clie_mensual SET id_boleta = prox_id_boletas 
    WHERE id_cliente = socio AND estado_pago = 0;

    SELECT COUNT(Id_repactacion) INTO counter FROM repactaciones 
    WHERE Id_cliente = socio AND estado_repactacion = 0;
    
    IF counter > 0 THEN
        SELECT valor_cuota, no_cuotas, ult_cuota_facturada INTO precio_cuotas, cant_cuotas, ult_repac_fac 
        FROM repactaciones WHERE Id_cliente = socio AND estado_repactacion = 0;
        
        IF ult_repac_fac + 1 = cant_cuotas THEN
            UPDATE repactaciones SET ult_cuota_facturada = cant_cuotas, estado_repactacion = 1 
            WHERE Id_cliente = socio AND estado_repactacion = 0;
        ELSE
            UPDATE repactaciones SET ult_cuota_facturada = ult_cuota_facturada + 1 
            WHERE Id_cliente = socio AND estado_repactacion = 0;
        END IF;
    ELSE
        SET precio_cuotas = 0;
    END IF;

    INSERT INTO deudas
        (Id_cliente, Id_boleta, fecha, monto, respaldo_monto, estado_deuda, saldo, respaldo_saldo, estado_saldo) 
    VALUES
        (socio, prox_id_boletas, CURDATE(), total_boletas, 0, 5, saldo_anteriores, 0, 5);

    -- INSERT normalizado en boletas
    INSERT INTO boletas
        (num_boleta, id_cliente, tipo_de_docto, fecha_a_pagar, fecha_vencimiento, 
         lectura_ant_m3, lectura_act_m3, cosumo_m3, total_mes_act, cargo_fijo, 
         alcantarillado, subsidio, consumo, saldo_anterior, total_boleta, estado_pago, 
         cuota_mortuoria, donaciones, multa_atraso, tramo_base, tramo1, tramo2, tramo3, 
         subsidio1, subsidio2, subsidio3, subsidio4, subsidio5, repactacion, 
         fecha_toma_lectura, num_medidor, repactaciones) 
    VALUES
        (0, socio, tipo_doctos, CURDATE(), fecha_venc, 
         lant, lact, consumo_M3, total_mes_actual, cargo_fijos, 
         alcantarillados, subsidio_total, consumo, saldo_anteriores, total_boletas, 5, 
         cargo_mortuoria, 0, Multa_Atrasos, metraje_base, metraje_tramo1, metraje_tramo2, metraje_tramo3, 
         subsidio_consumo, 0, 0, 0, 0, 0, 
         fecha_ing_lectura, numero_del_medidor, precio_cuotas);

    -- NUEVO: Guardar snapshot histórico (CONCAT para MySQL 5.6)
    INSERT INTO boletas_snapshot (id_boleta, snapshot_datos, fecha_creacion)
    VALUES (
        prox_id_boletas,
        CONCAT(
            '{"datos_cliente":{"nombre":"', IFNULL(cliente_nombre, ''), '",',
            '"rut":"', IFNULL(cliente_rut, ''), '",',
            '"direccion":"', IFNULL(cliente_direccion, ''), '",',
            '"ciudad":"', IFNULL(cliente_ciudad, ''), '",',
            '"sector":"', IFNULL(cliente_sector_nombre, ''), '",',
            '"numero_medidor":"', IFNULL(numero_del_medidor, ''), '"},',
            '"datos_apr":{"nombre_servicio":"', IFNULL(apr_nombre, ''), '",',
            '"rut_servicio":"', IFNULL(apr_rut, ''), '",',
            '"direccion_servicio":"', IFNULL(apr_direccion, ''), '",',
            '"comuna_servicio":"', IFNULL(apr_comuna, ''), '",',
            '"telefono_oficina":"', IFNULL(apr_telefono, ''), '",',
            '"representante_legal":"', IFNULL(apr_representante, ''), '",',
            '"telefono_representante":"', IFNULL(apr_telefono_rep, ''), '"},',
            '"datos_boleta":{"num_boleta":0,',
            '"fecha_emision":"', CURDATE(), '",',
            '"fecha_vencimiento":"', IFNULL(fecha_venc, ''), '",',
            '"total_boleta":', IFNULL(total_boletas, 0), ',',
            '"estado_pago":5,',
            '"lectura_anterior":', IFNULL(lant, 0), ',',
            '"lectura_actual":', IFNULL(lact, 0), ',',
            '"consumo_m3":', IFNULL(consumo_M3, 0), '}}'
        ),
        CURDATE()
    );

    SELECT estado_socio INTO estado_cocio FROM clientes WHERE Id_cliente = socio;
    IF estado_cocio < 3 THEN
        UPDATE clientes SET estado_socio = estado_socio + 1 WHERE id_cliente = socio;
    END IF;
    
    COMMIT;
END //

DELIMITER ;
