using System.Text.Json;

namespace Watcher.Services;

public class UpdateCheckService : BackgroundService
{
    private readonly ILogger<UpdateCheckService> _logger;
    private readonly IUpdateCheckStore _updateCheckStore;
    private readonly IVersionService _versionService;
    private readonly string _repositoryUrl;
    private readonly int _checkIntervalHours;
    private readonly bool _enabled;
    private readonly HttpClient _httpClient;

    public UpdateCheckService(
        ILogger<UpdateCheckService> logger,
        IUpdateCheckStore updateCheckStore,
        IVersionService versionService,
        IConfiguration configuration)
    {
        _logger = logger;
        _updateCheckStore = updateCheckStore;
        _versionService = versionService;
        _httpClient = new HttpClient();

        // Konfiguration aus Environment Variablen laden
        _repositoryUrl = configuration["UpdateCheck:RepositoryUrl"]
            ?? Environment.GetEnvironmentVariable("UPDATE_CHECK_REPOSITORY_URL")
            ?? "https://git.triggermeelmo.com/api/v1/repos/Watcher/watcher/releases/latest";

        _checkIntervalHours = int.TryParse(
            configuration["UpdateCheck:CheckIntervalHours"]
            ?? Environment.GetEnvironmentVariable("UPDATE_CHECK_INTERVAL_HOURS"),
            out var hours) ? hours : 24; // Default: 24 Stunden

        _enabled = bool.TryParse(
            configuration["UpdateCheck:Enabled"]
            ?? Environment.GetEnvironmentVariable("UPDATE_CHECK_ENABLED"),
            out var enabled) ? enabled : true; // Default: aktiviert

        _logger.LogInformation(
            "UpdateCheckService konfiguriert: Enabled={Enabled}, Repository={Repo}, IntervalHours={Hours}",
            _enabled, _repositoryUrl, _checkIntervalHours);
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        if (!_enabled)
        {
            _logger.LogInformation("UpdateCheckService ist deaktiviert.");
            return;
        }

        // Warte 2 Minuten nach Start, bevor der erste Check läuft
        await Task.Delay(TimeSpan.FromMinutes(2), stoppingToken);

        var timer = new PeriodicTimer(TimeSpan.FromHours(_checkIntervalHours));

        while (await timer.WaitForNextTickAsync(stoppingToken))
        {
            try
            {
                await CheckForUpdatesAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Fehler beim Update-Check.");
            }

            await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
        }
    }

    private async Task CheckForUpdatesAsync()
    {
        var currentVersion = _versionService.GetVersion();

        _logger.LogInformation("Starte Update-Check. Aktuelle Version: {Version}", currentVersion);

        // Bei "development" oder "latest" immer als aktuell markieren
        if (currentVersion == "development" || currentVersion == "latest")
        {
            _updateCheckStore.IsUpdateAvailable = false;
            _updateCheckStore.LatestVersion = currentVersion;
            _updateCheckStore.LastChecked = DateTime.UtcNow;
            _logger.LogInformation("Development/Latest Build - keine Update-Prüfung nötig.");
            return;
        }

        try
        {
            // Gitea API abfragen
            var response = await _httpClient.GetAsync(_repositoryUrl);

            if (!response.IsSuccessStatusCode)
            {
                _logger.LogWarning("Gitea API Fehler: {StatusCode}", response.StatusCode);
                return;
            }

            var jsonContent = await response.Content.ReadAsStringAsync();
            var releaseInfo = JsonSerializer.Deserialize<GiteaReleaseResponse>(jsonContent);

            if (releaseInfo?.TagName == null)
            {
                _logger.LogWarning("Keine Release-Information gefunden.");
                return;
            }

            var latestVersion = releaseInfo.TagName;
            _updateCheckStore.LatestVersion = latestVersion;
            _updateCheckStore.LastChecked = DateTime.UtcNow;

            // Versionsvergleich
            var isNewer = CompareVersions(latestVersion, currentVersion);
            _updateCheckStore.IsUpdateAvailable = isNewer;

            if (isNewer)
            {
                _logger.LogInformation(
                    "Neue Version verfügbar: {Latest} (aktuell: {Current})",
                    latestVersion, currentVersion);
            }
            else
            {
                _logger.LogInformation(
                    "System ist auf dem neuesten Stand: {Version}",
                    currentVersion);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Fehler beim Abrufen der Release-Informationen von Gitea.");
        }
    }

    private bool CompareVersions(string latestVersion, string currentVersion)
    {
        // Entferne "v" Prefix falls vorhanden
        latestVersion = latestVersion.TrimStart('v');
        currentVersion = currentVersion.TrimStart('v');

        // Versuche semantic versioning zu parsen
        if (Version.TryParse(latestVersion, out var latest) &&
            Version.TryParse(currentVersion, out var current))
        {
            return latest > current;
        }

        // Fallback: String-Vergleich
        return string.Compare(latestVersion, currentVersion, StringComparison.Ordinal) > 0;
    }

    // DTO für Gitea API Response
    private class GiteaReleaseResponse
    {
        public string? TagName { get; set; }
    }
}
