<?php

class Generar
{
    protected $nomina;
    protected $pago;
    protected $preNomina;

    public function __construct($nomina, $pago)
    {
        $this->nomina = $nomina;
        $this->pago = $pago;
        $this->preNomina = $this->nomina->idPrenominaCredito;
        Yii::import('application.modules.configuracion.models.*');
        Yii::import('application.modules.prestamo.models.ConfBeneficiario');
    }

    public function createAll()
    {
        $this->ordenesPago();
        $this->abonosPrestamos();
        $this->asignacionesHaberes();
        $this->deduccionesHaberes();
    }

    protected function descripcion($cuota)
    {
        return vsprintf("%s Cuota cargada: %s Tipo de credito:", [
            $this->nomina->getDescripcion(),
            Yii::app()->format->number($cuota['monto']),
            $cuota['tipo_credito']
        ]);
    }

    public function ordenesPago()
    {
        (new Warp($this->datosOrdenesPagos()))->map(function ($cuota) {
            if ($cuota['id_asociado']) {
                OrdenPago::generar([
                    'idproveedor' => $cuota['id_asociado'],
                    'id_tipo_orden' => 2,
                    'id_tipo_carga' => 3,
                    'id_tipo_persona' => $cuota['id_tipo_persona'],
                    'rif' => $cuota['cedula'],
                    'monto_pago' => Yii::app()->format->number($cuota['monto']),
                    'descripcion' => 'Tipo: asociado '. $this->descripcion($cuota),
                    'idbanco' => $this->getIdAsociadoCuentaBanco($cuota),
                    'asociado_tipo_cuenta' => $cuota['asociado_tipo_cuenta'],
                    'id_concepto' => ConceptosOrdenPago::proceso(8),
                ], 2);
            } elseif ($cuota['id_proveedor']) {
                OrdenPago::generar([
                    'idproveedor' => $cuota['id_proveedor'],
                    'id_tipo_orden' => 1,
                    'id_tipo_carga' => 3,
                    'id_tipo_persona' => $cuota['id_tipo_persona'],
                    'rif' => $cuota['cedula'],
                    'monto_pago' => Yii::app()->format->number($cuota['monto']),
                    'descripcion' => 'Tipo: proveedor '. $this->descripcion($cuota),
                    'idbanco' => $cuota['id_proveedor_cuenta_banco'],
                    'id_concepto' => ConceptosOrdenPago::proceso(8),
                ], 2);
            } else {
                $this->crearProveedor($cuota);
            }
        });
    }

    public function abonosPrestamos()
    {
        (new Warp($this->datosAbonoPrestamos()))->map(function ($cuota) {
            $reporteCredito = ReporteCreditos::model()->find('idcredito=:idcredito', [':idcredito' => $cuota['id_credito']]);

            CreditoAbono::generar([
                'idasociado' => $reporteCredito->idasociado,
                'idcredito' => $cuota['id_credito'],
                'monto_abonar' => Yii::app()->format->number($cuota['monto']),
                'idforma_pago' => 3,
                'idbanco' => $this->pago->id_banco,
                'numero_referencia' => $this->pago->referencia,
                'fecha_referencia' => $this->pago->fecha_pago,
                'prestamos_seleccionados' => json_encode([
                    [
                        'id_credito' => $cuota['id_credito'],
                        'id_tipo_credito' => $reporteCredito->id_tipo_credito,
                        'cuotas_pagadas' => $reporteCredito->cuotas_pagadas,
                        'monto_deuda' => (new ReporteCreditos())->getMontoDeudaActualConfigurado($cuota['id_credito']),
                        'monto_abonar' => 0,
                    ],
                ]),
            ]);
        });
    }

    public function asignacionesHaberes()
    {
        (new Warp($this->datosAsignacionHaberes()))->map(function ($cuota) {
            AjusteHaberes::generar([
                'idasociado' => $cuota['id_asociado'],
                'id_tipo_ajuste' => 2,
                'id_concepto_ajuste' => 2,
                'id_tipo_movimiento' => 1,
                'observacion' => 'Asignación de haberes realizada desde pago de nomina de préstamos.',
                'numero_operacion' => $this->pago->referencia,
                'fecha_operacion' => $this->pago->fecha_pago,
                'monto_asociado' => Yii::app()->format->number($cuota['monto']),
            ], 2);
        });
    }

