using Microsoft.EntityFrameworkCore;
using Ikar.Server.Data;
using Ikar.Server.Data.Entities;
using Ikar.Shared;

namespace Ikar.Server.Infrastructure.Updates;

public sealed class AndroidUpdateCompatibilityTrackingService(IkarDbContext dbContext)
{
    private const int MaxUserAgentLength = 512;

    public async Task TrackHitAsync(
        HttpRequest request,
        string route,
        string? requestedFileName,
        CancellationToken cancellationToken)
    {
        var hit = new AndroidUpdateCompatibilityHit
        {
            HitAt = DateTimeOffset.UtcNow,
            Route = TrimToLength(route, 64) ?? "unknown",
            RequestPath = TrimToLength(request.Path.Value, 256) ?? string.Empty,
            RequestedFileName = TrimToLength(requestedFileName, 260),
            ClientPlatform = TrimToLength(ReadClientPlatform(request), 32),
            ClientVersionCode = ReadClientVersionCode(request),
            ClientVersionName = TrimToLength(ReadClientVersionName(request), 64),
            UserAgent = TrimToLength(request.Headers.UserAgent.ToString(), MaxUserAgentLength),
            RemoteIp = TrimToLength(request.HttpContext.Connection.RemoteIpAddress?.ToString(), 64)
        };

        dbContext.AndroidUpdateCompatibilityHits.Add(hit);
        await dbContext.SaveChangesAsync(cancellationToken);
    }

    private static string? ReadClientPlatform(HttpRequest request)
    {
        var platform = request.Headers[ClientVersionMetadata.PlatformHeaderName].ToString();
        if (!string.IsNullOrWhiteSpace(platform))
        {
            return platform;
        }

        platform = request.Query[ClientVersionMetadata.PlatformQueryName].ToString();
        return string.IsNullOrWhiteSpace(platform) ? null : platform;
    }

    private static int? ReadClientVersionCode(HttpRequest request)
    {
        var rawVersionCode = request.Headers[ClientVersionMetadata.VersionCodeHeaderName].ToString();
        if (string.IsNullOrWhiteSpace(rawVersionCode))
        {
            rawVersionCode = request.Query[ClientVersionMetadata.VersionCodeQueryName].ToString();
        }

        return int.TryParse(rawVersionCode, out var parsedVersionCode) && parsedVersionCode > 0
            ? parsedVersionCode
            : null;
    }

    private static string? ReadClientVersionName(HttpRequest request)
    {
        var versionName = request.Headers[ClientVersionMetadata.VersionNameHeaderName].ToString();
        if (!string.IsNullOrWhiteSpace(versionName))
        {
            return versionName;
        }

        versionName = request.Query[ClientVersionMetadata.VersionNameQueryName].ToString();
        return string.IsNullOrWhiteSpace(versionName) ? null : versionName;
    }

    private static string? TrimToLength(string? value, int maxLength)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return null;
        }

        var trimmed = value.Trim();
        return trimmed.Length <= maxLength ? trimmed : trimmed[..maxLength];
    }
}
