using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;

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

public sealed class UbuntuConnectorOptions
{
    public const string HttpClientName = "excititor.connector.ubuntu.catalog";

    /// <summary>
    /// Root index that lists Ubuntu CSAF channels.
    /// </summary>
    public Uri IndexUri { get; set; } = new("https://ubuntu.com/security/csaf/index.json");

    /// <summary>
    /// Channels to include (e.g. stable, esm, lts).
    /// </summary>
    public IList<string> Channels { get; } = new List<string> { "stable" };

    /// <summary>
    /// Duration to cache discovery metadata.
    /// </summary>
    public TimeSpan MetadataCacheDuration { get; set; } = TimeSpan.FromHours(4);

    /// <summary>
    /// Prefer offline snapshot when available.
    /// </summary>
    public bool PreferOfflineSnapshot { get; set; }
    /// <summary>
    /// Optional file path for offline index snapshot.
    /// </summary>
    public string? OfflineSnapshotPath { get; set; }
    /// <summary>
    /// Controls persistence of network responses to <see cref="OfflineSnapshotPath"/>.
    /// </summary>
    public bool PersistOfflineSnapshot { get; set; } = true;

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

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

        if (Channels.Count == 0)
        {
            throw new InvalidOperationException("At least one channel must be specified.");
        }

        for (var i = Channels.Count - 1; i >= 0; i--)
        {
            if (string.IsNullOrWhiteSpace(Channels[i]))
            {
                Channels.RemoveAt(i);
            }
        }

        if (Channels.Count == 0)
        {
            throw new InvalidOperationException("Channel names cannot be empty.");
        }

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

        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);
            }
        }
    }
}