    public function deduccionesHaberes()
    {
        (new Warp($this->datosDeduccionHaberes()))->map(function ($cuota) {
            AjusteHaberes::generar([
                'idasociado' => $cuota['id_asociado'],
                'id_tipo_ajuste' => 1,
                'id_concepto_ajuste' => 2,
                'id_tipo_movimiento' => 1,
                'observacion' => 'Asignación de haberes realizada desde pago de nomina de préstamos.',
                'numero_operacion' => $this->pago->referencia,
                'fecha_operacion' => $this->pago->fecha_pago,
                'monto_asociado' => Yii::app()->format->number($cuota['monto']),
            ], 2);

            CreditoTablaAmortizacion::setEstatus([
                'id' => $cuota['id_tabla_amortizacion'],
                'id_estatus_cuota' => 2,
            ]);
        });
    }

    private function getIdAsociadoCuentaBanco($cuota)
    {
        if ($cuota['id_asociado_cuenta_banco'] == null) {
            throw new Exception("El asociado <strong>{$cuota['nombre']}</strong> no tiene cuenta de banco principal definida.");
        }

        return $cuota['id_asociado_cuenta_banco'];
    }

    private function crearProveedor($cuota)
    {
        if ($proveedor = Proveedor::getIf([
            'rif' => $cuota['cedula'],
            'tipo_persona' => $cuota['id_tipo_persona'],
            'tipo_proveedor' => 2,
        ])) {
            $proveedor = [
                'id_proveedor' => $proveedor->id,
                'id_tipo_persona' => $proveedor->id_tipo_persona,
                'id_banco' => $proveedor->proveedorCuentaBancosPrincipal->id,
            ];
        } else {
            $proveedor = Proveedor::generar([
                'razon_social' => $cuota['nombre'],
                'id_tipo_persona' => $cuota['id_tipo_persona'],
                'rif' => $cuota['cedula'],
                'id_cuenta' => ConfBeneficiario::getCuentaContableBeneficiario(),
                'id_tipo_proveedor' => 2,
            ]);

            $proveedorCuentaBanco = ProveedorCuentaBanco::generar([
                'idproveedor' => $proveedor->id,
                'idbanco' => $cuota['id_banco'],
                'cuenta_bancaria' => $cuota['numero_cuenta'],
                'cuenta_corriente' => true,
                'cuenta_principal' => true,
            ]);

            $proveedor = [
                'id_proveedor' => $proveedor->id,
                'id_tipo_persona' => $proveedor->id_tipo_persona,
                'id_banco' => $proveedorCuentaBanco->id,
            ];
        }

        OrdenPago::generar([
            'idproveedor' => $proveedor['id_proveedor'],
            'id_tipo_orden' => 1,
            'id_tipo_carga' => 3,
            'id_tipo_persona' => $proveedor['id_tipo_persona'],
            'rif' => $cuota['cedula'],
            'monto_pago' => Yii::app()->format->number($cuota['monto']),
            'descripcion' => 'Tipo: proveedor '. $this->descripcion($cuota),
            'idbanco' => $proveedor['id_banco'],
            'id_concepto' => ConceptosOrdenPago::proceso(8),
        ], 2);
    }

