using System.Text;
using Dapper;
using GmRelay.Shared.Domain;
using Npgsql;
using Telegram.Bot;
using Telegram.Bot.Types;

namespace GmRelay.Bot.Features.Sessions.ExportCalendar;

internal sealed record CalendarSessionDto(Guid Id, string Title, DateTime ScheduledAt);

public sealed class ExportCalendarHandler(
    NpgsqlDataSource dataSource,
    ITelegramBotClient botClient)
{
    public async Task HandleAsync(Message message, CancellationToken cancellationToken)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        var sessions = await connection.QueryAsync<CalendarSessionDto>(
            @"SELECT s.id as Id, s.title as Title, s.scheduled_at as ScheduledAt
              FROM sessions s
              JOIN game_groups g ON s.group_id = g.id
              WHERE g.telegram_chat_id = @ChatId 
                AND s.status = @Planned
                AND s.scheduled_at > NOW()
              ORDER BY s.scheduled_at ASC",
            new { ChatId = message.Chat.Id, Planned = SessionStatus.Planned });

        var sessionsList = sessions.ToList();

        if (sessionsList.Count == 0)
        {
            await botClient.SendMessage(
                chatId: message.Chat.Id,
                text: "📭 У этой группы нет запланированных сессий для экспорта.",
                cancellationToken: cancellationToken);
            return;
        }

        var sb = new StringBuilder();
        sb.AppendLine("BEGIN:VCALENDAR");
        sb.AppendLine("VERSION:2.0");
        sb.AppendLine("PRODID:-//GM-Relay//TTRPG Schedule//EN");

        foreach (var s in sessionsList)
        {
            var dtStart = s.ScheduledAt.ToString("yyyyMMddTHHmmssZ");
            var dtEnd = s.ScheduledAt.AddHours(4).ToString("yyyyMMddTHHmmssZ");

            sb.AppendLine("BEGIN:VEVENT");
            sb.AppendLine($"UID:{s.Id}@gmrelay");
            sb.AppendLine($"DTSTAMP:{DateTime.UtcNow:yyyyMMddTHHmmssZ}");
            sb.AppendLine($"DTSTART:{dtStart}");
            sb.AppendLine($"DTEND:{dtEnd}");
            sb.AppendLine($"SUMMARY:{s.Title}");
            // Escape special chars according to iCal standards (RFC 5545) -- simple escaping for summary
            // In a fuller implementation we'd escape \r\n, commas, etc. But titles are mostly plain text.
            sb.AppendLine("END:VEVENT");
        }

        sb.AppendLine("END:VCALENDAR");

        var bytes = Encoding.UTF8.GetBytes(sb.ToString());
        using var stream = new MemoryStream(bytes);

        var inputFile = InputFile.FromStream(stream, "schedule.ics");

        await botClient.SendDocument(
             chatId: message.Chat.Id,
             document: inputFile,
             caption: "📅 <b>Ваш календарь игр!</b>\nОткройте файл на устройстве, чтобы добавить события в свой календарь.",
             parseMode: Telegram.Bot.Types.Enums.ParseMode.Html,
             messageThreadId: message.MessageThreadId,
             cancellationToken: cancellationToken);
    }
}
