<?php
namespace Incoviba\Controller\API;

use DateInterval;
use DateTimeImmutable;
use DateTimeInterface;
use Incoviba\Common\Implement\Exception\EmptyRedis;
use Incoviba\Controller\withRedis;
use Incoviba\Service;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class Money
{
    use withJson, withRedis;

    private int $time = 60 * 60 * 24 * 30;

    public function get(ServerRequestInterface $request, ResponseInterface $response, Service\Redis $redisService,
                        Service\Money $moneyService): ResponseInterface
    {
        $data = $request->getParsedBody();
        $output = [
            'input' => $data
        ];
        $output[$data['provider']] = 0;
        $redisKey = $data['provider'];
        $date = new DateTimeImmutable($data['fecha']);
        if (isset($data['start'])) {
            $start = new DateTimeImmutable($data['start']);
        }
        $value = $this->getValue($redisService, $redisKey, $moneyService, $date, $data['provider']);
        if (isset($start)) {
            $months = $date->diff($start)->m;
            $current = clone $start;
            $value = $this->getValue($redisService, $redisKey, $moneyService, $current, $data['provider']);
            for ($i = 1; $i <= $months; $i ++) {
                $current = $current->add(new DateInterval("P{$i}M"));
                $value += $this->getValue($redisService, $redisKey, $moneyService, $current, $data['provider']);
            }
        }
        $output[$data['provider']] = $value;
        return $this->withJson($response, $output);
    }

    protected array $data;
    protected function getValue(Service\Redis $redisService, string $redisKey, Service\Money $moneyService,
                                DateTimeInterface $date, string $provider): float
    {
        if (isset($this->data[$provider][$date->format('Y-m-d')])) {
            return $this->data[$provider][$date->format('Y-m-d')];
        }
        try {
            $this->data[$provider] = (array) $this->fetchRedis($redisService, $redisKey);
            if (!isset($this->data[$provider][$date->format('Y-m-d')])) {
                throw new EmptyRedis($redisKey);
            }
        } catch (EmptyRedis) {
            $result = $moneyService->get($provider, $date);
            $this->data[$provider][$date->format('Y-m-d')] = $result;
            $this->saveRedis($redisService, $redisKey, $this->data[$provider], $this->time);
        }
        return $this->data[$provider][$date->format('Y-m-d')];
    }
    public function uf(ServerRequestInterface $request, ResponseInterface $response, Service\UF $ufService): ResponseInterface
    {
        $body = $request->getParsedBody();
        $output = [
            'input' => $body,
            'uf' => 0
        ];
        $date = new DateTimeImmutable($body['fecha']);
        $now = new DateTimeImmutable();
        if ($date > $now) {
            return $this->withJson($response, $output);
        }
        $output['uf'] = $ufService->get($date);
        return $this->withJson($response, $output);
    }
    public function ipc(ServerRequestInterface $request, ResponseInterface $response,
                        Service\IPC $ipcService): ResponseInterface
    {
        $data = $request->getParsedBody();
        $output = [
            'input' => $data,
            'date_string' => '',
            'ipc' => 0
        ];
        $start = new DateTimeImmutable($data['start']);
        $end = new DateTimeImmutable($data['end']);
        $now = new DateTimeImmutable();
        if ($end > $now) {
            return $this->withJson($response, $output);
        }
        $dateKey = "{$start->format('Y-m')}|{$end->format('Y-m')}";
        $output['date_string'] = $dateKey;
        $output['ipc'] = $ipcService->get($start, $end);
        return  $this->withJson($response, $output);
    }
}
