using System.Text;
using Dapper;
using GmRelay.Shared.Domain;
using Microsoft.Extensions.Configuration;
using Npgsql;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Types.ReplyMarkups;

namespace GmRelay.Bot.Features.Sessions.ExportCalendar;

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

public sealed class ExportCalendarHandler(
    NpgsqlDataSource dataSource,
    ITelegramBotClient botClient,
    IConfiguration configuration)
{
    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}");
            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");

        // Create calendar subscription
        string? subscriptionUrl = null;
        var baseUrl = configuration["Web:BaseUrl"];
        var senderId = message.From?.Id;
        if (!string.IsNullOrWhiteSpace(baseUrl) && senderId.HasValue)
        {
            try
            {
                var token = Guid.NewGuid().ToString("N");
                var groupId = await connection.QueryFirstOrDefaultAsync<Guid?>(
                    @"SELECT id FROM game_groups WHERE telegram_chat_id = @ChatId",
                    new { ChatId = message.Chat.Id });

                await connection.ExecuteAsync(
                    @"INSERT INTO calendar_subscriptions (id, token, user_telegram_id, group_id, filter_type, created_at, expires_at)
                      VALUES (gen_random_uuid(), @token, @userTelegramId, @groupId, @filterType, now(), NULL)",
                    new { token, userTelegramId = senderId.Value, groupId, filterType = (int)CalendarSubscriptionFilter.SpecificGroup });

                subscriptionUrl = $"{baseUrl.TrimEnd('/')}/calendar/{token}.ics";
            }
            catch
            {
                // Non-critical: if subscription creation fails, still send the file
            }
        }

        var replyMarkup = subscriptionUrl is not null
            ? new InlineKeyboardMarkup(new[]
            {
                new[] { InlineKeyboardButton.WithUrl("🔗 Подписаться на календарь", subscriptionUrl) }
            })
            : null;

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