<?php

class AjusteMasivo extends Utilidades
{
    protected $data;
    protected $nomina;
    protected $escenario = 11;
    protected $titulo_proceso = 14;
    protected $tipo_parametro_unidad = 1;
    protected $escenario_aporte_ordinario = 3;

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

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

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

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

    protected function data()
    {
        if ($this->data == null) {
            $this->data = Yii::app()->getDb()->createCommand('
                SELECT idunidad as id_unidad,
                       coalesce(sum(monto_asociado),0) AS monto_asociado,
                       coalesce(sum(monto_patrono),0) AS monto_patrono,
                       coalesce(sum(monto_asociado),0) + coalesce(sum(monto_patrono),0) as total
                from ajuste_haberes.ajuste_haberes ah
                inner join asociado a on a.idasociado=ah.idasociado
                where ah.id_nomina_ajuste_haberes=:id
                group by a.idunidad
            ')->bindValue('id', $this->nomina->id)->queryAll();
        }

        return $this->data;
    }

    protected function convert($key = null, $column = null)
    {
        $data = $this->data();

        if ($key !== null) {
            return (new Warp($data))->flatMap(function ($ajuste) use ($column, $key) {
                return [
                    "{$key}_{$ajuste['id_unidad']}" => $ajuste[$column],
                ];
            });
        }

        return $datos;
    }

    protected function total()
    {
        $data = $this->data();

        return (new Warp($data))->sum('total');
    }

    protected function saldos()
    {
        $debe = (new Warp(
            $this->debe()
        ))->flatten();

        $haber = (new Warp(
            $this->haber()
        ))->flatten();

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

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

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

    protected function debe()
    {
        if ($this->nomina->id_tipo_ajuste == 1) {
            return [
                'clv_ajuste_aporte_socio' => $this->convert('clv_ajuste_aporte_socio', 'monto_asociado'),
                'clv_ajuste_aporte_patrono' => $this->convert('clv_ajuste_aporte_patrono', 'monto_patrono'),
            ];
        }

        return [
            'clv_concepto_ajuste' => $this->total(),
        ];
    }

    protected function haber()
    {
        if ($this->nomina->id_tipo_ajuste == 1) {
            return [
                'clv_concepto_ajuste' => $this->total(),
            ];
        }

        return [
            'clv_ajuste_aporte_socio' => $this->convert('clv_ajuste_aporte_socio', 'monto_asociado'),
            'clv_ajuste_aporte_patrono' => $this->convert('clv_ajuste_aporte_patrono', 'monto_patrono'),
        ];
    }

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

        $saldos = $this->saldos();

        if ($this->nomina->id_tipo_ajuste == 1) {
            return $this->deduccion($movimiento, $saldos);
        }

        return $this->asignacion($movimiento, $saldos);
    }

    protected function asignacion($movimiento, $saldos)
    {
        $movimiento->crear(
            CuentaConcepto::find($this->nomina->id_concepto_ajuste),
            $saldos['clv_concepto_ajuste']
        );

        foreach ($this->data as $ajuste) {
            if ($ajuste['monto_asociado'] > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'aport_rec_asociado',
                        'escenario' => $this->escenario_aporte_ordinario,
                        'tipo_parametro' => $this->tipo_parametro_unidad,
                        'proceso' => $ajuste['id_unidad'],
                    ]),
                    0,
                    $ajuste['monto_asociado']
                );
            }
        }

        foreach ($this->data as $ajuste) {
            if ($ajuste['monto_patrono'] > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'aport_rec_patron',
                        'escenario' => $this->escenario_aporte_ordinario,
                        'tipo_parametro' => $this->tipo_parametro_unidad,
                        'proceso' => $ajuste['id_unidad'],
                    ]),
                    0,
                    $ajuste['monto_patrono']
                );
            }
        }
    }

    protected function deduccion($movimiento, $saldos)
    {
        foreach ($this->data as $ajuste) {
            if ($ajuste['monto_asociado'] > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'aport_rec_asociado',
                        'escenario' => $this->escenario_aporte_ordinario,
                        'tipo_parametro' => $this->tipo_parametro_unidad,
                        'proceso' => $ajuste['id_unidad'],
                    ]),
                    $ajuste['monto_asociado']
                );
            }
        }

        foreach ($this->data as $ajuste) {
            if ($ajuste['monto_patrono'] > 0) {
                $movimiento->crear(
                    Parametros::getCuentaContable([
                        'clave' => 'aport_rec_patron',
                        'escenario' => $this->escenario_aporte_ordinario,
                        'tipo_parametro' => $this->tipo_parametro_unidad,
                        'proceso' => $ajuste['id_unidad'],
                    ]),
                    $ajuste['monto_patrono']
                );
            }
        }

        $movimiento->crear(
            CuentaConcepto::find($this->nomina->id_concepto_ajuste),
            0,
            $saldos['clv_concepto_ajuste']
        );
    }

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

        $comprobante = new Comprobante('crea');
        $comprobante->fecha_comprobante = $this->fechaComprobante();
        $comprobante->descripcion = $this->descripcion();
        $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 descripcion()
    {
        return vsprintf('%s a %s', [
            $this->tipoAjuste(),
            $this->nomina->nombre_archivo,
        ]);
    }

    protected function tipoAjuste()
    {
        switch ($this->nomina->id_tipo_ajuste) {
            case 1:
                return 'Deducción masiva de haberes';
            case 2:
                return 'Asignación masiva de haberes';
        }
    }
}
