<?php

// Para obtener la porcion del monto de bloqueo por los prestamos del asociado
// new DeudaActual(id_asociado)->bloqueo();

// Para obtener la porcion del monto que no tiene bloqueo de los prestamos del asociado
// new DeudaActual(id_asociado)->noBloqueo()

// Para obtener el total del monto deudor del asociado por todos los prestamos
// new DeudaActual(id_asociado)->total()

// Para obtener el monto de bloqueo de un prestamo en especifico
// new DeudaActual(id_asociado)->get($prestamo)

class DeudaActual
{
    protected $asociado;
    protected $bloqueo = null;
    protected $process = null;
    protected $prestamos = null;

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

    public function getBloqueo()
    {
        return $this->bloqueo;
    }

    public function setBloqueo($bloqueo)
    {
        $this->bloqueo = $bloqueo;
        return $this;
    }

    public function bloqueo()
    {
        $this->prestamos = $this->getPrestamos();
        return array_sum(
            (new Warp($this->prestamos))->map(function ($prestamo) {
                return $this->calculate($prestamo, true);
            })
        );
    }

    public function noBloqueo()
    {
        $total = 0;
        $model = Yii::app()->db->createCommand('
            SELECT t.idasociado,
                   t.id_tipo_credito,
                   t.prestamo,
                   t.deuda_actual,
                   t.deuda_actual_esp,
                   tc.metodo_liberacion_capital,
                   tc.monto_disponibilidad_solicitudes
            FROM "reporte_creditos" "t"
            inner join prestamos.tipo_credito tc on t.id_tipo_credito=tc.id
            WHERE t.idasociado=:id
                AND t.afecta_disponibilidad_haberes=TRUE
                AND t.id_estatus_credito IN (4,7,9,15,16)
                AND tc.monto_disponibilidad_solicitudes IS NULL
        ')->bindValue('id', $this->asociado)->queryAll();

        if (! $model) {
            return $total;
        }

        foreach ($model as $prestamo) {
            if ($prestamo['metodo_liberacion_capital'] == 2) {
                $total += $prestamo['prestamo'];
            } else {
                $total += $prestamo['deuda_actual'] + $prestamo['deuda_actual_esp'];
            }
        }

        return $total;
    }

    public function total()
    {
        $this->prestamos = $this->getPrestamos();
        return array_sum(
            (new Warp($this->prestamos))->map(function ($prestamo) {
                return $this->calculate($prestamo);
            })
        );
    }

    public function isEmpty($prestamo)
    {
        return empty($prestamo['monto_disponibilidad_solicitudes']);
    }

    public function hasBloqueo()
    {
        if ($this->getBloqueo() == null) {
            $bloqueo = Yii::app()->db->createCommand('
                SELECT exists(
                    SELECT 1
                    FROM "reporte_creditos" "t"
                    inner join prestamos.tipo_credito tc on t.id_tipo_credito=tc.id
                    WHERE t.idasociado=:id
                      AND t.afecta_disponibilidad_haberes=TRUE
                      AND t.id_estatus_credito IN (4,7,9,15,16)
                      AND tc.monto_disponibilidad_solicitudes is not null
                )
            ')->bindValue('id', $this->asociado)->queryRow()['exists'];

            $this->setBloqueo($bloqueo);
        }

        return $this->getBloqueo();
    }

    public function get($prestamo)
    {
        if (Yii::app()->user->checkAccess('usuario_asociado')) {
            return $this->prestamoAsociado($prestamo);
        }

        return $this->prestamoAdmin($prestamo);
    }

    private function calculate($prestamo, $bloqueo = false)
    {
        if ($prestamo['metodo_liberacion_capital'] != 1) {
            return $prestamo['prestamo'];
        }

        if ($this->isEmpty($prestamo) && ! $bloqueo) {
            return $prestamo['deuda_actual'] + $prestamo['deuda_actual_esp'];
        }

        return $this->get($prestamo);
    }

    private function prestamoAdmin($prestamo)
    {
        if (! isset($prestamo['bloqueo_porcentaje'])) {
            $prestamo = $this->process([$prestamo])[0];
        }

        if ($prestamo['bloqueo_porcentaje']) {
            if ($prestamo['porcentaje_administrador'] != '') {
                return $prestamo['prestamo'] * $prestamo['porcentaje_administrador'];
            }
        } else {
            if ($prestamo['monto_administrador'] != '') {
                return $prestamo['monto_administrador'];
            }
        }
    }

    private function prestamoAsociado($prestamo)
    {
        if (! isset($prestamo['bloqueo_porcentaje'])) {
            $prestamo = $this->process([$prestamo])[0];
        }

        if ($prestamo['bloqueo_porcentaje'] == 1) {
            if ($prestamo['porcentaje_asociado'] != '') {
                return $prestamo['porcentaje_asociado'] * $prestamo['prestamo'];
            }
        } else {
            if ($prestamo['monto_asociado'] != '') {
                return $prestamo['monto_asociado'];
            }
        }
    }

    private function getPrestamos()
    {
        if ($this->prestamos == null) {
            $this->prestamos = $this->process(
                Yii::app()->db->createCommand('
                    SELECT t.id_tipo_credito,
                           t.prestamo,
                           t.deuda_actual,
                           t.deuda_actual_esp,
                           tc.metodo_liberacion_capital,
                           tc.monto_disponibilidad_solicitudes
                    FROM "reporte_creditos" "t"
                    inner join prestamos.tipo_credito tc on t.id_tipo_credito=tc.id
                    WHERE t.idasociado=:id
                        AND t.afecta_disponibilidad_haberes=TRUE
                        AND t.id_estatus_credito IN (4,7,9,15,16)
                ')->bindValue('id', $this->asociado)->queryAll()
            );
        }

        return $this->prestamos;
    }

    private function process($prestamos)
    {
        if ($this->process == null) {
            $this->process = (new Warp($prestamos))->map(function ($prestamo) {
                $datos = [
                    'bloqueo_porcentaje' => null,
                    'monto_administrador' => null,
                    'monto_asociado' => null,
                    'porcentaje_administrador' => null,
                    'porcentaje_asociado' => null,
                ];

                if ($this->isEmpty($prestamo)) {
                    return array_merge($prestamo, $datos);
                }

                $bloqueo = (object) json_decode($prestamo['monto_disponibilidad_solicitudes'], true);

                if (isset($bloqueo->monto_bloqueo_haberes_administrador)) {
                    $datos['bloqueo_porcentaje'] = false;
                    $datos['monto_administrador'] = $bloqueo->monto_bloqueo_haberes_administrador;
                }

                if (isset($bloqueo->monto_bloqueo_haberes_asociado)) {
                    $datos['bloqueo_porcentaje'] = false;
                    $datos['monto_asociado'] = $bloqueo->monto_bloqueo_haberes_asociado;
                }

                if (isset($bloqueo->porcentaje_bloqueo_haberes_administrador)) {
                    $datos['bloqueo_porcentaje'] = true;
                    $datos['porcentaje_administrador'] = $bloqueo->porcentaje_bloqueo_haberes_administrador / 100;
                }

                if (isset($bloqueo->porcentaje_bloqueo_haberes_asociado)) {
                    $datos['bloqueo_porcentaje'] = true;
                    $datos['porcentaje_asociado'] = $bloqueo->porcentaje_bloqueo_haberes_asociado / 100;
                }

                return array_merge($prestamo, $datos);
            });
        }

        return $this->process;
    }
}
