<?php

declare(strict_types=1);

namespace App\Scenario;

use App\Util\ParsedCommand;
use Pkirillw\MaxBotApi\Builder\Message as MessageBuilder;
use Pkirillw\MaxBotApi\Scheme\Enum\Format;
use Pkirillw\MaxBotApi\Scheme\Update\MessageCreatedUpdate;

final class MessagesScenario extends AbstractScenario
{
    public function handle(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        switch ($command->name) {
            case 'send_text':
                $this->sendText($update, $command);
                return;
            case 'send_markdown':
                $this->sendFormatted($update, $command, Format::Markdown);
                return;
            case 'send_html':
                $this->sendFormatted($update, $command, Format::Html);
                return;
            case 'reply':
                $this->replyToMessage($update, $command);
                return;
            case 'forward':
                $this->forward($update, $command);
                return;
            case 'edit':
                $this->edit($update, $command);
                return;
            case 'delete':
                $this->delete($update, $command);
                return;
            case 'messages':
                $this->listMessages($update, $command);
                return;
            case 'message':
                $this->getMessage($update, $command);
                return;
            case 'markup':
                $this->markup($update, $command);
                return;
            case 'notify':
                $this->silentMessage($update, $command);
                return;
            case 'disable_preview':
                $this->disablePreview($update, $command);
                return;
        }
    }

    private function sendText(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $text = $command->tail !== '' ? $command->tail : 'Просто текст.';
        $this->api->messages->send(MessageBuilder::new()->setChat($update->getChatId())->setText($text));
    }

    private function sendFormatted(MessageCreatedUpdate $update, ParsedCommand $command, Format $format): void
    {
        $text = $command->tail !== '' ? $command->tail : '_empty_';
        $this->api->messages->send(
            MessageBuilder::new()->setChat($update->getChatId())->setText($text)->setFormat($format),
        );
    }

    private function replyToMessage(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $messageId = $command->arg(0);
        $text = $command->tail;
        if ($messageId === null || str_starts_with($text, $messageId)) {
            // tail still includes messageId — strip it.
            $text = trim(implode(' ', array_slice($command->args, 1)));
        }
        if ($messageId === null || $text === '') {
            $this->replyMarkdown($update, 'Usage: `/reply <messageId> <text>`');
            return;
        }
        $this->api->messages->send(
            MessageBuilder::new()
                ->setChat($update->getChatId())
                ->setReply($text, $messageId),
        );
    }

    private function forward(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $messageId = $command->arg(0);
        if ($messageId === null) {
            $this->replyMarkdown($update, 'Usage: `/forward <messageId>`');
            return;
        }
        $this->api->messages->send(
            MessageBuilder::new()
                ->setChat($update->getChatId())
                ->setForward($messageId),
        );
    }

    private function edit(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $messageId = $command->arg(0);
        $text = trim(implode(' ', array_slice($command->args, 1)));
        if ($messageId === null || $text === '') {
            $this->replyMarkdown($update, 'Usage: `/edit <messageId> <new text>`');
            return;
        }
        $this->api->messages->editMessage(
            $messageId,
            MessageBuilder::new()->setChat($update->getChatId())->setText($text),
        );
        $this->replyMarkdown($update, "Edited `$messageId`");
    }

    private function delete(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $messageId = $command->arg(0);
        if ($messageId === null) {
            $this->replyMarkdown($update, 'Usage: `/delete <messageId>`');
            return;
        }
        $result = $this->api->messages->deleteMessage($messageId);
        $this->replyMarkdown($update, sprintf('deleteMessage(%s): success=%s', $messageId, $result->success ? 'true' : 'false'));
    }

    private function listMessages(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $chatId = $command->argInt(0);
        $count = $command->argInt(1, 5);
        if ($chatId <= 0) {
            $this->replyMarkdown($update, 'Usage: `/messages <chatId> [count]`');
            return;
        }
        $list = $this->api->messages->getMessages($chatId, count: $count);
        $lines = [];
        foreach ($list->messages as $m) {
            $lines[] = sprintf('• `%s` %s', $m->body?->mid ?? '?', mb_substr($m->body?->text ?? '', 0, 80));
        }
        $this->replyMarkdown($update, "*Messages in $chatId*\n" . ($lines === [] ? '(empty)' : implode("\n", $lines)));
    }

    private function getMessage(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $messageId = $command->arg(0);
        if ($messageId === null) {
            $this->replyMarkdown($update, 'Usage: `/message <messageId>`');
            return;
        }
        $msg = $this->api->messages->getMessage($messageId);
        $sender = $msg->sender?->name ?? '—';
        $text = $msg->body?->text ?? '(no text)';
        $this->replyMarkdown($update, sprintf("*Message `%s`*\nsender: %s\ntext: %s", $messageId, $sender, $text));
    }

    private function markup(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $userId = $command->argInt(0, $update->getUserId());
        $text = sprintf('Hey user #%d — you are mentioned!', $userId);
        // Mention the user by adding a markup over the entire text.
        $this->api->messages->send(
            MessageBuilder::new()
                ->setChat($update->getChatId())
                ->setText($text)
                ->addMarkUp($userId, 0, mb_strlen($text)),
        );
    }

    private function silentMessage(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $text = $command->tail !== '' ? $command->tail : 'Тихое сообщение (без уведомления).';
        $this->api->messages->send(
            MessageBuilder::new()
                ->setChat($update->getChatId())
                ->setText($text)
                ->setNotify(false),
        );
    }

    private function disablePreview(MessageCreatedUpdate $update, ParsedCommand $command): void
    {
        $url = $command->arg(0, 'https://dev.max.ru');
        $this->api->messages->send(
            MessageBuilder::new()
                ->setChat($update->getChatId())
                ->setText('Ссылка без превью: ' . $url)
                ->setDisableLinkPreview(true),
        );
    }
}
