using System.ComponentModel;
using ClawdDotNet.Core.Api;
using ClawdDotNet.Core.Api.Models;

namespace ClawdDotNet.Models;

/// <summary>
/// TypeConverter der im PropertyGrid eine Dropdown-Liste
/// mit verfügbaren OpenRouter-Modellen anzeigt.
/// Die Modelle werden einmalig per API abgerufen und gecached.
/// Freitext-Eingabe bleibt weiterhin möglich (CanConvertFrom = true).
/// </summary>
public sealed class ModelTypeConverter : StringConverter
{
    private static List<ModelInfo>? _cachedModels;
    private static bool _fetchInProgress;
    private static readonly Lock _lock = new();

    /// <summary>
    /// Wird von außen gesetzt (beim Start der Anwendung), damit
    /// der Converter Zugriff auf den OpenRouterClient hat.
    /// </summary>
    public static OpenRouterClient? Client { get; set; }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext? context) => true;

    /// <summary>false = Dropdown ist editierbar (Freitext erlaubt)</summary>
    public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context) => false;

    public override StandardValuesCollection? GetStandardValues(ITypeDescriptorContext? context)
    {
        EnsureModelsLoaded();

        if (_cachedModels is null || _cachedModels.Count == 0)
        {
            // Fallback: Einige gängige Modelle
            return new StandardValuesCollection(new[]
            {
                "anthropic/claude-sonnet-4-5",
                "anthropic/claude-haiku-4",
                "openai/gpt-4.1",
                "openai/gpt-4.1-mini",
                "google/gemini-2.5-pro-preview",
                "google/gemini-2.5-flash-preview",
                "deepseek/deepseek-chat-v3-0324",
                "meta-llama/llama-4-maverick"
            });
        }

        var ids = _cachedModels.Select(m => m.Id).ToArray();
        return new StandardValuesCollection(ids);
    }

    private static void EnsureModelsLoaded()
    {
        if (_cachedModels is not null || Client is null)
            return;

        lock (_lock)
        {
            if (_cachedModels is not null || _fetchInProgress)
                return;

            _fetchInProgress = true;
        }

        // Asynchronen Abruf im Hintergrund starten
        _ = Task.Run(async () =>
        {
            try
            {
                var models = await Client.GetAvailableModelsAsync();
                _cachedModels = models;
            }
            catch
            {
                _cachedModels = []; // Fehler → Fallback wird verwendet
            }
            finally
            {
                lock (_lock) { _fetchInProgress = false; }
            }
        });
    }

    /// <summary>
    /// Kann von außen aufgerufen werden um den Cache zu leeren
    /// (z.B. wenn sich der API-Key ändert).
    /// </summary>
    public static void InvalidateCache()
    {
        lock (_lock) { _cachedModels = null; }
    }
}
