<?php

namespace FSPoster\App\TelegramNotification\App\Services;

use Exception;
use FSPoster\App\Pages\Settings\Workflow\Services\WorkflowActionService;
use FSPoster\App\Pages\Settings\Workflow\Services\WorkflowService;
use FSPoster\App\Providers\Common\WorkflowEventsManager;
use FSPoster\App\Providers\Core\Container;
use FSPoster\App\SocialNetworks\Telegram\Api\Api;
use FSPoster\App\SocialNetworks\Telegram\Api\AuthData;
use FSPoster\App\SocialNetworks\Telegram\Api\PostingData;
use FSPoster\App\TelegramNotification\App\DTOs\Request\TelegramNotificationRequest;
use FSPoster\App\TelegramNotification\App\DTOs\Response\TelegramNotificationResponse;
use FSPoster\App\TelegramNotification\App\Mappers\TelegramNotificationMapper;
use FSPoster\App\TelegramNotification\App\Repositories\TelegramNotificationRepository;
use RuntimeException;

class TelegramNotificationService
{
    private TelegramNotificationRepository $repository;
    private TelegramNotificationMapper $mapper;

    public function __construct(TelegramNotificationRepository $repository, TelegramNotificationMapper $mapper)
    {
        $this->repository = $repository;
        $this->mapper = $mapper;
    }

    public function getViewData(int $id): TelegramNotificationResponse
    {
        $actionService = Container::get(WorkflowActionService::class);
        $workflowActionInfo = $actionService->get($id);

        if (! $workflowActionInfo) {
            throw new RuntimeException(fsp__('Workflow action not found.'));
        }

        $data = json_decode($workflowActionInfo->data, true) ?: [];

        $workflowService = Container::get(WorkflowService::class);
        $workflow = $workflowService->get($workflowActionInfo->workflow_id);

        if ($workflow === null) {
            throw new RuntimeException(fsp__('Workflow not found.'));
        }

        $workflowEventsManager = Container::get(WorkflowEventsManager::class);
        $availableParams = $workflowEventsManager->get($workflow->when)->getAvailableParams();
        $shortCodes = $workflowEventsManager->getShortcodeService()->getShortCodesList($availableParams);

        $channels = $this->repository->getActiveChannels();
        $availableChannels = array_map([$this->mapper, 'toAvailableChannel'], $channels);

        return $this->mapper->toResponse($data, $shortCodes, $availableChannels, (bool) $workflowActionInfo->is_active);
    }

    public function updateAction(int $id, TelegramNotificationRequest $request, int $isActive): void
    {
        $actionService = Container::get(WorkflowActionService::class);

        if (! $actionService->get($id)) {
            throw new RuntimeException(fsp__('Workflow action not found.'));
        }

        $newData = [
            'channels' => array_map('intval', $request->getChannels()),
            'message'  => $request->getMessage(),
        ];

        $actionService->update($id, [
            'data'      => json_encode($newData),
            'is_active' => $isActive,
        ]);
    }

    public function sendNotification(array $channelIds, string $message): void
    {
        $channelIds = array_values(array_unique(array_map('intval', $channelIds)));
        $channelsMap = $this->repository->getChannelsByIds($channelIds);

        $sessionIds = [];
        foreach ($channelsMap as $channelRow) {
            $sessionIds[] = (int) $channelRow->channel_session_id;
        }
        $sessionsMap = $this->repository->getSessionsByIds(array_values(array_unique($sessionIds)));

        foreach ($channelIds as $channelId) {
            $channel = $channelsMap[$channelId] ?? null;

            if ($channel === null) {
                continue;
            }

            $session = $sessionsMap[(int) $channel->channel_session_id] ?? null;

            if ($session === null) {
                continue;
            }

            $botToken = $session->data_obj['bot_token'] ?? '';

            if (empty($botToken)) {
                continue;
            }

            $authData = new AuthData();
            $authData->token = $botToken;
            $authData->chatId = $channel->remote_id;

            $postingData = new PostingData();
            $postingData->message = $message;
            $postingData->uploadMedia = [];
            $postingData->addReadMoreBtn = false;
            $postingData->readMoreBtnUrl = '';
            $postingData->readMoreBtnText = '';
            $postingData->silent = false;

            $api = Container::get(Api::class);
            $api->setAuthData($authData);

            if (! empty($session->proxy)) {
                $api->setProxy($session->proxy);
            }

            $api->sendPost($postingData);
        }
    }
}
