<?php
declare(strict_types=1);

namespace App\Modules\Settings;

use DateInterval;
use DateTimeImmutable;
use App\Core\Exceptions\AllegroOAuthException;
use Throwable;

final class AllegroTokenManager
{
    public function __construct(
        private readonly AllegroIntegrationRepository $repository,
        private readonly AllegroOAuthClient $oauthClient
    ) {
    }

    /**
     * @return array{0: string, 1: string}
     */
    public function resolveToken(): array
    {
        $oauth = $this->repository->getTokenCredentials();
        if ($oauth === null) {
            throw new AllegroOAuthException('Brak polaczenia OAuth Allegro. Polacz konto w Ustawieniach.');
        }

        $env = (string) ($oauth['environment'] ?? 'sandbox');
        $accessToken = trim((string) ($oauth['access_token'] ?? ''));
        $tokenExpiresAt = trim((string) ($oauth['token_expires_at'] ?? ''));

        if ($accessToken === '') {
            return $this->forceRefresh();
        }

        if ($tokenExpiresAt !== '') {
            try {
                $expiresAt = new DateTimeImmutable($tokenExpiresAt);
                if ($expiresAt <= (new DateTimeImmutable('now'))->add(new DateInterval('PT5M'))) {
                    return $this->forceRefresh();
                }
            } catch (Throwable) {
                return $this->forceRefresh();
            }
        }

        return [$accessToken, $env];
    }

    /**
     * @return array{0: string, 1: string}
     */
    private function forceRefresh(): array
    {
        $oauth = $this->repository->getTokenCredentials();
        if ($oauth === null) {
            throw new AllegroOAuthException('Brak danych OAuth Allegro.');
        }

        $token = $this->oauthClient->refreshAccessToken(
            (string) ($oauth['environment'] ?? 'sandbox'),
            (string) ($oauth['client_id'] ?? ''),
            (string) ($oauth['client_secret'] ?? ''),
            (string) ($oauth['refresh_token'] ?? '')
        );

        $expiresAt = null;
        $expiresIn = max(0, (int) ($token['expires_in'] ?? 0));
        if ($expiresIn > 0) {
            $expiresAt = (new DateTimeImmutable('now'))
                ->add(new DateInterval('PT' . $expiresIn . 'S'))
                ->format('Y-m-d H:i:s');
        }

        $refreshToken = trim((string) ($token['refresh_token'] ?? ''));
        if ($refreshToken === '') {
            $refreshToken = (string) ($oauth['refresh_token'] ?? '');
        }

        $this->repository->saveTokens(
            (string) ($token['access_token'] ?? ''),
            $refreshToken,
            (string) ($token['token_type'] ?? ''),
            (string) ($token['scope'] ?? ''),
            $expiresAt
        );

        $updated = $this->repository->getTokenCredentials();
        $newToken = trim((string) ($updated['access_token'] ?? ''));
        if ($newToken === '') {
            throw new AllegroOAuthException('Nie udalo sie odswiezyc tokenu Allegro.');
        }

        return [$newToken, (string) ($updated['environment'] ?? 'sandbox')];
    }
}
