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

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

public sealed class OracleConnectorOptions
{
    public const string HttpClientName = "excititor.connector.oracle.catalog";

    /// <summary>
    /// Oracle CSAF catalog endpoint hosting advisory metadata.
    /// </summary>
    public Uri CatalogUri { get; set; } = new("https://www.oracle.com/security-alerts/cpu/csaf/catalog.json");

    /// <summary>
    /// Optional CPU calendar endpoint providing upcoming release dates.
    /// </summary>
    public Uri? CpuCalendarUri { get; set; }
    /// <summary>
    /// Duration the discovery metadata should be cached before refresh.
    /// </summary>
    public TimeSpan MetadataCacheDuration { get; set; } = TimeSpan.FromHours(6);

    /// <summary>
    /// When true, the loader will prefer offline snapshot data over network fetches.
    /// </summary>
    public bool PreferOfflineSnapshot { get; set; }
    /// <summary>
    /// Optional file path for persisting or ingesting catalog snapshots.
    /// </summary>
    public string? OfflineSnapshotPath { get; set; }
    /// <summary>
    /// Enables writing fresh catalog responses to <see cref="OfflineSnapshotPath"/>.
    /// </summary>
    public bool PersistOfflineSnapshot { get; set; } = true;

    /// <summary>
    /// Optional request delay when iterating catalogue entries (for rate limiting).
    /// </summary>
    public TimeSpan RequestDelay { get; set; } = TimeSpan.FromMilliseconds(250);

    public void Validate(IFileSystem? fileSystem = null)
    {
        if (CatalogUri is null || !CatalogUri.IsAbsoluteUri)
        {
            throw new InvalidOperationException("CatalogUri must be an absolute URI.");
        }

        if (CatalogUri.Scheme is not ("http" or "https"))
        {
            throw new InvalidOperationException("CatalogUri must use HTTP or HTTPS.");
        }

        if (CpuCalendarUri is not null && (!CpuCalendarUri.IsAbsoluteUri || CpuCalendarUri.Scheme is not ("http" or "https")))
        {
            throw new InvalidOperationException("CpuCalendarUri must be an absolute HTTP(S) URI when provided.");
        }

        if (MetadataCacheDuration <= TimeSpan.Zero)
        {
            throw new InvalidOperationException("MetadataCacheDuration must be positive.");
        }

        if (RequestDelay < TimeSpan.Zero)
        {
            throw new InvalidOperationException("RequestDelay cannot be negative.");
        }

        if (PreferOfflineSnapshot && string.IsNullOrWhiteSpace(OfflineSnapshotPath))
        {
            throw new InvalidOperationException("OfflineSnapshotPath must be provided when PreferOfflineSnapshot is enabled.");
        }

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