<?php
namespace Incoviba\Model\Venta;

use DateTimeInterface;
use Incoviba\Common\Ideal\Model;
use Incoviba\Model\Venta;

class Pie extends Model
{
    public DateTimeInterface $fecha;
    public float $valor;
    public ?float $uf;
    public int $cuotas;
    public ?Pie $asociado;
    public ?Pago $reajuste;

    public array $cuotasArray = [];
    public function cuotas(bool $pagadas = false, bool $vigentes = false): array
    {
        if ($this->asociado !== null) {
            $cuotas = $this->asociado->cuotas($pagadas, $vigentes);
            $this->cuotasArray = array_merge($this->cuotasArray, $cuotas);
        }
        if (!$pagadas and !$vigentes) {
            return $this->cuotasArray;
        }
        if ($pagadas) {
            return array_filter($this->cuotasArray, function(Cuota $cuota) {
                return in_array($cuota->pago->currentEstado->tipoEstadoPago->descripcion, ['depositado', 'abonado']);
            });
        }
        return array_filter($this->cuotasArray, function(Cuota $cuota) {
            return $cuota->pago->currentEstado->tipoEstadoPago->activo or $cuota->pago->currentEstado->tipoEstadoPago->descripcion === 'devuelto';
        });
    }

    public function valor(string $moneda = Pago::UF): float
    {
        $proporcion = $this->proporcion();
        if ($this->asociado !== null) {
            return $this->asociado->valor($moneda) * $proporcion;
        }
        return array_reduce($this->cuotas(), function(float $sum, Cuota $cuota) use ($moneda) {
                return $sum + $cuota->pago->valor($moneda);
            }, 0) * $proporcion;
    }
    protected array $pagado;
    public function pagado(string $moneda = Pago::UF): float
    {
        $proporcion = $this->proporcion();
        if ($this->asociado !== null) {
            return $this->asociado->pagado($moneda) / $this->asociado->proporcion() * $proporcion;
        }
        if (!isset($this->pagado[$moneda])) {
            $this->pagado[$moneda] = array_reduce($this->cuotas(true), function(float $sum, Cuota $cuota) use ($moneda) {
                return $sum + $cuota->pago->valor($moneda);
            }, 0);
        }
        return $this->pagado[$moneda] * $proporcion;
    }
    protected function proporcion(): float
    {
        $proporcion = 1;
        if (count($this->asociados()) > 0) {
            $proporcion = $this->valor / ((($this->asociado) ? $this->asociado->valor : $this->valor) + array_reduce($this->asociados(), function(float $sum, Pie $pie) {
                        return $sum + $pie->valor;
                    }, 0));
        }
        return $proporcion;
    }

    public ?array $asociados;
    public function asociados(): array
    {
        if ($this->asociado !== null) {
            return $this->asociado->asociados();
        }
        if (!isset($this->asociados) or $this->asociados === []) {
            $this->asociados = $this->runFactory('asociados');
        }
        return $this->asociados ?? [];
    }

    public function jsonSerialize(): mixed
    {
        return array_merge(parent::jsonSerialize(), [
            'fecha' => $this->fecha->format('Y-m-d H:i:s'),
            'valor' => $this->valor,
            'uf' => $this->uf ?? 1,
            'cuotas' => $this->cuotas,
            'asociado' => $this->asociado ?? '',
            'reajuste' => $this->reajuste ?? ''
        ]);
    }
}
