<?php

class RHQuery
{
    protected $rh;
    protected $where = false;

    public function __construct($rh)
    {
        $this->rh = $rh;
    }

    public function make()
    {
        return "
            select
                *
                {$this->porcentajeInteres()}
            from (
                SELECT a.idasociado
                        ,a.cedula
                        ,a.nombre
                        ,a.apellidos
                        ,a.fechaingreso::DATE as fecha_registro -- fecha de ingreso
                        ,a.idunidad AS id_unidad
                        ,u.descripcion AS nombre_unidad
                        ,a.idtipotrabajador
                        ,tt.descripcion AS tipo_trabajador
                        ,ea.nombre_estatus as estatus_asociado
                        ,(
                            select b.descripcion
                            from asociado_cuenta_banco acb
                            left join banco b on b.idbanco=acb.id_banco
                            where acb.cuenta_principal IS TRUE
                                and acb.idasociado=a.idasociado
                            ORDER BY id DESC
                            limit 1
                        ) as nombre_banco
                        ,(
                            select cuenta_bancaria
                            from asociado_cuenta_banco
                            where cuenta_principal IS TRUE
                                and idasociado=a.idasociado
                            ORDER BY id DESC
                            limit 1
                        ) as numero_cuenta
                        ,coalesce(aporte_extra_patrono.monto, 0) as aporte_extra_patrono
                        ,coalesce(aporte_extra_asociado.monto, 0) as aporte_extra_socio
                        ,coalesce(aporte_ordinario.monto_patrono, 0) - COALESCE(diferido.monto_patrono, 0) as aporte_patrono
                        ,coalesce(aporte_ordinario.monto_asociado, 0) - COALESCE(diferido.monto_asociado, 0) as aporte_asociado
                        ,coalesce(ajuste_haberes_asignacion.monto_patrono, 0) as asignacion_monto_patrono
                        ,coalesce(ajuste_haberes_asignacion.monto_asociado, 0) as asignacion_monto_asociado
                        ,coalesce(ajuste_haberes_deduccion.monto_patrono, 0) as descuento_monto_patrono
                        ,coalesce(ajuste_haberes_deduccion.monto_asociado, 0) as descuento_monto_asociado
                        ,coalesce(dividendo.monto, 0) as dividendos
                        ,(
                            coalesce(aporte_extra_patrono.monto, 0) + coalesce(aporte_extra_asociado.monto, 0) -- aporte extra
                            + (
                                (coalesce(aporte_ordinario.monto_patrono, 0) - COALESCE(diferido.monto_patrono, 0)) -- aporte ordinario patrono
                                +
                                (coalesce(aporte_ordinario.monto_asociado, 0) - COALESCE(diferido.monto_asociado, 0)) -- aporte ordinario asociado
                            )
                            + (coalesce(ajuste_haberes_asignacion.monto_patrono, 0) + coalesce(ajuste_haberes_asignacion.monto_asociado, 0)) -- asignacion de haberes
                            - (coalesce(ajuste_haberes_deduccion.monto_patrono, 0) + coalesce(ajuste_haberes_deduccion.monto_asociado, 0)) -- deduccion de haberes
                            + coalesce(dividendo.monto, 0)
                        ) as aporte_total
                        ,coalesce(retiros.monto, 0) as retiro_parcial
                        ,coalesce(liquidacion.monto, 0) as monto_liquidado
                        ,(
                            (
                                coalesce(aporte_extra_patrono.monto, 0) + coalesce(aporte_extra_asociado.monto, 0) -- aporte extra
                                + (
                                    (coalesce(aporte_ordinario.monto_patrono, 0) - COALESCE(diferido.monto_patrono, 0)) -- aporte ordinario patrono
                                    +
                                    (coalesce(aporte_ordinario.monto_asociado, 0) - COALESCE(diferido.monto_asociado, 0)) -- aporte ordinario asociado
                                )
                                + (coalesce(ajuste_haberes_asignacion.monto_patrono, 0) + coalesce(ajuste_haberes_asignacion.monto_asociado, 0)) -- asignacion de haberes
                                - (coalesce(ajuste_haberes_deduccion.monto_patrono, 0) + coalesce(ajuste_haberes_deduccion.monto_asociado, 0)) -- deduccion de haberes
                                + coalesce(dividendo.monto, 0)
                            )
                            - coalesce(retiros.monto, 0)
                            - coalesce(liquidacion.monto, 0)
                        ) as total_haberes
                FROM asociado a
                LEFT JOIN asociado_estatus ae ON a.idasociado = ae.idasociado AND actual = true
                LEFT JOIN estatus_asociado ea ON ae.id_estatus_asociado = ea.id
                LEFT JOIN unidad u ON u.idunidad = a.idunidad
                LEFT JOIN tipo_trabajador tt ON a.idtipotrabajador = tt.idtipotrabajador
                LEFT JOIN (-- aporte extra patrono
                    SELECT datos.id_asociado
                        ,sum(datos.monto) as monto
                    FROM (
                        -- masivo
                        SELECT av.id
                            ,av.id_asociado
                            ,av.monto as monto
                        FROM retenciones.aporte_voluntario av
                        LEFT JOIN retenciones.datos_txt_integrado dti ON av.id_txt_integrado=dti.id
                        LEFT JOIN retenciones.estatus_txt_integrado eti ON av.id=eti.id_datos_txt_integrado
                            AND eti.actual is true
                        LEFT JOIN contable.proceso_pago pp on pp.id_proceso=dti.id
                            AND pp.id_nombre_proceso=7
                        WHERE eti.id_estatus_txt=5 -- pagado
                            AND id_aportante=2 -- patrono
                            {$this->filtro('pp.fecha_pago')}
                        UNION
                        -- individual
                        SELECT av.id
                            ,av.id_asociado
                            ,av.monto as monto
                        FROM retenciones.aporte_voluntario av
                        LEFT JOIN retenciones.estatus_aporte_voluntario eav ON av.id=eav.id_aporte_voluntario
                            and eav.actual is true
                        WHERE eav.id_status_av=2 -- aprobado
                            AND av.id_aportante=2  -- patrono
                            {$this->filtro('av.fecha_pago')}
                    ) as datos
                    GROUP BY datos.id_asociado
                ) as aporte_extra_patrono ON aporte_extra_patrono.id_asociado=a.idasociado
                LEFT JOIN (-- aporte extra asociado
                    SELECT d.id_asociado,
                        COALESCE(d.monto, 0) - COALESCE(aporte_retiro.monto_retiro, 0) AS monto
                    FROM (
                        SELECT datos.id_asociado
                            ,sum(datos.monto) as monto
                        FROM (
                            -- masivo
                            SELECT av.id
                                ,av.id_asociado
                                ,av.monto as monto
                            FROM retenciones.aporte_voluntario av
                            LEFT JOIN retenciones.datos_txt_integrado dti ON av.id_txt_integrado=dti.id
                            LEFT JOIN retenciones.estatus_txt_integrado eti ON dti.id=eti.id_datos_txt_integrado
                                AND eti.actual is true
                            LEFT JOIN contable.proceso_pago pp on pp.id_proceso=dti.id
                                AND pp.id_nombre_proceso=7 -- aportes voluntarios
                            WHERE eti.id_estatus_txt=5 -- pagado
                                AND id_aportante=1 -- asociado
                                AND av.id_tipo_aporte_voluntario=1 -- capitalizacion
                                {$this->filtro('pp.fecha_pago')}
                            UNION
                            -- carga individual
                            SELECT av.id
                                ,av.id_asociado
                                ,av.monto
                            FROM retenciones.aporte_voluntario av
                            LEFT JOIN retenciones.estatus_aporte_voluntario eav ON av.id=eav.id_aporte_voluntario
                                and eav.actual is true
                            WHERE eav.id_status_av=2 -- aprobados
                                and av.id_aportante=1 -- asociado
                                AND av.id_tipo_aporte_voluntario=1 -- capitalizacion
                                {$this->filtro('av.fecha_pago')}
                        ) as datos
                        GROUP BY datos.id_asociado
                    ) d
                    LEFT JOIN (
                    SELECT avr.id_asociado
                            ,sum(monto) AS monto_retiro
                        FROM retenciones.aporte_voluntario as avr
                        left JOIN retenciones.estatus_aporte_voluntario gav ON avr.id = gav.id_aporte_voluntario
                            AND gav.actual IS TRUE
                        LEFT JOIN retenciones.datos_txt_integrado dti ON avr.id_txt_integrado=dti.id
                        LEFT JOIN retenciones.estatus_txt_integrado eti ON avr.id=eti.id_datos_txt_integrado
                            AND eti.actual IS TRUE
                        LEFT JOIN contable.proceso_pago pp on pp.id_proceso=avr.id
                            AND pp.id_nombre_proceso=7 -- aportes voluntarios
                        WHERE id_tipo_aporte_voluntario=2 -- retiro
                            AND gav.id_status_av=5 -- pago retiro
                            {$this->filtro('pp.fecha_pago')}
                        GROUP BY id_asociado
                    ) AS aporte_retiro ON aporte_retiro.id_asociado = d.id_asociado
                ) as aporte_extra_asociado on aporte_extra_asociado.id_asociado=a.idasociado
                LEFT JOIN (-- aporte ordinario
                    SELECT ao.id_asociado,
                        sum(coalesce(ao.aporte_patrono,0)) as monto_patrono,
                        sum(coalesce(ao.aporte_asociado,0)) as monto_asociado
                    FROM retenciones.aporte_ordinario ao
                    INNER JOIN retenciones.datos_txt_integrado dti ON ao.id_txt = dti.id
                    INNER JOIN retenciones.estatus_txt_integrado eti ON dti.id = eti.id_datos_txt_integrado
                        AND eti.actual = true
                        AND eti.id_estatus_txt in (5, 6) --> (pagado, pagado con diferido)
                    INNER JOIN contable.proceso_pago pp on pp.id_proceso=dti.id
                        AND pp.id_nombre_proceso=6 --> aporte ordinario
                        AND pp.blnborrado is false
                        {$this->filtro('pp.fecha_pago')}
                    WHERE ao.blnborrado is false
                    GROUP BY ao.id_asociado
                ) as aporte_ordinario on aporte_ordinario.id_asociado=a.idasociado
                LEFT JOIN (-- diferido
                    SELECT aporte.id_asociado
                        ,sum(d.deuda_actual_patrono) AS monto_patrono
                        ,sum(d.deuda_actual_socio) AS monto_asociado
                    FROM retenciones.historial_aportes_diferidos d
                    LEFT JOIN retenciones.aporte_ordinario aporte ON aporte.id = d.id_aporte
                    LEFT JOIN retenciones.datos_txt_integrado txt ON aporte.id_txt = txt.id
                    LEFT JOIN retenciones.estatus_txt_integrado estatus ON txt.id = estatus.id_datos_txt_integrado
                    WHERE estatus.id_estatus_txt = 6
                        AND estatus.actual = true
                        AND d.actual = true
                        {$this->filtro('d.fecha_operacion')}
                    GROUP BY aporte.id_asociado
                ) diferido ON a.idasociado = diferido.id_asociado
                LEFT JOIN (-- ajuste haberes asignacion
                    SELECT aha.idasociado as id_asociado
                        ,sum(aha.monto_patrono) AS monto_patrono
                        ,sum(aha.monto_asociado) AS monto_asociado
                    FROM ajuste_haberes.ajuste_haberes aha
                    LEFT JOIN ajuste_haberes.ajuste_haberes_seguimiento ahs ON aha.id = ahs.id_ajuste_haberes
                    WHERE ahs.actual = true
                        AND ahs.id_estatus_ajuste_haberes = 2
                        AND aha.id_tipo_ajuste = 2
                        {$this->filtro('ahs.fecha_registro')}
                    GROUP BY aha.idasociado
                ) ajuste_haberes_asignacion ON ajuste_haberes_asignacion.id_asociado = a.idasociado
                LEFT JOIN (-- ajuste haberes deduccion
                    SELECT ahd.idasociado as id_asociado,
                        sum(ahd.monto_asociado) AS monto_asociado,
                        sum(ahd.monto_patrono) AS monto_patrono
                    FROM ajuste_haberes.ajuste_haberes ahd
                    LEFT JOIN ajuste_haberes.ajuste_haberes_seguimiento ahs ON ahd.id=ahs.id_ajuste_haberes
                    WHERE ahs.actual=true
                        AND ahs.id_estatus_ajuste_haberes=2 --aprobado
                        AND ahd.id_tipo_ajuste=1
                        {$this->filtro('ahd.fecha_operacion')}
                    GROUP BY ahd.idasociado
                ) ajuste_haberes_deduccion ON ajuste_haberes_deduccion.id_asociado = a.idasociado
                LEFT JOIN (-- dividendos
                    SELECT ad.idasociado as id_asociado
                        ,sum(ad.dividendo) AS monto
                    FROM asociado_dividendos ad
                    WHERE ad.activo = true
                        -- TODO: {$this->filtro('ad.fecha_capitalizacion')}
                    GROUP BY ad.idasociado
                ) dividendo ON dividendo.id_asociado = a.idasociado
                LEFT JOIN (-- retiros
                    SELECT r.idasociado AS id_asociado
                        ,sum(r.monto_aprobado) AS monto
                    FROM retiro.retiro_parcial r
                    LEFT JOIN retiro.estatus_retiro_parcial erp ON r.id=erp.id_retiro_parcial
                        AND erp.actual is true
                    LEFT JOIN contable.proceso_pago pp on pp.id_proceso=r.id
                        AND pp.id_nombre_proceso=2
                    WHERE r.blnborrado is false
                        AND erp.id_estatus_retiro=ANY(ARRAY[2, 4])
                        {$this->filtro('pp.fecha_pago')}
                    GROUP BY r.idasociado
                ) as retiros ON retiros.id_asociado=a.idasociado
                LEFT JOIN (-- liquidaciones
                    SELECT l.idasociado AS id_asociado
                        ,sum(l.monto_total_disponible) AS monto
                    FROM retiro.liquidacion l
                    LEFT JOIN retiro.estatus_liquidacion el ON l.id=el.id_liquidacion
                        AND el.actual = true
                    LEFT JOIN contable.proceso_pago pp on pp.id_proceso=l.id AND pp.id_nombre_proceso=3
                    WHERE l.blnborrado = false
                        AND el.id_estatus_liquidacion=4 -- pagadas
                        {$this->filtro('pp.fecha_pago')}
                    GROUP BY l.idasociado
                ) as liquidacion ON liquidacion.id_asociado = a.idasociado
                {$this->condiciones()}
                ORDER BY a.cedula, a.nombre, a.apellidos
            ) as rh;";
    }

