using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using ClaudeDo.Data;

namespace ClaudeDo.Worker;

/// <summary>
/// Persists a single secret encrypted with DPAPI (CurrentUser scope), one instance per file.
/// Windows-only. Used for the Online-Inbox refresh token (~/.claudeDo/online-inbox.token) and
/// the ticket-system PAT (~/.claudeDo/ticket.pat).
/// </summary>
[SupportedOSPlatform("windows")]
public sealed class DpapiTokenStore
{
    private readonly string _tokenPath;

    public DpapiTokenStore(string tokenPath) => _tokenPath = tokenPath;

    public static DpapiTokenStore InAppData(string fileName)
        => new(Path.Combine(Paths.AppDataRoot(), fileName));

    public void Save(string secret)
    {
        ArgumentException.ThrowIfNullOrEmpty(secret);
        var cipher = ProtectedData.Protect(Encoding.UTF8.GetBytes(secret), null, DataProtectionScope.CurrentUser);
        Directory.CreateDirectory(Path.GetDirectoryName(_tokenPath)!);
        File.WriteAllBytes(_tokenPath, cipher);
    }

    public string? Read()
    {
        if (!File.Exists(_tokenPath)) return null;
        try
        {
            var plain = ProtectedData.Unprotect(File.ReadAllBytes(_tokenPath), null, DataProtectionScope.CurrentUser);
            return Encoding.UTF8.GetString(plain);
        }
        catch
        {
            return null;
        }
    }

    public bool Exists() => File.Exists(_tokenPath);

    public void Clear()
    {
        if (File.Exists(_tokenPath)) File.Delete(_tokenPath);
    }
}

/// DI-Marker: der Online-Inbox-Refresh-Token.
public sealed record OnlineRefreshTokenStore(DpapiTokenStore Store);

/// DI-Marker: der Personal Access Token des Ticketsystems.
public sealed record TicketPatStore(DpapiTokenStore Store);
