using System.Net.Http;
using System.Text.Json;
using ytLive.Models;

namespace ytLive.Services;

/// <summary>
/// Polls YouTube Live Chat API for messages.
/// YouTube doesn't have WebSocket for chat — polling is the only option.
/// </summary>
public class YouTubeChatService : IDisposable
{
    private readonly YouTubeAuthService _auth;
    private readonly HttpClient _http = new();
    private Timer? _pollTimer;
    private string? _nextPageToken;
    private string? _liveChatId;
    private bool _isRunning;

    public event Action<ChatMessage>? MessageReceived;

    private static readonly JsonSerializerOptions JsonOpts = new()
    {
        PropertyNameCaseInsensitive = true
    };

    public YouTubeChatService(YouTubeAuthService auth)
    {
        _auth = auth;
    }

    public void Start(string liveChatId, int pollIntervalMs = 2000)
    {
        _liveChatId = liveChatId;
        _isRunning = true;
        _nextPageToken = null;
        _pollTimer = new(async _ => await Poll(), null, 0, pollIntervalMs);
    }

    public void Stop()
    {
        _isRunning = false;
        _pollTimer?.Dispose();
        _pollTimer = null;
    }

    private async Task Poll()
    {
        if (!_isRunning || _liveChatId == null || _auth.CurrentChannel == null) return;

        try
        {
            if (_auth.CurrentChannel.TokenExpiry <= DateTime.UtcNow.AddMinutes(5))
                await _auth.RefreshToken();

            var url = $"https://www.googleapis.com/youtube/v3/liveChat/messages?liveChatId={_liveChatId}&part=snippet,authorDetails&maxResults=50";
            if (_nextPageToken != null)
                url += $"&pageToken={_nextPageToken}";

            _http.DefaultRequestHeaders.Authorization = new("Bearer", _auth.CurrentChannel.AccessToken);
            var response = await _http.GetAsync(url);
            if (!response.IsSuccessStatusCode) return;

            var json = await response.Content.ReadAsStringAsync();
            var data = JsonSerializer.Deserialize<JsonElement>(json);

            if (data.TryGetProperty("nextPageToken", out var token))
                _nextPageToken = token.GetString();

            if (!data.TryGetProperty("items", out var items)) return;

            foreach (var item in items.EnumerateArray())
            {
                var snippet = item.GetProperty("snippet");
                var author = item.GetProperty("authorDetails");

                var message = new ChatMessage
                {
                    Id = item.GetProperty("id").GetString()!,
                    AuthorName = author.GetProperty("displayName").GetString()!,
                    AuthorChannelId = author.GetProperty("channelId").GetString()!,
                    AuthorImageUrl = author.GetProperty("profileImageUrl").GetString()!,
                    Message = snippet.GetProperty("textMessageDetails").GetProperty("messageText").GetString()!,
                    Timestamp = DateTime.Parse(snippet.GetProperty("publishedAt").GetString()!),
                    IsMember = author.GetProperty("isChatSponsor").GetBoolean()
                };

                MessageReceived?.Invoke(message);
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine($"Chat poll error: {ex.Message}");
        }
    }

    public void Dispose()
    {
        Stop();
        _http.Dispose();
    }
}
