<?php

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

class LiquidacionIndividual extends Utilidades
{
    public $escenario = 10;
    protected $liquidacion;
    protected $datos = null;
    protected $tipo_unidad = 1;
    protected $tipo_prestamo = 3;
    protected $titulo_proceso = 3;
    protected $pago_liquidacion = 10;

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

    private function setFicha()
    {
        if ($this->datos !== null) {
            return;
        }

        if ($this->liquidacion->ficha_liquidacion === null) {
            throw new Exception('Faltan datos para generar comprobante.');
        }

        $this->datos = json_decode($this->liquidacion->ficha_liquidacion, true);
    }

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

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

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

    private function movimientos($comprobante)
    {
        $movimiento = new Movimiento(
            $comprobante,
            $this->liquidacion->fecha_pago
        );

        $datos = $this->saldos();
        $unidad = $this->liquidacion->idAsociado->idunidad;

        if ((new Warp($datos))->get('debe.cta_liquid_aporte_socio', 0) > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_liquid_aporte_socio',
                    'escenario' => $this->pago_liquidacion,
                    'tipo_parametro' => $this->tipo_unidad,
                    'proceso' => $unidad,
                ]),
                (new Warp($datos))->get('debe.cta_liquid_aporte_socio', 0)
            );
        }

        if ((new Warp($datos))->get('debe.cta_liquid_aporte_patrono', 0) > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_liquid_aporte_patrono',
                    'escenario' => $this->pago_liquidacion,
                    'tipo_parametro' => $this->tipo_unidad,
                    'proceso' => $unidad,
                ]),
                (new Warp($datos))->get('debe.cta_liquid_aporte_patrono', 0)
            );
        }

        if ((new Warp($datos))->get('debe.cta_liquid_aporte_vol_socio', 0) > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_liquid_aporte_vol_socio',
                    'escenario' => $this->pago_liquidacion,
                    'tipo_parametro' => $this->tipo_unidad,
                    'proceso' => $unidad,
                ]),
                (new Warp($datos))->get('debe.cta_liquid_aporte_vol_socio', 0)
            );
        }

        if ((new Warp($datos))->get('debe.cta_liquid_aporte_vol_patrono', 0) > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_liquid_aporte_vol_patrono',
                    'escenario' => $this->pago_liquidacion,
                    'tipo_parametro' => $this->tipo_unidad,
                    'proceso' => $unidad,
                ]),
                (new Warp($datos))->get('debe.cta_liquid_aporte_vol_patrono', 0)
            );
        }

        if ((new Warp($datos))->get('haber.cta_liquid_retiro_parcial', 0) > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_liquid_retiro_parcial',
                    'escenario' => $this->pago_liquidacion,
                    'tipo_parametro' => $this->tipo_unidad,
                    'proceso' => $unidad,
                ]),
                0,
                (new Warp($datos))->get('haber.cta_liquid_retiro_parcial', 0)
            );
        }

        $saldos = (new Warp($datos))->get('haber.cta_liquid_plazo_prestamo', []);
        if ($this->configuracionAuxiliar('cta_liquid_plazo_prestamo')) {
            foreach ((new Group([
                'by' => 'cta_liquid_plazo_prestamo',
                'column' => 'monto',
                'escenario' => $this->pago_liquidacion,
                'tipo_parametro' => $this->tipo_prestamo,
                'data' => $saldos,
            ]))->get() as $prestamo) {
                $movimiento->crear(
                    $prestamo['cuenta_contable'],
                    0,
                    $prestamo['monto']
                );
            }
        } else {
            $monto = (new Warp($saldos))->sum('monto', 0);
            if ($monto > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'cta_liquid_plazo_prestamo',
                        'escenario' => null,
                        'tipo_parametro' => null,
                        'proceso' => null,
                    ]),
                    0,
                    $monto
                );
            }
        }

        $saldos = (new Warp($datos))->get('haber.cta_liquid_x_cobrar_capital', []);
        if ($this->configuracionAuxiliar('cta_liquid_x_cobrar_capital')) {
            foreach ((new Group([
                'by' => 'cta_liquid_x_cobrar_capital',
                'column' => 'monto',
                'escenario' => $this->pago_liquidacion,
                'tipo_parametro' => $this->tipo_prestamo,
                'data' => $saldos,
            ]))->get() as $capital) {
                $movimiento->crear(
                    $capital['cuenta_contable'],
                    0,
                    $capital['monto']
                );
            }
        } else {
            $monto = (new Warp($saldos))->sum('monto', 0);
            if ($monto > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'cta_liquid_x_cobrar_capital',
                        'escenario' => null,
                        'tipo_parametro' => null,
                        'proceso' => null,
                    ]),
                    0,
                    $monto
                );
            }
        }

        $saldos = (new Warp($datos))->get('haber.cta_liquid_x_cobrar_interes', []);
        if ($this->configuracionAuxiliar('cta_liquid_x_cobrar_interes')) {
            foreach ((new Group([
                'by' => 'cta_liquid_x_cobrar_interes',
                'column' => 'monto',
                'escenario' => $this->pago_liquidacion,
                'tipo_parametro' => $this->tipo_prestamo,
                'data' => $saldos,
            ]))->get() as $interes) {
                $movimiento->crear(
                    $interes['cuenta_contable'],
                    0,
                    $interes['monto']
                );
            }
        } else {
            $monto = (new Warp($saldos))->sum('monto', 0);
            if ($monto > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'cta_liquid_x_cobrar_interes',
                        'escenario' => null,
                        'tipo_parametro' => null,
                        'proceso' => null,
                    ]),
                    0,
                    $monto
                );
            }
        }

        $saldos = (new Warp($datos))->get('haber.cta_liquid_ingreso_interes', []);
        if ($this->configuracionAuxiliar('cta_liquid_ingreso_interes')) {
            foreach ((new Group([
                'by' => 'cta_liquid_ingreso_interes',
                'column' => 'monto',
                'escenario' => $this->pago_liquidacion,
                'tipo_parametro' => $this->tipo_prestamo,
                'data' => $saldos,
            ]))->get() as $interes) {
                $movimiento->crear(
                    $interes['cuenta_contable'],
                    0,
                    $interes['monto']
                );
            }
        } else {
            $monto = (new Warp($saldos))->sum('monto', 0);
            if ($monto > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'cta_liquid_ingreso_interes',
                        'escenario' => null,
                        'tipo_parametro' => null,
                        'proceso' => null,
                    ]),
                    0,
                    $monto
                );
            }
        }

        $saldos = (new Warp($datos))->get('debe.cta_liquid_ingreso_diferido', []);
        if ($this->configuracionAuxiliar('cta_liquid_ingreso_diferido')) {
            foreach ((new Group([
                'by' => 'cta_liquid_ingreso_diferido',
                'column' => 'monto',
                'escenario' => $this->pago_liquidacion,
                'tipo_parametro' => $this->tipo_prestamo,
                'data' => $saldos,
            ]))->get() as $capital) {
                $movimiento->crear(
                    $capital['cuenta_contable'],
                    $capital['monto']
                );
            }
        } else {
            $monto = (new Warp($saldos))->sum('monto', 0);
            if ($monto > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'cta_liquid_ingreso_diferido',
                        'escenario' => null,
                        'tipo_parametro' => null,
                        'proceso' => null,
                    ]),
                    $monto
                );
            }
        }

        if ((new Warp($datos))->get('haber.cta_liquid_com_administrativa', 0) > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_liquid_com_administrativa',
                    'escenario' => $this->pago_liquidacion,
                    'tipo_parametro' => $this->tipo_unidad,
                    'proceso' => $unidad,
                ]),
                0,
                (new Warp($datos))->get('haber.cta_liquid_com_administrativa', 0)
            );
        }

        if ((new Warp($datos))->get('haber.cta_liquid_com_bancaria', 0) > 0) {
            $movimiento->crear(
                BancoCuentaContable::get($this->liquidacion->id_banco),
                0,
                (new Warp($datos))->get('haber.cta_liquid_com_bancaria', 0)
            );
        }

        if ((new Warp($datos))->get('haber.cta_liquid_rebaja_banco', 0) > 0) {
            $movimiento->crear(
                BancoCuentaContable::get($this->liquidacion->id_banco),
                0,
                (new Warp($datos))->get('haber.cta_liquid_rebaja_banco', 0)
            );
        }

        if ((new Warp($datos))->get('debe.cta_liquid_cuenta_cobrar', 0) > 0) {
            $movimiento->crear(
                Parametros::getCuentaContable([
                    'clave' => 'cta_liquid_cuenta_cobrar',
                    'escenario' => $this->pago_liquidacion,
                    'tipo_parametro' => $this->tipo_unidad,
                    'proceso' => $unidad,
                ]),
                (new Warp($datos))->get('debe.cta_liquid_cuenta_cobrar', 0)
            );
        }
    }

    private function saldos()
    {
        $debe = (new Warp([
            'cta_liquid_aporte_socio' => $this->aporteAsociado(),
            'cta_liquid_aporte_patrono' => $this->aportePatrono(),
            'cta_liquid_aporte_vol_socio' => $this->datos('asignaciones.conceptos.2.monto') + $this->datos('asignaciones.conceptos.6.monto'),
            'cta_liquid_aporte_vol_patrono' => $this->datos('asignaciones.conceptos.3.monto'),
            'cta_liquid_ingreso_diferido' => $this->datos('interes_afectado_prenomina.conceptos', 'cta_liquid_ingreso_diferido'),
            'cta_liquid_cuenta_cobrar' => $this->datos('totales.cuenta_x_cobrar'),
        ]))->flatten();

        $haber = (new Warp([
            'cta_liquid_retiro_parcial' => $this->datos('retiro_deducciones.conceptos.2.monto'),
            'cta_liquid_plazo_prestamo' => $this->datos('capital_cartera_prestamos.conceptos', 'cta_liquid_plazo_prestamo'),
            'cta_liquid_x_cobrar_capital' => $this->datos('capital_afectado_prenomina.conceptos', 'cta_liquid_x_cobrar_capital'),
            'cta_liquid_x_cobrar_interes' => $this->datos('interes_afectado_prenomina.conceptos', 'cta_liquid_x_cobrar_interes'),
            'cta_liquid_ingreso_interes' => $this->datos('interes_afectado_prenomina.conceptos', 'cta_liquid_ingreso_interes'),
            'cta_liquid_com_administrativa' => $this->datos('totales.comision_administrativa'),
            'cta_liquid_com_bancaria' => $this->datos('totales.comision_bancaria'),
            'cta_liquid_rebaja_banco' => $this->datos('totales.total_a_depositar'),
        ]))->flatten();

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

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

        return [
            'debe' => [
                'cta_liquid_aporte_socio' => $this->aporteAsociado(),
                'cta_liquid_aporte_patrono' => $this->aportePatrono(),
                'cta_liquid_aporte_vol_socio' => $this->datos('asignaciones.conceptos.2.monto') + $this->datos('asignaciones.conceptos.6.monto'),
                'cta_liquid_aporte_vol_patrono' => $this->datos('asignaciones.conceptos.3.monto'),
                'cta_liquid_ingreso_diferido' => $this->datos('interes_afectado_prenomina.conceptos'),
                'cta_liquid_cuenta_cobrar' => $this->datos('totales.cuenta_x_cobrar'),
            ],
            'haber' => [
                'cta_liquid_retiro_parcial' => $this->datos('retiro_deducciones.conceptos.2.monto'),
                'cta_liquid_plazo_prestamo' => $this->datos('capital_cartera_prestamos.conceptos'),
                'cta_liquid_x_cobrar_capital' => $this->datos('capital_afectado_prenomina.conceptos'),
                'cta_liquid_x_cobrar_interes' => $this->datos('interes_afectado_prenomina.conceptos'),
                'cta_liquid_ingreso_interes' => $this->datos('interes_afectado_prenomina.conceptos'),
                'cta_liquid_com_administrativa' => $this->datos('totales.comision_administrativa'),
                'cta_liquid_com_bancaria' => $this->datos('totales.comision_bancaria'),
                'cta_liquid_rebaja_banco' => $this->datos('totales.total_a_depositar'),
            ],
        ];
    }

    private function comprobante()
    {
        $this->setProceso($this->liquidacion);

        $comprobante = new Comprobante();
        $comprobante->fecha_comprobante = $this->fechaComprobante();
        $comprobante->descripcion = 'Liquidación a '.$this->liquidacion->idAsociado->nombreCompleto();
        $comprobante->status = 1;
        $comprobante->nro_documento = $this->liquidacion->referencia_pago;
        if (! $comprobante->save()) {
            throw new Exception('Error al generar comprobante contable.', $this->codigo_error);
        }

        return $comprobante;
    }

    protected function datos($path = null, $key = null)
    {
        $datos = (new Warp($this->datos))->get($path, 0);

        if ($key !== null) {
            return (new Warp($datos))->flatMap(function ($concepto) use ($key) {
                return [
                    "{$key}_{$concepto['id_tipo_credito']}" => $concepto['monto'],
                ];
            });
        }

        return $datos;
    }

    protected function aporteAsociado()
    {
        return ($this->datos('asignaciones.conceptos.0.monto') + $this->datos('asignaciones.conceptos.4.monto')) - $this->datos('retiro_deducciones.conceptos.0.monto');
    }

    protected function aportePatrono()
    {
        return ($this->datos('asignaciones.conceptos.1.monto') + $this->datos('asignaciones.conceptos.5.monto')) - $this->datos('retiro_deducciones.conceptos.1.monto');
    }
}
