<?php

Yii::import('application.modules.configuracion.models.*');

class SituacionFinancieraQuery
{
    use AttributeAccess;

    protected $attributes;

    public function __construct($attributes = [])
    {
        $this->attributes = $attributes;
    }

    public function run()
    {
        $where_cuenta = '';
        $where_total_cuenta = '';
        $where_nivel = '';

        if ($this->hasAccountRange()) {
            $where_cuenta = " AND cuenta BETWEEN '{$this->cuenta_desde}' AND '{$this->cuenta_hasta}'
                              AND titulo_mov = 2
                              OR (titulo_mov = 1 AND cuenta BETWEEN '1' AND '{$this->cuenta_hasta}')";
            $where_total_cuenta = " AND cuenta BETWEEN '{$this->cuenta_desde}' AND '{$this->cuenta_hasta}' ";
        }

        if ($this->nivel != null) {
            $where_nivel = ' AND nivel <= '.$this->nivel.' ';
        }

        if ($this->excluir_movimiento_cierre) {
            $movimiento_cierre = 'AND (id_tipo_comprobante=1 OR id_tipo_comprobante=2)';
        } else {
            $movimiento_cierre = 'AND (id_tipo_comprobante=1 OR id_tipo_comprobante=2 OR id_tipo_comprobante=3)';
        }

        // Vamos a buscar los dias primero y ultimo de dicho rango (trimestre)
        if ($this->trimestre == 1) {
            $filtro_trimestre_ant = 4; //trimestre anterior
            $filtro_anyo_ant = $this->anyo - 1; //año del trimestre anterior
        } else {
            $filtro_trimestre_ant = $this->trimestre - 1;
            $filtro_anyo_ant = $this->anyo;
        }

        $mes_ultimo_trimestre = $this->trimestre * 3;
        $mes_primero_trimestre = ($mes_ultimo_trimestre - 3) + 1;

        $mes_ultimo_trimestre_ant = $filtro_trimestre_ant * 3;
        $mes_primero_trimestre_ant = ($mes_ultimo_trimestre_ant - 3) + 1;

        $fecha_hasta_trimestre = date('Y-m-t', strtotime($this->anyo.'-'.$mes_ultimo_trimestre.'-01'));
        $fecha_desde_trimestre = date('Y-m-t', strtotime($this->anyo.'-'.$mes_primero_trimestre.'-01'));

        if (! $this->validateDate($fecha_desde_trimestre) || ! $this->validateDate($fecha_hasta_trimestre)) {
            return [[], true, 'No ha seleccionado un año para consulta la informacion.'];
        }

        $fecha_hasta_trimestre_ant = date('Y-m-t', strtotime($filtro_anyo_ant.'-'.$mes_ultimo_trimestre_ant.'-01'));
        $fecha_desde_trimestre_ant = $filtro_anyo_ant.'-'.$mes_primero_trimestre_ant.'-01';

        if ($fecha_desde_trimestre != null && $fecha_hasta_trimestre != null) {
            $where_fecha = " AND fecha_comprobante BETWEEN '${fecha_desde_trimestre}' AND '${fecha_hasta_trimestre}' ";
        }

        if ($fecha_desde_trimestre_ant != null && $fecha_hasta_trimestre_ant != null) {
            $where_fecha_ant = " AND fecha_comprobante BETWEEN '${fecha_desde_trimestre_ant}' AND '${fecha_hasta_trimestre_ant}' ";
        }

        $fecha_ant = " AND fecha_comprobante < '${fecha_desde_trimestre}'";

        $model_plan_cuentas = CuentasConsolidada::model()->findAll([
            'condition' => "blnborrado = FALSE AND SUBSTRING(cuenta from 1 for 1) IN ('1','2','3')  ".$where_cuenta.''.$where_nivel,
            'order' => 'cuenta ASC',
        ]);

        $ctas = Yii::app()->getDb()->createCommand("
            SELECT id
            FROM contable.cuentas_consolidada
            WHERE codigo_cuenta ILIKE '%341.%'
                AND blnborrado=false
                AND titulo_mov=1
        ")->queryColumn();

        $config_contable = ['0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 5, '5' => 7, '6' => 9, '7' => 11];
        // $config_contable = [
        //     '0' => 0,
        //     '1' => 3,
        //     '2' => 5,
        //     '3' => 7,
        //     '4' => 9,
        //     '5' => 11,
        //     '6' => 13,
        //     '7' => 15,
        // ];

        $datos = [];
        $acum_total_anterior = 0;
        $acum_total_actual = 0;
        $acum_variacion = 0;

        $acum_activos_anterior = 0;
        $acum_activos_actual = 0;
        $acum_activos_variacion = 0;

        $acum_pasivos_anterior = 0;
        $acum_pasivos_actual = 0;
        $acum_pasivos_variacion = 0;

        $acum_patrimonio_anterior = 0;
        $acum_patrimonio_actual = 0;
        $acum_patrimonio_variacion = 0;

        $datos['attributes'] = $this->attributes;
        $datos['attributes']['fecha_hasta'] = date('d-m-Y', strtotime($fecha_hasta_trimestre));

        $ejercicio = EjerciciosContables::model()->find('activo=1');
        $conf_contable = ConfContable::model()->find('id=4');
        foreach ($model_plan_cuentas as $cuenta) {
            // Buscamos el detalle de cada cuenta
            $ingresoactual = DetalleAnalitico::model()->find([
                'select' => 'COALESCE(sum(monto_debe), 0) -COALESCE(sum(monto_haber), 0) as total_monto_actual',
                'condition' => "SUBSTRING('400000000' from 1 for 1 ) = SUBSTRING(cuenta from 1 for 1 )
                                AND estatus_contab=1
                                AND activo=1
                                AND clvejercicio={$ejercicio->id}
                                AND blnborrado=FALSE
                                {$movimiento_cierre}
                                {$where_fecha}",
            ]);
            $ingresoanterior = DetalleAnalitico::model()->find([
                'select' => 'COALESCE(sum(monto_debe), 0) -COALESCE(sum(monto_haber), 0) as total_monto_anterior',
                'condition' => "SUBSTRING('400000000' from 1 for 1 ) = SUBSTRING(cuenta from 1 for 1 )
                                AND estatus_contab=1
                                AND activo=1
                                AND clvejercicio={$ejercicio->id}
                                AND blnborrado=FALSE
                                {$movimiento_cierre}
                                {$fecha_ant}",
            ]);

            // condicion para las cuentas de excedente y patrimonio
            $cuentaPatrimonioExcedente = in_array($cuenta->id, array_merge($ctas, [
                'patrimonio' => 477,
                'excedente' => 498,
                'utilidad_retenida_ejercicio' => $conf_contable->atributo,
            ]));

            /*
                * TRIMESTRE ANTERIOR
                *
                * Consulta la utilidad acumulada del periodo anterior cuando se consulta el primer trimestre
                */
            if ($this->trimestre == 1) {
                $model_total_anterior = DetalleAnalitico::model()->find([
                    'select' => 'COALESCE(sum(monto_debe), 0) - COALESCE(sum(monto_haber), 0) as total_monto_anterior ',
                    'condition' => "SUBSTRING('{$cuenta->cuenta}' from 1 for '{$config_contable[$cuenta->nivel]}') = SUBSTRING(cuenta from 1 for '{$config_contable[$cuenta->nivel]}')
                                    AND estatus_contab=1
                                    AND activo=1
                                    AND clvejercicio={$ejercicio->id}
                                    AND blnborrado=FALSE
                                    AND id_tipo_comprobante=2
                                    {$where_total_cuenta}",
                ]);
            } else {
                /*
                    * con esta sección se imprime en la cuenta de utilidad acumulada (id_cuenta) que está colocada en
                    * la sección de configuración global contable. Se observa que se marcan id de cuentas por defecto
                    * para que pueda sumar los totales a los niveles padres de la cuenta axulilizar destinada para
                    * imprimir el valor de la utilidad acumulada (se eliminó el filtro $ejercicio->estatus!=3)
                    */
                if ($cuentaPatrimonioExcedente && $ingresoanterior->total_monto_anterior != null) {
                    $model_total_anterior = DetalleAnalitico::model()->find([
                        'select' => "COALESCE(sum(monto_debe), 0) -
                                        COALESCE(sum(monto_haber), 0) +
                                        (
                                        (
                                            SELECT COALESCE(sum(monto_debe), 0) - COALESCE(sum(monto_haber), 0) as total_monto_actual
                                            FROM contable.vsw_detalle_analitico
                                            WHERE SUBSTRING('400000000' from 1 for 1) = SUBSTRING(cuenta from 1 for 1)
                                                AND estatus_contab=1
                                                AND activo=1
                                                AND clvejercicio={$ejercicio->id}
                                                AND blnborrado = FALSE
                                                {$movimiento_cierre}
                                                {$fecha_ant}
                                            LIMIT 1
                                        ) +
                                        (
                                            SELECT COALESCE(sum(monto_debe), 0) - COALESCE(sum(monto_haber), 0) as total_monto_actual
                                            FROM contable.vsw_detalle_analitico
                                            WHERE SUBSTRING('500000000' from 1 for 1) = SUBSTRING(cuenta from 1 for 1)
                                                AND estatus_contab=1
                                                AND activo=1
                                                AND clvejercicio={$ejercicio->id}
                                                AND blnborrado=FALSE
                                                {$movimiento_cierre}
                                                {$fecha_ant}
                                            LIMIT 1
                                        )
                                    ) as total_monto_anterior",
                        'condition' => "SUBSTRING('{$cuenta->cuenta}' from 1 for {$config_contable[$cuenta->nivel]}) = SUBSTRING(cuenta from 1 for {$config_contable[$cuenta->nivel]})
                                        AND estatus_contab=1
                                        AND activo=1
                                        AND clvejercicio={$ejercicio->id}
                                        AND blnborrado=FALSE
                                        {$movimiento_cierre}
                                        {$where_total_cuenta}
                                        {$fecha_ant}",
                    ]);
                } else {
                    /**
                     * Con esta sección se imprimen las cuentas que poseen movimientos de los grupos principales
                     * activo, pasivo y patrimonio.
                     */
                    $model_total_anterior = DetalleAnalitico::model()->find([
                        'select' => 'COALESCE(sum(monto_debe), 0) - COALESCE(sum(monto_haber), 0) as total_monto_anterior ',
                        'condition' => "SUBSTRING('{$cuenta->cuenta}' from 1 for {$config_contable[$cuenta->nivel]}) = SUBSTRING(cuenta from 1 for {$config_contable[$cuenta->nivel]})
                                        AND estatus_contab=1
                                        AND activo=1
                                        AND clvejercicio={$ejercicio->id}
                                        AND blnborrado = FALSE
                                        {$movimiento_cierre}
                                        {$fecha_ant}",
                    ]);
                }
            }

            /*
                * TRIMESTRE ACTUAL
                *
                * Consulta utilidad acumulada del trimestre actual.
                * Con esta sección se imprime en la cuenta de utilidad acumulada (id_cuenta) que está colocada en la
                * sección de configuración global contable. Se observa que se marcan id de cuentas por defecto para
                * que pueda sumar los totales a los niveles padres de la cuenta axulilizar destinada para imprimir
                * el valor de la utilidad acumulada (se eliminó el filtro $ejercicio->estatus!=3)
                */
            if ($cuentaPatrimonioExcedente && $ingresoactual->total_monto_actual != null) {
                $model_total = DetalleAnalitico::model()->find([
                    'select' => 'COALESCE(sum(monto_debe), 0) - COALESCE(sum(monto_haber), 0) as total_monto_actual',
                    'condition' => "(
                                        SUBSTRING('{$cuenta->cuenta}' from 1 for {$config_contable[$cuenta->nivel]}) = SUBSTRING(cuenta from 1 for {$config_contable[$cuenta->nivel]})
                                        OR SUBSTRING('400000000' from 1 for 1) = SUBSTRING(cuenta from 1 for 1)
                                        OR SUBSTRING('500000000' from 1 for 1) = SUBSTRING(cuenta from 1 for 1)
                                    )
                                    AND estatus_contab=1
                                    AND activo=1
                                    AND clvejercicio={$ejercicio->id}
                                    AND blnborrado = FALSE
                                    {$movimiento_cierre}
                                    AND fecha_comprobante <= '{$fecha_hasta_trimestre}'",
                ]);
            } else {
                $model_total = DetalleAnalitico::model()->find([
                    'select' => 'COALESCE(sum(monto_debe), 0) - COALESCE(sum(monto_haber), 0) as total_monto_actual',
                    'condition' => "SUBSTRING('{$cuenta->cuenta}' from 1 for {$config_contable[$cuenta->nivel]}) = SUBSTRING(cuenta from 1 for {$config_contable[$cuenta->nivel]})
                                AND blnborrado = FALSE
                                AND estatus_contab=1
                                AND activo=1
                                AND clvejercicio={$ejercicio->id}
                                {$where_fecha}
                                {$movimiento_cierre}",
                ]);
            }

            $monto_anterior = $model_total_anterior->total_monto_anterior ? $model_total_anterior->total_monto_anterior : 0;
            $monto_actual = $model_total->total_monto_actual ? $model_total->total_monto_actual : 0;

            if (($cuentaPatrimonioExcedente && $ingresoactual->total_monto_actual != null) || $this->trimestre == 1) {
                // formula: (debe - haber)
                $monto_actual = $monto_actual;
            } else {
                // formula: (debe - haber) + saldo_anterior
                $monto_actual = $monto_actual + $monto_anterior;
            }

            $monto_variacion = $monto_actual - $monto_anterior;

            //Verificamos si a la cuenta se le hacen movimientos
            $cta_mov = DetalleComprobante::model()->findByAttributes(['id_cuenta' => $cuenta->id]);

            // Si es una cuenta de movimiento si sumo para el total del balance
            if ($cta_mov != null) {
                $acum_total_anterior += $monto_anterior;
                $acum_total_actual += $monto_actual;
                $acum_variacion += $monto_variacion;
            }

            //total de los activos
            if (trim($cuenta->cuenta[0]) == '1' && $cuenta->nivel == 1) {
                $acum_activos_anterior += $monto_anterior;
                $acum_activos_actual += $monto_actual;
                $acum_activos_variacion += $monto_variacion;
            }

            //total de los pasivos
            if (trim($cuenta->cuenta[0]) == '2' && $cuenta->nivel == 1) {
                $acum_pasivos_anterior += $monto_anterior;
                $acum_pasivos_actual += $monto_actual;
                $acum_pasivos_variacion += $monto_variacion;
            }

            //total de patrimonio
            if (trim($cuenta->cuenta[0]) == '3' && $cuenta->nivel == 1) {
                $acum_patrimonio_anterior += $monto_anterior;
                $acum_patrimonio_actual += $monto_actual;
                $acum_patrimonio_variacion += $monto_variacion;
            }

            // Si son los 3 primeros niveles la presentacion debe ser en mayusculas y negrita
            if (in_array($cuenta->nivel, [1, 2, 3])) {
                $clase_cuenta = 'cuenta_alto_nivel';
            } else {
                $clase_cuenta = '';
            }

            if ($this->sin_ceros && array_sum([$monto_actual, $monto_anterior, $monto_variacion]) == 0) {
                $mostrar = false;
            } else {
                $mostrar = true;
            }

            // Obtenemos el patrimonio:
            $total_patrimonio_anterior = (-$acum_activos_anterior - $acum_pasivos_anterior);
            $total_patrimonio_actual = (-$acum_activos_actual - $acum_pasivos_actual);
            $total_patrimonio_variacion = ($total_patrimonio_actual - $total_patrimonio_anterior);

            if ($mostrar) {
                $datos['detalle'][$cuenta->id] = [
                    'clase' => $clase_cuenta,
                    'cuenta_titulo' => $cuenta->titulo_mov == 1,
                    'cuenta' => $cuenta->cuenta,
                    'descripcion' => $cuenta->descripcion,
                    'anterior' => $monto_anterior,
                    'actual' => $monto_actual,
                    'variacion' => $monto_variacion,
                ];
            }
        }

        $datos['totales'] = [
            'activo' => [
                'anterior' => $acum_activos_anterior,
                'actual' => $acum_activos_actual,
                'variacion' => $acum_activos_variacion,
            ],
            'pasivo' => [
                'anterior' => $acum_pasivos_anterior,
                'actual' => $acum_pasivos_actual,
                'variacion' => $acum_pasivos_variacion,
            ],
            'patrimonio' => [
                'anterior' => $total_patrimonio_anterior,
                'actual' => $total_patrimonio_actual,
                'variacion' => $total_patrimonio_variacion,
            ],
            'pasivo_patrimonio' => [
                'anterior' => $total_patrimonio_anterior + $acum_pasivos_anterior,
                'actual' => $total_patrimonio_actual + $acum_pasivos_actual,
                'variacion' => $total_patrimonio_variacion + $acum_pasivos_variacion,
            ],
        ];

        return [$datos, false, ''];
    }

    public function validateDate($date, $format = 'Y-m-d')
    {
        $d = \DateTime::createFromFormat($format, $date);
        return $d && $d->format($format) == $date;
    }

    protected function hasAccountRange()
    {
        return $this->cuenta_desde != null && $this->cuenta_hasta != null;
    }
}
