<?php
namespace Incoviba\Service\Proyecto;

use Exception;
use DateTimeImmutable;
use DateInterval;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Repository;
use Incoviba\Service;
use Incoviba\Model;

class Terreno extends Ideal\Service
{
    public function __construct(LoggerInterface $logger, protected Repository\Proyecto $proyectoRepository,
                                protected Service\Contabilidad\Nubox $nuboxService, protected Service\IPC $ipcService)
    {
        parent::__construct($logger);
    }

    /**
     * @param int $proyecto_id
     * @return Model\Proyecto\Terreno|null
     * @throws Exception
     */
    public function valor(int $proyecto_id): ?Model\Proyecto\Terreno
    {
        $terreno = null;
        try {
            $proyecto = $this->proyectoRepository->fetchById($proyecto_id);
            $today = new DateTimeImmutable();
            $lastNovember = (new DateTimeImmutable($today->format('Y-01-30')))->sub(new DateInterval('P2M'));
            if ($proyecto->terreno->fecha >= $lastNovember) {
                return $proyecto->terreno;
            }
            try {
                // Valor 1o enero
                return $this->getValorContable($proyecto, $lastNovember->add(new DateInterval('P1M'))->add(new DateInterval('P1D')));
            } catch (Implement\Exception\EmptyResponse) {}
            if ($proyecto->terreno->fecha === null) {
                return null;
            }
            if ($proyecto->terreno->fecha->getTimestamp() > 0) {
                return $this->getValorReajustado($proyecto);
            }
            $terreno = $proyecto->terreno;
        } catch (Implement\Exception\EmptyResult) {}
        return $terreno;
    }

    /**
     * @throws Implement\Exception\EmptyResponse
     * @throws Implement\Exception\EmptyResult
     * @throws Exception
     */
    protected function getValorContable(Model\Proyecto $proyecto, DateTimeImmutable $lastDecember): Model\Proyecto\Terreno
    {
        try {
            $cuentaNubox = $this->nuboxService->getCuenta($proyecto->inmobiliaria()->rut, 'Terrenos');
            $movimientos = $this->nuboxService->getMesCuenta($proyecto->inmobiliaria()->rut, $cuentaNubox, $lastDecember);
        } catch (Implement\Exception\HttpResponse | ClientExceptionInterface $exception) {
            throw new Implement\Exception\EmptyResponse("No existen cuentas para este proyecto para la fecha {$lastDecember->format('d-m-Y')}", $exception);
        }
        if (count($movimientos) === 0 or $movimientos[0]['Saldo'] === 0.0) {
            throw new Implement\Exception\EmptyResponse("No hay movimientos para este proyecto para la fecha {$lastDecember->format('d-m-Y')}");
        }
        $data = [
            'fecha' => (new DateTimeImmutable($movimientos[0]['FechaMovimiento']))->format('Y-m-d'),
            'valor' => $movimientos[0]['Saldo'],
        ];
        $proyecto = $this->proyectoRepository->editTerreno($proyecto, $data);
        return $proyecto->terreno;
    }

    /**
     * @throws Exception
     */
    protected function getValorReajustado(Model\Proyecto $proyecto): ?Model\Proyecto\Terreno
    {
        $novPrevTerreno = new DateTimeImmutable($proyecto->terreno->fecha->format('m') < 12 ? $proyecto->terreno->fecha->sub(new DateInterval('P1Y'))->format('Y-11-1') : $proyecto->terreno->fecha->format('Y-11-1'));
        $lastDecember = new DateTimeImmutable((new DateTimeImmutable())->sub(new DateInterval('P1Y'))->format('Y-12-31'));
        $novLast = new DateTimeImmutable($lastDecember->format('Y-11-1'));
        $ipc = $this->ipcService->get($novPrevTerreno, $novLast);
        $terreno = $proyecto->terreno;
        $terreno->fecha = $novLast;
        $terreno->valor *= (1 + $ipc);
        return $terreno;
    }
}
