using System;
using System.IO;
using System.IO.Abstractions;

namespace StellaOps.Excititor.Connectors.MSRC.CSAF.Configuration;

public sealed class MsrcConnectorOptions
{
    public const string TokenClientName = "excititor.connector.msrc.token";
    public const string DefaultScope = "https://api.msrc.microsoft.com/.default";

    /// <summary>
    /// Azure AD tenant identifier (GUID or domain).
    /// </summary>
    public string TenantId { get; set; } = string.Empty;

    /// <summary>
    /// Azure AD application (client) identifier.
    /// </summary>
    public string ClientId { get; set; } = string.Empty;

    /// <summary>
    /// Azure AD application secret for client credential flow.
    /// </summary>
    public string? ClientSecret { get; set; }
    /// <summary>
    /// OAuth scope requested for MSRC API access.
    /// </summary>
    public string Scope { get; set; } = DefaultScope;

    /// <summary>
    /// When true, token acquisition is skipped and the connector expects offline handling.
    /// </summary>
    public bool PreferOfflineToken { get; set; }
    /// <summary>
    /// Optional path to a pre-provisioned bearer token used when <see cref="PreferOfflineToken"/> is enabled.
    /// </summary>
    public string? OfflineTokenPath { get; set; }
    /// <summary>
    /// Optional fixed bearer token for constrained environments (e.g., short-lived offline bundles).
    /// </summary>
    public string? StaticAccessToken { get; set; }
    /// <summary>
    /// Minimum buffer (seconds) subtracted from token expiry before refresh.
    /// </summary>
    public int ExpiryLeewaySeconds { get; set; } = 60;

    public void Validate(IFileSystem? fileSystem = null)
    {
        if (PreferOfflineToken)
        {
            if (string.IsNullOrWhiteSpace(OfflineTokenPath) && string.IsNullOrWhiteSpace(StaticAccessToken))
            {
                throw new InvalidOperationException("OfflineTokenPath or StaticAccessToken must be provided when PreferOfflineToken is enabled.");
            }
        }
        else
        {
            if (string.IsNullOrWhiteSpace(TenantId))
            {
                throw new InvalidOperationException("TenantId is required when not operating in offline token mode.");
            }

            if (string.IsNullOrWhiteSpace(ClientId))
            {
                throw new InvalidOperationException("ClientId is required when not operating in offline token mode.");
            }

            if (string.IsNullOrWhiteSpace(ClientSecret))
            {
                throw new InvalidOperationException("ClientSecret is required when not operating in offline token mode.");
            }
        }

        if (string.IsNullOrWhiteSpace(Scope))
        {
            Scope = DefaultScope;
        }

        if (ExpiryLeewaySeconds < 10)
        {
            ExpiryLeewaySeconds = 10;
        }

        if (!string.IsNullOrWhiteSpace(OfflineTokenPath))
        {
            var fs = fileSystem ?? new FileSystem();
            var directory = Path.GetDirectoryName(OfflineTokenPath);
            if (!string.IsNullOrWhiteSpace(directory) && !fs.Directory.Exists(directory))
            {
                fs.Directory.CreateDirectory(directory);
            }
        }
    }
}
