<?php

Yii::import('application.modules.contable.models.*', true);
Yii::import('application.modules.contable.models.comprobantes.*', true);

class PagoNominaPrestamos extends Utilidades
{
    protected $nomina;
    protected $restante;
    protected $escenario = 12;
    protected $titulo_proceso = 8;
    protected $montoRerverso = null;
    protected $tipo_parametro_unidad = 1;
    protected $tipo_parametro_prestamo = 3;
    protected $escenario_pago_aportes_ordinario = 3;

    public function __construct($nomina, $restante)
    {
        $this->nomina = $nomina;
        $this->restante = $restante;
    }

    public function contabilizar()
    {
        if (! ParamEscenarios::conectado($this->escenario)) {
            return;
        }

        $comprobante = $this->comprobante();

        $this->seguimientoComprobante(
            $comprobante->id,
            $this->nomina->id,
            $this->nomina->getIdComprobantePago(),
            $this->titulo_proceso
        );

        $this->movimientos($comprobante);
        // $this->checkBalance($comprobante);
    }

    protected function saldos()
    {
        $debe = [
            'cta_retenciones_banco' => $this->nomina->getMontoPagado(),
            'cta_reverso_ingreso_diferido' => $this->getInteresDeduccion('interes'),
            'cta_aporte_deduccion_haberes' => $this->aporteDeduccionHaberes(),
        ];
        $haber = (new Warp([
            'reverso_cta_x_cobrar_capital' => $this->getInteresDeduccion('capital'),
            'reverso_cta_x_cobrar_interes' => $this->getInteresDeduccion('interes'),
            'cta_x_pagar_asociados_no_definidos' => $this->getMontoAsociadosNoDefinidos(),
            'cta_ingreso_interes_prestamo' => $this->getInteresDeduccion('interes'),
            'cta_x_pagar_remanente_patrono' => $this->restante,
            'cta_aporte_asignacion_haberes' => $this->getMontoNoDefinidosAsignaciones(),
        ]))->flatten();

        // $this->debug($debe, $haber);

        // $this->validate($debe, $haber);

        return array_merge([], $debe, $haber);
    }

