using ClaudeDo.Worker.Config;
using Microsoft.Extensions.Logging;

namespace ClaudeDo.Worker.Tickets;

/// <summary>
/// Der eine Ort, der beantwortet "ist die Ticketsystem-Anbindung eingerichtet?".
/// Liest die Base-URL aus dem WorkerConfig-Singleton (in-place aktualisiert vom Hub-Setter,
/// also ohne Neustart wirksam) und den PAT aus dem DPAPI-Store.
///
/// IsConfigured ist die Abbruchbedingung im Hook, der bei jedem Statuswechsel läuft. Ohne
/// Base-URL — der Normalfall — kostet sie dank Kurzschluss gar nichts: der Token wird nie
/// gelesen, keine Datei, keine DB. Ist eine Base-URL gesetzt, kommt pro Aufruf ein
/// DPAPI-Entschlüsseln einer kleinen Datei dazu; bei ein paar Statuswechseln pro Task ist das
/// billiger als ein Cache, den jemand invalidieren müsste.
/// </summary>
public sealed class TicketSystemConfig
{
    private readonly WorkerConfig _worker;
    private readonly TicketPatStore _pat;

    public TicketSystemConfig(WorkerConfig worker, TicketPatStore pat)
    {
        _worker = worker;
        _pat = pat;
    }

    /// <summary>
    /// Die Base-URL, wie HttpClient sie braucht: absolut, ohne Schrägstrich am Ende.
    ///
    /// Ein Feld namens "API base URL" lädt dazu ein, einen blanken Hostnamen einzutippen.
    /// Ohne Schema ist das aber eine RELATIVE URI, und HttpClient lehnt sie mit einer
    /// InvalidOperationException ab, lange bevor ein Paket fließt. Deshalb wird hier — und nur
    /// hier, weil das der einzige Leser ist — `http://` ergänzt. `http` und nicht `https`, weil
    /// die API im Intranet ohne TLS läuft; wer TLS will, tippt das Schema hin und es bleibt stehen.
    /// </summary>
    public string? BaseUrl
    {
        get
        {
            var raw = _worker.TicketApiBaseUrl?.Trim();
            if (string.IsNullOrEmpty(raw)) return null;
            if (!raw.Contains("://", StringComparison.Ordinal)) raw = "http://" + raw;
            return raw.TrimEnd('/');
        }
    }

    public string? Token => _pat.Store.Read();

    public bool IsConfigured => BaseUrl is not null && !string.IsNullOrEmpty(Token);
}

/// Baut einen Client aus der aktuellen Konfiguration, oder null, wenn nichts eingerichtet ist.
public sealed class TicketClientFactory
{
    private readonly TicketSystemConfig _config;
    private readonly IHttpClientFactory _httpFactory;
    private readonly ILogger<BandelTicketClient> _logger;

    public TicketClientFactory(TicketSystemConfig config, IHttpClientFactory httpFactory, ILogger<BandelTicketClient> logger)
    {
        _config = config;
        _httpFactory = httpFactory;
        _logger = logger;
    }

    public BandelTicketClient? Create()
    {
        if (!_config.IsConfigured) return null;
        return new BandelTicketClient(_httpFactory.CreateClient("tickets"), _config.BaseUrl!, _config.Token!, _logger);
    }
}
