<?php

declare(strict_types=1);

namespace App\Framework\Notification\Channels\Telegram;

use App\Framework\Http\Method;
use App\Framework\HttpClient\ClientRequest;
use App\Framework\HttpClient\HttpClient;
use App\Framework\Notification\Channels\Telegram\ValueObjects\TelegramChatId;

/**
 * Telegram Chat ID Discovery
 *
 * Helps discover chat IDs by fetching recent updates from Telegram Bot API
 */
final readonly class ChatIdDiscovery
{
    public function __construct(
        private HttpClient $httpClient,
        private TelegramConfig $config
    ) {
    }

    /**
     * Get all recent chat IDs that have interacted with the bot
     *
     * @return array<TelegramChatId> Array of discovered chat IDs
     */
    public function discoverChatIds(): array
    {
        $updates = $this->getUpdates();

        $chatIds = [];
        foreach ($updates as $update) {
            if (isset($update['message']['chat']['id'])) {
                $chatId = TelegramChatId::fromInt($update['message']['chat']['id']);
                $chatIds[$chatId->toString()] = $chatId; // Use as key to avoid duplicates
            }
        }

        return array_values($chatIds);
    }

    /**
     * Get detailed information about recent chats
     *
     * @return array Array of chat information with chat_id, name, type, etc.
     */
    public function discoverChatsWithInfo(): array
    {
        $updates = $this->getUpdates();

        $chats = [];
        foreach ($updates as $update) {
            if (isset($update['message']['chat'])) {
                $chat = $update['message']['chat'];
                $chatId = (string) $chat['id'];

                if (!isset($chats[$chatId])) {
                    $chats[$chatId] = [
                        'chat_id' => TelegramChatId::fromInt($chat['id']),
                        'type' => $chat['type'] ?? 'unknown',
                        'title' => $chat['title'] ?? null,
                        'username' => $chat['username'] ?? null,
                        'first_name' => $chat['first_name'] ?? null,
                        'last_name' => $chat['last_name'] ?? null,
                        'last_message_text' => $update['message']['text'] ?? null,
                        'last_message_date' => $update['message']['date'] ?? null,
                    ];
                }
            }
        }

        return array_values($chats);
    }

    /**
     * Get the most recent chat ID (usually yours if you just messaged the bot)
     *
     * @return TelegramChatId|null Most recent chat ID or null if no updates
     */
    public function getMostRecentChatId(): ?TelegramChatId
    {
        $updates = $this->getUpdates();

        if (empty($updates)) {
            return null;
        }

        // Updates are ordered by update_id (oldest first), so we get the last one
        $latestUpdate = end($updates);

        if (isset($latestUpdate['message']['chat']['id'])) {
            return TelegramChatId::fromInt($latestUpdate['message']['chat']['id']);
        }

        return null;
    }

    /**
     * Fetch recent updates from Telegram API
     *
     * @return array Array of update objects
     */
    private function getUpdates(): array
    {
        $request = ClientRequest::json(
            method: Method::POST,
            url: $this->config->getGetUpdatesEndpoint(),
            data: []
        );

        $response = $this->httpClient->send($request);

        if (!$response->isSuccessful()) {
            throw new TelegramApiException(
                "Failed to get updates: HTTP {$response->status->value}",
                $response->status->value
            );
        }

        $data = $response->json();

        if (!isset($data['ok']) || $data['ok'] !== true) {
            $errorMessage = $data['description'] ?? 'Unknown error';
            throw new TelegramApiException(
                "Telegram API error: {$errorMessage}",
                $data['error_code'] ?? 0
            );
        }

        return $data['result'] ?? [];
    }

    /**
     * Print discovered chats in a human-readable format
     */
    public function printDiscoveredChats(): void
    {
        $chats = $this->discoverChatsWithInfo();

        if (empty($chats)) {
            echo "ℹ️  No chats found. Please send a message to your bot first.\n";
            return;
        }

        echo "📋 Discovered Chats:\n";
        echo str_repeat('=', 60) . "\n\n";

        foreach ($chats as $index => $chat) {
            echo sprintf("#%d\n", $index + 1);
            echo sprintf("  💬 Chat ID: %s\n", $chat['chat_id']->toString());
            echo sprintf("  📱 Type: %s\n", $chat['type']);

            if ($chat['username']) {
                echo sprintf("  👤 Username: @%s\n", $chat['username']);
            }

            if ($chat['first_name']) {
                $fullName = $chat['first_name'];
                if ($chat['last_name']) {
                    $fullName .= ' ' . $chat['last_name'];
                }
                echo sprintf("  📛 Name: %s\n", $fullName);
            }

            if ($chat['title']) {
                echo sprintf("  🏷️  Title: %s\n", $chat['title']);
            }

            if ($chat['last_message_text']) {
                $messagePreview = strlen($chat['last_message_text']) > 50
                    ? substr($chat['last_message_text'], 0, 50) . '...'
                    : $chat['last_message_text'];
                echo sprintf("  💬 Last Message: %s\n", $messagePreview);
            }

            if ($chat['last_message_date']) {
                echo sprintf("  📅 Last Message Date: %s\n", date('Y-m-d H:i:s', $chat['last_message_date']));
            }

            echo "\n";
        }
    }
}
