<?php

declare(strict_types=1);

namespace App\Handler;

use App\Keyboard\KeyboardFactory;
use Pkirillw\MaxBotApi\Api;
use Pkirillw\MaxBotApi\Builder\Message as MessageBuilder;
use Pkirillw\MaxBotApi\Exception\ApiException;
use Pkirillw\MaxBotApi\Exception\MaxBotApiException;
use Pkirillw\MaxBotApi\Exception\NetworkException;
use Pkirillw\MaxBotApi\Exception\TimeoutException;
use Pkirillw\MaxBotApi\Scheme\Enum\Format;
use Pkirillw\MaxBotApi\Scheme\Update\UpdateInterface;
use Psr\Log\LoggerInterface;

abstract class AbstractUpdateHandler implements UpdateHandlerInterface
{
    public function __construct(
        protected Api $api,
        protected LoggerInterface $logger,
        protected KeyboardFactory $keyboards,
    ) {}

    public function safeHandle(UpdateInterface $update): void
    {
        $this->logger->info('update: ' . $update::class, [
            'type' => $update->getUpdateType()->value,
            'chat_id' => $update->getChatId(),
            'user_id' => $update->getUserId(),
        ]);

        try {
            $this->handle($update);
        } catch (ApiException $e) {
            $this->logger->error('API error: ' . $e->getMessage(), [
                'api_code' => $e->apiCode,
                'http_code' => $e->httpCode,
            ]);
            $this->notifyAdmin($update, sprintf('API error `%s`: %s', $e->apiCode, $e->getMessage()));
        } catch (NetworkException $e) {
            $this->logger->warning('network: ' . $e->getMessage());
        } catch (TimeoutException $e) {
            $this->logger->warning('timeout: ' . $e->getMessage());
        } catch (MaxBotApiException $e) {
            $this->logger->error('lib error: ' . $e->getMessage());
            $this->api->debugs->sendErr($e);
            $this->notifyAdmin($update, 'Library error: ' . $e->getMessage());
        }
    }

    protected function notifyAdmin(UpdateInterface $update, string $text): void
    {
        $chatId = $update->getChatId();
        if ($chatId <= 0) {
            return;
        }
        try {
            $this->api->messages->send(
                MessageBuilder::new()
                    ->setChat($chatId)
                    ->setText('⚠ ' . $text)
                    ->setFormat(Format::Markdown),
            );
        } catch (\Throwable $e) {
            $this->logger->error('notifyAdmin failed: ' . $e->getMessage());
        }
    }
}
