using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Logging;
using StellaOps.Excititor.Connectors.Abstractions;
using StellaOps.Excititor.Connectors.SUSE.RancherVEXHub.Configuration;
using StellaOps.Excititor.Connectors.SUSE.RancherVEXHub.Metadata;
using StellaOps.Excititor.Core;

namespace StellaOps.Excititor.Connectors.SUSE.RancherVEXHub;

public sealed class RancherHubConnector : VexConnectorBase
{
    private static readonly VexConnectorDescriptor StaticDescriptor = new(
            id: "excititor:suse.rancher",
            kind: VexProviderKind.Hub,
            displayName: "SUSE Rancher VEX Hub")
        {
            Tags = ImmutableArray.Create("hub", "suse", "offline"),
        };

    private readonly RancherHubMetadataLoader _metadataLoader;
    private readonly IEnumerable<IVexConnectorOptionsValidator<RancherHubConnectorOptions>> _validators;

    private RancherHubConnectorOptions? _options;
    private RancherHubMetadataResult? _metadata;

    public RancherHubConnector(
        RancherHubMetadataLoader metadataLoader,
        ILogger<RancherHubConnector> logger,
        TimeProvider timeProvider,
        IEnumerable<IVexConnectorOptionsValidator<RancherHubConnectorOptions>>? validators = null)
        : base(StaticDescriptor, logger, timeProvider)
    {
        _metadataLoader = metadataLoader ?? throw new ArgumentNullException(nameof(metadataLoader));
        _validators = validators ?? Array.Empty<IVexConnectorOptionsValidator<RancherHubConnectorOptions>>();
    }

    public override async ValueTask ValidateAsync(VexConnectorSettings settings, CancellationToken cancellationToken)
    {
        _options = VexConnectorOptionsBinder.Bind(
            Descriptor,
            settings,
            validators: _validators);

        _metadata = await _metadataLoader.LoadAsync(_options, cancellationToken).ConfigureAwait(false);

        LogConnectorEvent(LogLevel.Information, "validate", "Rancher hub discovery loaded.", new Dictionary<string, object?>
        {
            ["discoveryUri"] = _options.DiscoveryUri.ToString(),
            ["subscriptionUri"] = _metadata.Metadata.Subscription.EventsUri.ToString(),
            ["requiresAuth"] = _metadata.Metadata.Subscription.RequiresAuthentication,
            ["fromOffline"] = _metadata.FromOfflineSnapshot,
        });
    }

    public override async IAsyncEnumerable<VexRawDocument> FetchAsync(VexConnectorContext context, [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(context);

        if (_options is null)
        {
            throw new InvalidOperationException("Connector must be validated before fetch operations.");
        }

        if (_metadata is null)
        {
            _metadata = await _metadataLoader.LoadAsync(_options, cancellationToken).ConfigureAwait(false);
        }

        LogConnectorEvent(LogLevel.Debug, "fetch", "Rancher hub connector discovery ready; event ingestion will be implemented in EXCITITOR-CONN-SUSE-01-002.", new Dictionary<string, object?>
        {
            ["since"] = context.Since?.ToString("O"),
            ["subscriptionUri"] = _metadata.Metadata.Subscription.EventsUri.ToString(),
        });

        yield break;
    }

    public override ValueTask<VexClaimBatch> NormalizeAsync(VexRawDocument document, CancellationToken cancellationToken)
        => throw new NotSupportedException("RancherHubConnector relies on format-specific normalizers for CSAF/OpenVEX payloads.");

    public RancherHubMetadata? GetCachedMetadata() => _metadata?.Metadata;
}