    protected function movimientos($comprobante)
    {
        $movimiento = new Movimiento(
            $comprobante,
            $this->nomina->getFechaOperacion()
        );

        $saldos = $this->saldos();

        $movimiento->crear(
            BancoCuentaContable::get($this->nomina->banco),
            $saldos['cta_retenciones_banco']
        );

        $capitalInteresDetalle = $this->getInteresDeduccionDetalle();

        foreach ((new Group([
            'by' => 'cta_reverso_ingreso_diferido',
            'column' => 'interes',
            'proceso' => 'id_tipo_credito',
            'escenario' => $this->escenario,
            'tipo_parametro' => $this->tipo_parametro_prestamo,
            'data' => $capitalInteresDetalle,
        ]))->get() as $aporte) {
            $movimiento->crear(
                $aporte['cuenta_contable'],
                $aporte['monto']
            );
        }

        foreach ((new Group([
            'by' => 'aport_rec_asociado',
            'column' => 'monto',
            'proceso' => 'id_unidad',
            'tipo_parametro' => $this->tipo_parametro_unidad,
            'escenario' => $this->escenario_pago_aportes_ordinario,
            'data' => $this->aporteDeduccionHaberesDetalle(),
        ]))->get() as $aporte) {
            $movimiento->crear(
                $aporte['cuenta_contable'],
                $aporte['monto']
            );
        }

        foreach ((new Group([
            'by' => 'reverso_cta_x_cobrar_capital',
            'column' => 'capital',
            'proceso' => 'id_tipo_credito',
            'escenario' => $this->escenario,
            'tipo_parametro' => $this->tipo_parametro_prestamo,
            'data' => $capitalInteresDetalle,
        ]))->get() as $aporte) {
            $movimiento->crear(
                $aporte['cuenta_contable'],
                0,
                $aporte['monto']
            );
        }

        foreach ((new Group([
            'by' => 'reverso_cta_x_cobrar_interes',
            'column' => 'interes',
            'proceso' => 'id_tipo_credito',
            'escenario' => $this->escenario,
            'tipo_parametro' => $this->tipo_parametro_prestamo,
            'data' => $capitalInteresDetalle,
        ]))->get() as $aporte) {
            $movimiento->crear(
                $aporte['cuenta_contable'],
                0,
                $aporte['monto']
            );
        }

        if ($saldos['cta_x_pagar_asociados_no_definidos'] > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_x_pagar_asociados_no_definidos',
                    'escenario' => null,
                    'tipo_parametro' => null,
                    'proceso' => null,
                ]),
                0,
                $saldos['cta_x_pagar_asociados_no_definidos']
            );
        }

        foreach ((new Group([
            'by' => 'cta_ingreso_interes_prestamo',
            'column' => 'interes',
            'proceso' => 'id_tipo_credito',
            'escenario' => $this->escenario,
            'tipo_parametro' => $this->tipo_parametro_prestamo,
            'data' => $capitalInteresDetalle,
        ]))->get() as $aporte) {
            $movimiento->crear(
                $aporte['cuenta_contable'],
                0,
                $aporte['monto']
            );
        }

        if ($saldos['cta_x_pagar_remanente_patrono'] > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_x_pagar_remanente_patrono',
                    'escenario' => $this->escenario,
                    'tipo_parametro' => $this->tipo_parametro_unidad,
                    'proceso' => $this->nomina->id_unidad,
                ]),
                0,
                $saldos['cta_x_pagar_remanente_patrono']
            );
        }

        if ($saldos['cta_aporte_asignacion_haberes'] > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'aport_rec_asociado',
                    'escenario' => null,
                    'tipo_parametro' => null,
                    'proceso' => null,
                ]),
                0,
                $saldos['cta_aporte_asignacion_haberes']
            );
        }
    }

    protected function comprobante()
    {
        $this->setProceso($this->nomina);

        $comprobante = new Comprobante('crea');
        $comprobante->fecha_comprobante = $this->fechaComprobante();
        $comprobante->descripcion = 'Pago nómina retenciones: '.$this->nomina->nombre_archivo;
        $comprobante->status = 1;
        $comprobante->nro_documento = $this->nomina->getReferencia();

        if (! $comprobante->save()) {
            throw new Exception('Error: <strong>'.array_values($comprobante->getErrors())[0][0].'</strong>');
        }

        return $comprobante;
    }

    protected function getInteresDeduccion($key = null)
    {
        if ($this->montoRerverso === null) {
            $this->montoRerverso = Yii::app()->getDb()->createCommand('
                select sum(capital) as capital
                      ,sum(interes) as interes
                from (
                    select coalesce(cdc.interes_pagado,0) + coalesce(case when cdcs.id_estatus_cobro_cuota=6 then coalesce(cdc.interes_cobro,0) end,0) as interes
                          ,coalesce(cdc.capital_pagado,0) + coalesce(case when cdcs.id_estatus_cobro_cuota=6 then coalesce(cdc.capital_cobro,0) end,0) as capital
                    from prestamos.datos_txt_tabla_amortizacion dtta
                    inner join prestamos.credito_tabla_amortizacion cta on cta.id=dtta.id_tabla_amortizacion
                    left join prestamos.cobro_diferencial_cuota cdc on cdc.id_proceso=dtta.id
                        and cdc.id_nombre_proceso=1
                        and cdc.blnborrado is false
                    left join prestamos.cobro_diferencial_cuota_seguimiento cdcs on cdcs.id_cobro_diferencial_cuota=cdc.id
                        and cdcs.actual is true
                        and cdcs.id_estatus_cobro_cuota=6
                    where dtta.id_txt=:nomina
                        -- remueve cuotas afectadas por subprocesos
                        and dtta.id_tabla_amortizacion not in (
                            select id_tabla_amortizacion
                            from prestamos.pre_nomina_tabla_amortizacion
                            where id_pre_nomina_credito=:prenomina
                                and blnborrado is true
                        )
                    union all
                    select coalesce(cta.monto_interes,0) as interes
                          ,coalesce(cta.monto_capital,0)
                    from prestamos.pre_nomina_tabla_amortizacion pnta
                    left join prestamos.credito_tabla_amortizacion cta on cta.id=pnta.id_tabla_amortizacion
                    where pnta.id_pre_nomina_credito=:prenomina
                        and pnta.blnborrado is false
                        and pnta.id_estatus_cuota_excluida=12 -- deduccion haberes
                ) t
            ')->bindValues([
                'nomina' => $this->nomina->id,
                'prenomina' => $this->nomina->id_prenomina_credito,
            ])->queryRow();
        }

        return (new Warp($this->montoRerverso))->get($key);
    }

    protected function getInteresDeduccionDetalle()
    {
        return Yii::app()->getDb()->createCommand('
            select id_tipo_credito
                  ,sum(capital) as capital
                  ,sum(interes) as interes
            from (
                select c.id_tipo_credito
                      ,coalesce(cdc.interes_pagado,0) + coalesce(case when cdcs.id_estatus_cobro_cuota=6 then coalesce(cdc.interes_cobro,0) end,0) as interes
                      ,coalesce(cdc.capital_pagado,0) + coalesce(case when cdcs.id_estatus_cobro_cuota=6 then coalesce(cdc.capital_cobro,0) end,0) as capital
                from prestamos.datos_txt_tabla_amortizacion dtta
                inner join prestamos.credito_tabla_amortizacion cta on cta.id=dtta.id_tabla_amortizacion
                inner join prestamos.credito c on c.id=cta.idcredito
                left join prestamos.cobro_diferencial_cuota cdc on cdc.id_proceso=dtta.id
                    and cdc.id_nombre_proceso=1
                    and cdc.blnborrado is false
                left join prestamos.cobro_diferencial_cuota_seguimiento cdcs on cdcs.id_cobro_diferencial_cuota=cdc.id
                    and cdcs.actual is true
                    and cdcs.id_estatus_cobro_cuota=6
                where dtta.id_txt=:nomina
                    -- remueve cuotas afectadas por subprocesos
                    and dtta.id_tabla_amortizacion not in (
                        select id_tabla_amortizacion
                        from prestamos.pre_nomina_tabla_amortizacion
                        where id_pre_nomina_credito=:prenomina
                            and blnborrado is true
                    )
                union all
                select c.id_tipo_credito
                    ,coalesce(cta.monto_interes,0) as interes
                    ,coalesce(cta.monto_capital,0)
                from prestamos.pre_nomina_tabla_amortizacion pnta
                inner join prestamos.credito_tabla_amortizacion cta on cta.id=pnta.id_tabla_amortizacion
                inner join prestamos.credito c on c.id=cta.idcredito
                where pnta.id_pre_nomina_credito=:prenomina
                    and pnta.blnborrado is false
                    and pnta.id_estatus_cuota_excluida=12 -- deduccion haberes
            ) t
            group by id_tipo_credito
        ')->bindValues([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->nomina->id_prenomina_credito,
        ])->queryAll();
    }

    protected function getMontoAsociadosNoDefinidos()
    {
        return Yii::app()->getDb()->createCommand('
            select coalesce(sum(monto),0)
            from (
                select monto_conciliado as monto
                from prestamos.datos_txt_tabla_amortizacion_diferido
                where id_txt=:nomina
                    and id_estatus_amortizacion_diferida in (2, 9)
                union all
                select dtta.monto_remanente
                from prestamos.datos_txt_tabla_amortizacion dtta
                inner join prestamos.datos_txt_tabla_amortizacion_seguimiento dttas on dttas.id_cuota=dtta.id
                    and dttas.actual is true
                where dtta.id_txt=:nomina
                    and dttas.id_estatus=9
                    and dtta.monto_remanente is not null
                    -- remueve cuotas afectadas por subprocesos
                    and dtta.id_tabla_amortizacion not in (
                        select id_tabla_amortizacion
                        from prestamos.pre_nomina_tabla_amortizacion
                        where id_pre_nomina_credito=:prenomina
                            and blnborrado is true
                    )
            ) as d
        ')->queryScalar([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->nomina->id_prenomina_credito,
        ]);
    }

    protected function getMontoNoDefinidosAsignaciones()
    {
        return Yii::app()->getDb()->createCommand('
            select coalesce(sum(monto),0)
            from (
                select monto_conciliado as monto
                from prestamos.datos_txt_tabla_amortizacion_diferido
                where id_txt=:nomina
                    and id_estatus_amortizacion_diferida=11
                union all
                select dtta.monto_remanente
                from prestamos.datos_txt_tabla_amortizacion dtta
                inner join prestamos.datos_txt_tabla_amortizacion_seguimiento dttas on dttas.id_cuota=dtta.id
                    and dttas.actual is true
                where dtta.id_txt=:nomina
                    and dttas.id_estatus=11
                    and dtta.monto_remanente is not null
                    -- remueve cuotas afectadas por subprocesos
                    and dtta.id_tabla_amortizacion not in (
                        select id_tabla_amortizacion
                        from prestamos.pre_nomina_tabla_amortizacion
                        where id_pre_nomina_credito=:prenomina
                            and blnborrado is true
                    )
            ) as d
        ')->queryScalar([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->nomina->id_prenomina_credito,
        ]);
    }

    protected function aporteDeduccionHaberes()
    {
        return Yii::app()->getDb()->createCommand('
            select sum(monto)
            from (
                select cdc.capital_cobro + cdc.interes_cobro as monto
                from prestamos.datos_txt_tabla_amortizacion dtta
                inner join prestamos.credito_tabla_amortizacion cta on cta.id=dtta.id_tabla_amortizacion
                left join prestamos.cobro_diferencial_cuota cdc on cdc.id_proceso=dtta.id
                    and cdc.id_nombre_proceso=1
                    and cdc.blnborrado is false
                left join prestamos.cobro_diferencial_cuota_seguimiento cdcs on cdcs.id_cobro_diferencial_cuota=cdc.id
                    and cdcs.actual is true
                where dtta.id_txt=:nomina
                    and cdcs.id_estatus_cobro_cuota=6 -- deduccioon de haberes
                    and dtta.monto_cobro is not null
                    -- remueve cuotas afectadas por subprocesos
                    and dtta.id_tabla_amortizacion not in (
                        select id_tabla_amortizacion
                        from prestamos.pre_nomina_tabla_amortizacion
                        where id_pre_nomina_credito=:prenomina
                            and blnborrado is true
                    )
                union all
                -- excluidas con estatus "deduccion"
                select cta.monto_cuota as monto
                from prestamos.pre_nomina_tabla_amortizacion pnta
                inner join prestamos.credito_tabla_amortizacion cta on cta.id=pnta.id_tabla_amortizacion
                where pnta.id_pre_nomina_credito=:prenomina
                    and pnta.blnborrado is false
                    and pnta.id_estatus_cuota_excluida=12 -- deduccion haberes
            ) t
        ')->queryScalar([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->nomina->id_prenomina_credito,
        ]);
    }

    protected function aporteDeduccionHaberesDetalle()
    {
        return Yii::app()->getDb()->createCommand('
            select idunidad as id_unidad
                  ,sum(monto) as monto
            from (
                select a.idunidad
                    ,cdc.capital_cobro + cdc.interes_cobro as monto
                from prestamos.datos_txt_tabla_amortizacion dtta
                inner join prestamos.credito_tabla_amortizacion cta on cta.id=dtta.id_tabla_amortizacion
                inner join prestamos.credito c on c.id=cta.idcredito
                inner join asociado a on a.idasociado=c.idasociado
                left join prestamos.cobro_diferencial_cuota cdc on cdc.id_proceso=dtta.id
                    and cdc.id_nombre_proceso=1
                    and cdc.blnborrado is false
                left join prestamos.cobro_diferencial_cuota_seguimiento cdcs on cdcs.id_cobro_diferencial_cuota=cdc.id
                    and cdcs.actual is true
                where dtta.id_txt=:nomina
                    and cdcs.id_estatus_cobro_cuota=6 -- deduccioon de haberes
                    and dtta.monto_cobro is not null
                    -- remueve cuotas afectadas por subprocesos
                    and dtta.id_tabla_amortizacion not in (
                        select id_tabla_amortizacion
                        from prestamos.pre_nomina_tabla_amortizacion
                        where id_pre_nomina_credito=:prenomina
                            and blnborrado is true
                    )
                union all
                -- excluidas con estatus "deduccion"
                select a.idunidad
                    ,cta.monto_cuota as monto
                from prestamos.pre_nomina_tabla_amortizacion pnta
                inner join prestamos.credito_tabla_amortizacion cta on cta.id=pnta.id_tabla_amortizacion
                inner join prestamos.credito c on c.id=cta.idcredito
                inner join asociado a on a.idasociado=c.idasociado
                where pnta.id_pre_nomina_credito=:prenomina
                    and pnta.blnborrado is false
                    and pnta.id_estatus_cuota_excluida=12 -- deduccion haberes
            ) t
            group by idunidad
        ')->bindValues([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->nomina->id_prenomina_credito,
        ])->queryAll();
    }
}
