<?php

declare(strict_types=1);

namespace Bastion\Services;

use App\Services\SettingsService;
use Bastion\Exceptions\BotTokenConfiguratorException;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Log\LoggerInterface;
use Openguru\OpenCartFramework\Router\Router;
use Openguru\OpenCartFramework\Support\Arr;
use Openguru\OpenCartFramework\Telegram\Exceptions\TelegramClientException;
use Openguru\OpenCartFramework\Telegram\TelegramService;

class BotTokenConfigurator
{
    private TelegramService $telegramService;
    private SettingsService $settings;
    private Router $router;
    private LoggerInterface $logger;

    public function __construct(
        TelegramService $telegramService,
        SettingsService $settings,
        Router $router,
        LoggerInterface $logger
    ) {
        $this->telegramService = $telegramService;
        $this->settings = $settings;
        $this->router = $router;
        $this->logger = $logger;
    }

    /**
     * @throws BotTokenConfiguratorException
     */
    public function configure(string $botToken): array
    {
        $this->telegramService->setBotToken($botToken);

        try {
            $me = $this->telegramService->exec('getMe');
            $webhookUrl = $this->telegramService->getWebhookUrl();

            if (! $webhookUrl) {
                $this->telegramService->exec('setWebhook', [
                    'url' => $this->getWebhookUrl(),
                ]);
                $webhookUrl = $this->telegramService->getWebhookUrl();
            }

            return [
                'first_name' => Arr::get($me, 'result.first_name'),
                'username' => Arr::get($me, 'result.username'),
                'id' => Arr::get($me, 'result.id'),
                'webhook_url' => $webhookUrl,
            ];
        } catch (TelegramClientException $exception) {
            $this->logger->error($exception->getMessage(), ['exception' => $exception]);
            if ($exception->getCode() === 404 || $exception->getCode() === 401) {
                throw new BotTokenConfiguratorException(
                    'Telegram сообщает, что BotToken не верный. Проверьте корректность.'
                );
            }

            throw new BotTokenConfiguratorException($exception->getMessage());
        } catch (Exception | GuzzleException $exception) {
            $this->logger->error($exception->getMessage(), ['exception' => $exception]);
            throw new BotTokenConfiguratorException($exception->getMessage());
        }
    }

    /**
     * @throws BotTokenConfiguratorException
     */
    private function getWebhookUrl(): string
    {
        $publicUrl = rtrim($this->settings->config()->getApp()->getShopBaseUrl(), '/');

        if (! $publicUrl) {
            throw new BotTokenConfiguratorException('Public URL is not set in configuration.');
        }

        $webhook = $this->router->url('webhook');

        return $publicUrl . $webhook;
    }
}