    private function datosOrdenesPagos()
    {
        return Yii::app()->getDb()->createCommand("
            select  t.datos[1] as nombre
                   ,t.datos[2] as id_tipo_persona
                   ,t.datos[3] as cedula
                   ,t.datos[4] as id_banco
                   ,t.datos[5] as numero_cuenta
                   ,t.datos[6] as cuenta_corriente
                   ,t.monto
                   ,a.idasociado as id_asociado
                   ,acb.id as id_asociado_cuenta_banco
                   ,acb.cuenta_corriente as asociado_tipo_cuenta
                   ,p.id as id_proveedor
                   ,pcb.id as id_proveedor_cuenta_banco
                   ,pcb.cuenta_corriente as proveedor_tipo_cuenta
                   ,t.tipo_credito
            from (
                select  dttad.id
                       ,array[
                           dttad.extra->>'nombre',
                           dttad.extra->>'id_tipo_persona',
                           dttad.extra->>'cedula',
                           dttad.extra->>'id_banco',
                           dttad.extra->>'numero_cuenta',
                           dttad.extra->>'cuenta_corriente'
                       ] as datos
                       ,dttad.monto_cuota as monto
                       ,dttad.id_tipo_credito
                       ,tc.descripcion as tipo_credito
                from prestamos.datos_txt_tabla_amortizacion_diferido dttad
                left join public.asociado a on a.cedula=dttad.cedula
                    and a.id_estatus=1
                left join public.asociado_cuenta_banco acb on acb.idasociado=a.idasociado
                    and acb.cuenta_principal is true
                    and acb.blnborrado is false
                left join prestamos.tipo_credito tc on tc.id=dttad.id_tipo_credito
                where dttad.id_txt=:nomina
                    and dttad.id_estatus_amortizacion_diferida in (2, 9)
            ) as t
            left join public.asociado a on a.id_tipo_persona=t.datos[2]::integer
                and a.cedula=t.datos[3]::integer
                and a.id_estatus=1
            left join public.asociado_cuenta_banco acb on acb.idasociado=a.idasociado
                and acb.cuenta_principal is true
            left join public.proveedor p on p.id_tipo_persona=t.datos[2]::integer
                and p.rif=t.datos[3]::text
                and p.id_estatus_proveedor=1
            left join public.proveedor_cuenta_banco pcb on pcb.idproveedor=p.id
                and pcb.cuenta_principal is true
            union all
            SELECT null
                  ,a.id_tipo_persona::text
                  ,a.cedula::text
                  ,null
                  ,null
                  ,null
                  ,dtta.monto_remanente
                  ,a.idasociado as id_asociado
                  ,(
                      select id
                      from asociado_cuenta_banco
                      where cuenta_principal IS TRUE
                          and blnborrado is false
                      order by id DESC
                      limit 1
                  ) as id_asociado_cuenta_banco
                  ,(
                      select cuenta_corriente
                      from asociado_cuenta_banco
                      where cuenta_principal IS TRUE
                          and blnborrado is false
                      order by id DESC
                      limit 1
                  ) as asociado_tipo_cuenta
                  ,null
                  ,null
                  ,null
                  ,c.id_tipo_credito::text
            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
            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
            WHERE dtta.id_txt=:nomina
                and dttas.id_estatus=9 --gestion reembolso
                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
                )
        ")->bindValues([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->preNomina->id,
        ])->queryAll();
    }

    private function datosAbonoPrestamos()
    {
        return Yii::app()->getDb()->createCommand("
            SELECT extra->>'prestamo' AS id_credito,
                   monto_cuota AS monto
            FROM prestamos.datos_txt_tabla_amortizacion_diferido
            WHERE id_txt=:id_txt
              AND id_estatus_amortizacion_diferida=10
        ")->bindValues([
            'id_txt' => $this->nomina->id,
        ])->queryAll();
    }

    private function datosAsignacionHaberes()
    {
        return Yii::app()->getDb()->createCommand('
            SELECT a.idasociado AS id_asociado ,
                   dttad.cedula ,
                   dttad.monto_cuota as monto
            FROM prestamos.datos_txt_tabla_amortizacion_diferido dttad
            INNER JOIN public.asociado a ON a.cedula=dttad.cedula
                AND a.id_estatus=1
            WHERE dttad.id_txt=:nomina
                AND dttad.id_estatus_amortizacion_diferida=11 --asignacion de haberes
            UNION ALL
            SELECT c.idasociado
                  ,a.cedula
                  ,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
            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 public.asociado a ON a.idasociado=c.idasociado
            WHERE dtta.id_txt=:nomina
                and dttas.id_estatus=11 --gestion reembolso
                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
                )
        ')->bindValues([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->preNomina->id,
        ])->queryAll();
    }

    private function datosDeduccionHaberes()
    {
        return Yii::app()->getDb()->createCommand('
            SELECT c.idasociado as id_asociado,
                   cta.id as id_tabla_amortizacion,
                   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
            WHERE pnta.id_pre_nomina_credito=:prenomina
                AND pnta.id_estatus_cuota_excluida=12
            UNION
            SELECT c.idasociado
                ,dtta.id_tabla_amortizacion
                ,coalesce(cdc.capital_cobro,0) + coalesce(cdc.interes_cobro,0)
            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 prestamos.cobro_diferencial_cuota cdc ON cdc.id_proceso=dtta.id
                AND cdc.id_nombre_proceso=1
                AND cdc.blnborrado is false
            INNER 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
                -- 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
                )
        ')->bindValues([
            'nomina' => $this->nomina->id,
            'prenomina' => $this->preNomina->id,
        ])->queryAll();
    }
}