    private function condiciones()
    {
        $condiciones = '';

        if ($this->validate($this->rh->id_unidad, true)) {
            $condiciones .= "{$this->modificador()} a.idunidad={$this->rh->id_unidad}";
        }

        if ($this->validate($this->rh->idtipotrabajador, true)) {
            $condiciones .= "{$this->modificador()} a.idtipotrabajador={$this->rh->idtipotrabajador}";
        }

        if ($this->validate($this->rh->id_estatus, true)) {
            $condiciones .= "{$this->modificador()} a.id_estatus={$this->rh->id_estatus}";
        }

        if ($this->validate($this->rh->cedula)) {
            $condiciones .= "{$this->modificador()} cedula={$this->rh->cedula}";
        }

        return $condiciones;
    }

    private function filtro($relation)
    {
        if ($this->rh->desdeH && $this->rh->hastaH) {
            return "AND {$relation} BETWEEN '{$this->rh->desdeH}' AND '{$this->rh->hastaH}'";
        } elseif ($this->rh->desdeH || $this->rh->hastaH) {
            return "AND {$relation} {$this->parametroHaberes('operador')} '{$this->parametroHaberes('fecha')}'";
        }

        return '';
    }

    private function parametroHaberes($key)
    {
        if ($this->rh->desdeH) {
            $operador = '>=';
            $fecha = $this->rh->desdeH;
        } else {
            $operador = '<=';
            $fecha = $this->rh->hastaH;
        }

        switch ($key) {
            case 'operador':
                return $operador;
            case 'fecha':
                return $fecha;
        }
    }

    private function validate($value, $strict = false)
    {
        if (! $strict) {
            return $value != '';
        }

        return $value != null && $value != '';
    }

    private function modificador()
    {
        if (! $this->where) {
            $this->where = true;
            return ' WHERE';
        }

        return ' AND';
    }

    private function porcentajeInteres()
    {
        if (! $this->rh->hasPorcentajeInteres()) {
            return '';
        }

        $porcentaje = $this->rh->porcentajeInteres();

        return ",rh.total_haberes * ({$porcentaje->porcentaje} / 12) as interes_calculado";
    }
}
