using System.Net.Http.Json;
using System.Text.Json.Serialization;
using Backend.Data;
using Microsoft.EntityFrameworkCore;

namespace Backend.Services;

public sealed class TwitchTrackerViewerStatsProvider(
    IHttpClientFactory httpClientFactory,
    AwardsDbContext db,
    ILogger<TwitchTrackerViewerStatsProvider> logger)
    : IViewerStatsProvider
{
    public async Task<ViewerStatsSnapshot?> GetChannelSummaryAsync(string twitchLogin, CancellationToken cancellationToken)
    {
        var login = twitchLogin.Trim().TrimStart('@').ToLowerInvariant();
        if (string.IsNullOrWhiteSpace(login))
        {
            return null;
        }

        try
        {
            using var timeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            timeout.CancelAfter(TimeSpan.FromSeconds(3));

            var settings = await db.SiteSettings
                .AsNoTracking()
                .FirstOrDefaultAsync(item => item.Id == 1, timeout.Token);

            var baseUrl = TrackingRulesSettings.NormalizeBaseUrl(settings?.ViewerStatsProviderBaseUrl);
            var client = httpClientFactory.CreateClient("TwitchTracker");
            var response = await client.GetFromJsonAsync<TwitchTrackerChannelSummaryResponse>(
                $"{baseUrl}/channels/summary/{Uri.EscapeDataString(login)}",
                timeout.Token);

            if (response is null)
            {
                return null;
            }

            return new ViewerStatsSnapshot(
                response.AverageViewers,
                Math.Max(0, response.MinutesStreamed / 60),
                response.HoursWatched,
                response.PeakViewers,
                response.FollowersGained,
                TrackingRulesSettings.Window30d);
        }
        catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
        {
            logger.LogInformation("TwitchTracker API lookup timed out for {TwitchLogin}.", login);
            return null;
        }
        catch (Exception ex)
        {
            logger.LogInformation(ex, "TwitchTracker API lookup failed for {TwitchLogin}.", login);
            return null;
        }
    }

    private sealed class TwitchTrackerChannelSummaryResponse
    {
        [JsonPropertyName("rank")]
        public int Rank { get; init; }

        [JsonPropertyName("minutes_streamed")]
        public int MinutesStreamed { get; init; }

        [JsonPropertyName("avg_viewers")]
        public int AverageViewers { get; init; }

        [JsonPropertyName("max_viewers")]
        public int PeakViewers { get; init; }

        [JsonPropertyName("hours_watched")]
        public int HoursWatched { get; init; }

        [JsonPropertyName("followers")]
        public int FollowersGained { get; init; }

        [JsonPropertyName("followers_total")]
        public int FollowersTotal { get; init; }
    }
}
