-- SP_PrestacionesImed
CREATE PROCEDURE [Clinica].[SP_PrestacionesImed]
    @FechaDesde         DATETIME,
    @FechaHasta         DATETIME,
    @IdProfesional      INT = NULL,
    @IdProfesionalOrden INT = NULL,
    @IdTipoPrestacion   VARCHAR(100) = NULL,
    @IdCaja             INT = NULL
AS
BEGIN
    SET NOCOUNT ON;

    -- Pre-calcular rango ordinal de lpv por (IdCita, CodPrestacion)
    -- Evita subconsultas correlacionadas anidadas que se ejecutan N veces por fila
    WITH LpvOrden AS (
        SELECT
            lpv.IdListaPrestVta,
            bi.IdCita,
            lpv.CodPrestacion,
            ROW_NUMBER() OVER (PARTITION BY bi.IdCita, lpv.CodPrestacion ORDER BY lpv.IdListaPrestVta) AS rn_lpv
        FROM Imed.ListaPrestVta lpv
        JOIN Imed.ListaBono lb ON lb.IdListaBono = lpv.IdListaBono
        JOIN Imed.BonoInterfaz bi ON bi.IdBonoInterfaz = lb.IdBonoInterfaz
    ),
    -- Pre-calcular nombre de prestacion por (IdCita, CodPrestacion, rn) desde CitaFichaEvolucionExamen
    CfeeOrden AS (
        SELECT
            cfee.IdCita,
            p.CodigoFonasa,
            p.Descripcion,
            ROW_NUMBER() OVER (PARTITION BY cfee.IdCita, p.CodigoFonasa ORDER BY cfee.IdCitaFichaEvolucionExamen) AS rn_cfee
        FROM Clinica.CitaFichaEvolucionExamen cfee
        JOIN Clinica.Prestacion p ON p.IdPrestacion = cfee.IdPrestacion
    )
    SELECT
        bq.IdMovimientoCaja, bq.Identificador, bq.IdCaja, bq.Caja,
        bq.IdTipoEstadoCaja, bq.TipoEstadoCaja, bq.RutCajero, bq.NombreCajero,
        bq.FechaMovimiento, bq.HoraMovimiento, bq.IdProfesional, bq.OrigenBono,
        bq.RutProfesional, bq.NombreProfesional, bq.IdProfesionalOrden_Potencial,
        bq.IdProfesionalOrden, bq.RutProfesionalOrden, bq.NombreProfesionalOrden,
        bq.RutPaciente, bq.NombrePaciente, bq.CodigoPrestacion, bq.NombrePrestacion,
        bq.IdTipoPrestacion, bq.TipoPrestacion, bq.Modalidad, bq.SistemaSalud,
        bq.Isapre, bq.NroBono, bq.FechaEmision, bq.FechaRecepcion, bq.Valor,
        bq.MontoPagadoPrevision, bq.MontoCopago, bq.SeguroComplementario,
        bq.Excedentes, bq.TotalPagado, bq.IdTipoCopago, bq.TipoCopago
    FROM (
        SELECT
            mc.IdMovimientoCaja,
            CASE WHEN mc.IdPresupuesto IS NOT NULL
                THEN CONVERT(VARCHAR,'P-'+CONVERT(VARCHAR,mc.IdPresupuesto))
                ELSE CONVERT(VARCHAR,'C-'+CONVERT(VARCHAR,mc.IdCita))
            END AS Identificador,
            cc.IdCaja,
            caja.Descripcion AS Caja,
            ec.IdTipoEstadoCaja,
            ec.Descripcion AS TipoEstadoCaja,
            '' AS RutCajero,
            usuario.LoginName AS NombreCajero,
            mc.FechaMovimiento,
            FORMAT(mc.FechaMovimiento,'HH:mm') AS HoraMovimiento,
            CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.IdProfesional
                 ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN cita.IdProfesionalExterno ELSE profesionalOrigen.IdProfesional END
            END AS IdProfesional,
            CASE WHEN mc.OrigenBono = 'Particular' THEN '' ELSE mc.OrigenBono END AS OrigenBono,
            CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.Rut
                 ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN profesionalExterno.Rut ELSE profesionalOrigen.Rut END
            END AS RutProfesional,
            CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.Nombres+' '+profesional.Apellidos
                 ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN profesionalExterno.Nombres+' '+profesionalExterno.Apellidos ELSE profesionalOrigen.Nombres+' '+profesionalOrigen.Apellidos END
            END AS NombreProfesional,
            CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.IdProfesional
                 WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.IdProfesional
                 ELSE NULL
            END AS IdProfesionalOrden_Potencial,
            CASE WHEN (CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.IdProfesional WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.IdProfesional ELSE NULL END)
                    = (CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.IdProfesional ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN cita.IdProfesionalExterno ELSE profesionalOrigen.IdProfesional END END)
                 THEN NULL
                 ELSE CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.IdProfesional WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.IdProfesional ELSE NULL END
            END AS IdProfesionalOrden,
            CASE WHEN (CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.IdProfesional WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.IdProfesional ELSE NULL END)
                    = (CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.IdProfesional ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN cita.IdProfesionalExterno ELSE profesionalOrigen.IdProfesional END END)
                 THEN '-'
                 ELSE CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.Rut WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.Rut ELSE '-' END
            END AS RutProfesionalOrden,
            CASE WHEN (CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.IdProfesional WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.IdProfesional ELSE NULL END)
                    = (CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.IdProfesional ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN cita.IdProfesionalExterno ELSE profesionalOrigen.IdProfesional END END)
                 THEN '-'
                 ELSE CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.Nombres+' '+profesionalFichaEvolucion.Apellidos WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.Nombres+' '+profesionalExterno.Apellidos ELSE '-' END
            END AS NombreProfesionalOrden,
            paciente.Rut AS RutPaciente,
            paciente.Nombres+' '+paciente.Apellidos AS NombrePaciente,
            lpv.CodPrestacion AS CodigoPrestacion,
            CASE
                WHEN lpv.Cantidad > 1 THEN
                    ISNULL(cfeeMatch.Descripcion, prestacion.Descripcion)
                    + ' x' + CAST(lpv.Cantidad AS VARCHAR(10))
                ELSE
                    ISNULL(cfeeMatch.Descripcion, prestacion.Descripcion)
            END AS NombrePrestacion,
            tp.IdTipoPrestacion,
            tp.Descripcion AS TipoPrestacion,
            tmp.Descripcion AS Modalidad,
            sistemaSalud.Descripcion AS SistemaSalud,
            isapre.Descripcion AS Isapre,
            CAST(lb.FolioBono AS VARCHAR(100)) AS NroBono,
            FORMAT(lb.FecEmi,'dd-MM-yyyy') AS FechaEmision,
            FORMAT(mc.FechaRecepcion,'dd-MM-yyyy') AS FechaRecepcion,
            lpv.MontoPrest AS Valor,
            lpv.MontoBon AS MontoPagadoPrevision,
            lpv.MontoCopago AS MontoCopago,
            ISNULL(seguros.TotalSeguro,0) AS SeguroComplementario,
            ISNULL(lpv.Excedentes,0) AS Excedentes,
            CASE
                WHEN EXISTS (
                    SELECT 1 FROM Caja.MovimientoCaja mc2
                    WHERE mc2.IdCita = mc.IdCita
                      AND mc2.OrigenBono = 'Copago'
                      AND mc2.IdTipoEstadoMovimientoCaja IN (1, 3)
                      AND mc2.Monto > 0
                )
                THEN 0
                ELSE lpv.MontoPrest - lpv.MontoBon - ISNULL(seguros.TotalSeguro,0) - ISNULL(lpv.Excedentes,0)
            END AS TotalPagado,
            tipoCopago.IdTipoCopago,
            tipoCopago.Descripcion AS TipoCopago
        FROM Caja.MovimientoCaja mc
        JOIN Caja.CicloCaja cc ON cc.IdCicloCaja = mc.IdCicloCaja
        JOIN Core.Usuario usuario ON usuario.IdUsuario = cc.IdUsuarioCajero
        JOIN Core.Contacto contacto ON contacto.IdContacto = usuario.IdContacto
        JOIN Caja.Caja caja ON caja.IdCaja = mc.IdCaja
        JOIN Caja.TipoEstadoCaja ec ON caja.IdTipoEstadoCaja = ec.IdTipoEstadoCaja
        JOIN Clinica.Cita cita ON cita.IdCita = mc.IdCita
        JOIN Clinica.Profesional profesional ON profesional.IdProfesional = cita.IdProfesional
        JOIN Clinica.Paciente paciente ON paciente.IdPaciente = cita.IdPaciente
        JOIN Clinica.Prestacion prestacion ON prestacion.IdPrestacion = cita.IdPrestacion
        JOIN Clinica.TipoPrestacion tp ON tp.IdTipoPrestacion = prestacion.IdTipoPrestacion
        JOIN Caja.TipoModalidadPago tmp ON tmp.IdTipoModalidadPago = mc.IdTipoModalidadPago
        LEFT JOIN Clinica.SistemaSalud sistemaSalud ON sistemaSalud.IdSistemaSalud = mc.SistemaSalud
        LEFT JOIN Clinica.Isapre isapre ON isapre.IdIsapre = mc.IdIsapre
        LEFT JOIN (
            SELECT *, ROW_NUMBER() OVER (PARTITION BY IdCita ORDER BY IdCitaFichaEvolucionExamen) AS rn
            FROM Clinica.CitaFichaEvolucionExamen
        ) cfee_unica ON cfee_unica.IdCita = cita.IdCita AND cfee_unica.rn = 1
        LEFT JOIN Ficha.FichaEvolucion fe ON fe.IdFichaEvolucion = cfee_unica.IdFichaEvolucion
        LEFT JOIN Clinica.Profesional profesionalOrigen ON profesionalOrigen.IdProfesional = fe.IdProfesional
        LEFT JOIN Clinica.Profesional profesionalFichaEvolucion ON fe.IdProfesional = profesionalFichaEvolucion.IdProfesional
        LEFT JOIN Clinica.Profesional profesionalExterno ON profesionalExterno.IdProfesional = cita.IdProfesionalExterno
        LEFT JOIN Caja.TipoCopago tipoCopago ON tipoCopago.IdTipoCopago = mc.IdTipoCopago
        JOIN Imed.BonoInterfaz bi ON bi.IdCita = cita.IdCita
        JOIN Imed.ListaBono lb ON lb.IdBonoInterfaz = bi.IdBonoInterfaz
        JOIN Imed.ListaPrestVta lpv ON lpv.IdListaBono = lb.IdListaBono
        -- JOIN al CTE pre-calculado en lugar de subconsulta correlacionada
        JOIN LpvOrden lo ON lo.IdListaPrestVta = lpv.IdListaPrestVta
        LEFT JOIN CfeeOrden cfeeMatch
            ON cfeeMatch.IdCita = cita.IdCita
           AND cfeeMatch.CodigoFonasa = lpv.CodPrestacion
           AND cfeeMatch.rn_cfee = lo.rn_lpv
        LEFT JOIN (
            SELECT IdListaPrestVta, SUM(MtoBonAdic) AS TotalSeguro
            FROM Imed.ListaOtrasBon
            GROUP BY IdListaPrestVta
        ) seguros ON seguros.IdListaPrestVta = lpv.IdListaPrestVta
        WHERE mc.OrigenBono = 'Imed'
          AND CAST(mc.FechaMovimiento AS DATE) BETWEEN CAST(@FechaDesde AS DATE) AND CAST(@FechaHasta AS DATE)
          AND (@IdProfesional IS NULL OR
               CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.IdProfesional
                    ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN cita.IdProfesionalExterno ELSE profesionalOrigen.IdProfesional END
               END = @IdProfesional)
          AND (@IdTipoPrestacion IS NULL
             OR tp.IdTipoPrestacion IN (SELECT CAST(value AS INT) FROM STRING_SPLIT(@IdTipoPrestacion, ',')))
          AND (@IdProfesionalOrden IS NULL OR
               CASE WHEN (CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.IdProfesional WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.IdProfesional ELSE NULL END)
                       = (CASE WHEN profesional.IdTipoOrigenProfesional != 2 THEN profesional.IdProfesional ELSE CASE WHEN cita.IdProfesionalExterno IS NOT NULL THEN cita.IdProfesionalExterno ELSE profesionalOrigen.IdProfesional END END)
                    THEN NULL
                    ELSE CASE WHEN prestacion.IdTipoPrestacion != 1 AND profesionalExterno.IdProfesional IS NULL THEN profesionalFichaEvolucion.IdProfesional WHEN profesionalExterno.IdProfesional IS NOT NULL THEN profesionalExterno.IdProfesional ELSE NULL END
               END = @IdProfesionalOrden)
          AND (@IdCaja IS NULL OR mc.IdCaja = @IdCaja)
          AND mc.IdPresupuesto IS NULL
          AND mc.IdTipoEstadoMovimientoCaja IN (1, 3)
    ) bq
    WHERE NOT (bq.NroBono IS NOT NULL AND bq.NroBono != '' AND bq.IdTipoCopago IS NOT NULL AND bq.TotalPagado > 0)

END
