<?php

class AjusteCuentaXCobrarAO extends Utilidades
{
    private $liquidacion;
    private $cedula = null;
    private $escenario = 2;
    protected $datos = null;
    protected $retenciones = null;
    private $tipo_parametro = 1; // Unidad
    private $escenario_retencion = 9;
    private $tipo_parametro_prestamo = 3;

    public function __construct($liquidacion)
    {
        $this->liquidacion = $liquidacion;
        Yii::import('application.modules.contable.models.*', true);
    }

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

        ////////////////////////////////// COMPROBANTE /////////////////////////////////
        $comprobante = $this->comprobante();

        $this->seguimientoComprobante(
            $comprobante->id,
            $this->liquidacion->id,
            null,
            6
        );
        ////////////////////////// MOVIMIENTOS DEL COMPROBANTE /////////////////////////
        $this->movimientos($comprobante);
    }

    protected function datos()
    {
        if ($this->datos == null) {
            $this->datos = $this->liquidacion->getAporteAportesEnTransitoAgrupados();
        }

        return $this->datos;
    }

    private function saldos()
    {
        $saldos = $this->datos();

        $asociado = (new Warp($saldos))->sum('aporte_asociado');
        $patrono = (new Warp($saldos))->sum('aporte_patrono');

        $debe = (new Warp([
            'cta_x_cobrar_asociado' => $asociado,
            'cta_x_cobrar_patron' => $patrono,
            'cta_rebaja_cartera_prestamos' => $this->getRetenciones('cta_rebaja_cartera_prestamos', 'capital'),
            'cta_ingresos_interes' => $this->getRetenciones('cta_ingresos_interes', 'interes'),
        ]))->flatten();

        $haber = (new Warp([
            'aport_no_rec_asociado' => $asociado,
            'aport_no_rec_patron' => $patrono,
            'cta_x_cobrar_capital' => $this->getRetenciones('cta_x_cobrar_capital', 'capital'),
            'cta_x_cobrar_interes' => $this->getRetenciones('cta_x_cobrar_interes', 'interes'),
        ]))->flatten();

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

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

        return [
            'debe' => (new Warp($saldos))->map(function ($saldo) {
                return array_merge($saldo, [
                    'cta_x_cobrar_asociado' => $saldo['aporte_asociado'],
                    'cta_x_cobrar_patron' => $saldo['aporte_patrono'],
                ]);
            }),
            'haber' => (new Warp($saldos))->map(function ($saldo) {
                return array_merge($saldo, [
                    'aport_no_rec_asociado' => $saldo['aporte_asociado'],
                    'aport_no_rec_patron' => $saldo['aporte_patrono'],
                ]);
            }),
        ];
    }

    private function movimientos($comprobante)
    {
        $movimiento = new Movimiento(
            $comprobante,
            date('Y-m-d')
        );

        $saldos = $this->saldos();

        foreach ($saldos['haber'] as $saldo) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'aport_no_rec_asociado',
                    'escenario' => $this->escenario,
                    'tipo_parametro' => $this->tipo_parametro,
                    'proceso' => $saldo['id_unidad'],
                ]),
                $saldo['aport_no_rec_asociado']
            );
        }

        foreach ($saldos['haber'] as $saldo) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'aport_no_rec_patron',
                    'escenario' => $this->escenario,
                    'tipo_parametro' => $this->tipo_parametro,
                    'proceso' => $saldo['id_unidad'],
                ]),
                $saldo['aport_no_rec_patron']
            );
        }

        foreach ($saldos['debe'] as $saldo) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_x_cobrar_asociado',
                    'escenario' => $this->escenario,
                    'tipo_parametro' => $this->tipo_parametro,
                    'proceso' => $saldo['id_unidad'],
                ]),
                0,
                $saldo['cta_x_cobrar_asociado']
            );
        }

        foreach ($saldos['debe'] as $saldo) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_x_cobrar_patron',
                    'escenario' => $this->escenario,
                    'tipo_parametro' => $this->tipo_parametro,
                    'proceso' => $saldo['id_unidad'],
                ]),
                0,
                $saldo['cta_x_cobrar_patron']
            );
        }

        // retenciones de prestamos
        foreach ($this->getRetenciones() as $capital) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_rebaja_cartera_prestamos',
                    'escenario' => $this->escenario_retencion,
                    'tipo_parametro' => $this->tipo_parametro_prestamo,
                    'proceso' => $capital['id_tipo_credito'],
                ]),
                $capital['capital']
            );
        }

        foreach ($this->getRetenciones() as $interes) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_ingresos_interes',
                    'escenario' => $this->escenario_retencion,
                    'tipo_parametro' => $this->tipo_parametro_prestamo,
                    'proceso' => $interes['id_tipo_credito'],
                ]),
                $interes['interes']
            );
        }

        foreach ($this->getRetenciones() as $capital) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_x_cobrar_capital',
                    'escenario' => $this->escenario_retencion,
                    'tipo_parametro' => $this->tipo_parametro_prestamo,
                    'proceso' => $capital['id_tipo_credito'],
                ]),
                0,
                $capital['capital']
            );
        }

        foreach ($this->getRetenciones() as $interes) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_x_cobrar_interes',
                    'escenario' => $this->escenario_retencion,
                    'tipo_parametro' => $this->tipo_parametro_prestamo,
                    'proceso' => $interes['id_tipo_credito'],
                ]),
                0,
                $interes['interes']
            );
        }
    }

    protected function cedula()
    {
        if ($this->cedula == null) {
            $this->cedula = $this->liquidacion->idAsociado->cedula;
        }

        return $this->cedula;
    }

    public function comprobante()
    {
        $this->setProceso(
            new FakeNomina(['fecha_comprobante' => $this->liquidacion->fecha_registro])
        );

        $comprobante = new Comprobante('crea');
        $comprobante->fecha_comprobante = $this->fechaComprobante();
        $comprobante->descripcion = "Reverso aporte {$this->cedula()} por liquidación";
        $comprobante->status = 1;
        $comprobante->nro_documento = $this->cedula();

        if (! $comprobante->save()) {
            throw new Exception('Error al generar comprobante contable.', $this->codigo_error);
        }

        return $comprobante;
    }

    private function getRetenciones($key = null, $field = null)
    {
        if ($this->retenciones == null) {
            $this->retenciones = $this->getCuotasDeRetenciones();
        }

        if ($key === null && $field === null) {
            return $this->retenciones;
        }

        return (new Warp($this->retenciones))->map(function ($cuota) use ($key, $field) {
            return [
                "{$key}_{$cuota['id_tipo_credito']}" => $cuota[$field],
            ];
        });
    }

    protected function getCuotasDeRetenciones()
    {
        return Yii::app()->getDb()->createCommand('
            select c.id_tipo_credito as id_tipo_credito,
                   sum(cta.monto_capital) as capital,
                   sum(cta.monto_interes) as interes,
                   sum(cta.monto_cuota) as total
            from prestamos.pre_nomina_tabla_amortizacion pnta
            inner join prestamos.pre_nomina_seguimiento pns on pns.id_pre_nomina_credito=pnta.id_pre_nomina_credito
                and pns.actual is true
            inner join prestamos.credito_tabla_amortizacion cta on cta.id=pnta.id_tabla_amortizacion
                and cta.blnborrado is false
            inner join prestamos.credito c on c.id=cta.idcredito
            where c.idasociado=:asociado
                and pns.id_estatus_pre_nomina in (
                    1,6, -- no afectado
                    3,7,2,4 -- afectado
                )
            group by c.id_tipo_credito
            having sum(cta.monto_cuota) > 0
        ')->bindValue('asociado', $this->liquidacion->idasociado)->queryAll();
    }
}
