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.Oracle.CSAF.Configuration;
using StellaOps.Excititor.Connectors.Oracle.CSAF.Metadata;
using StellaOps.Excititor.Core;

namespace StellaOps.Excititor.Connectors.Oracle.CSAF;

public sealed class OracleCsafConnector : VexConnectorBase
{
    private static readonly VexConnectorDescriptor DescriptorInstance = new(
        id: "excititor:oracle",
        kind: VexProviderKind.Vendor,
        displayName: "Oracle CSAF")
    {
        Tags = ImmutableArray.Create("oracle", "csaf", "cpu"),
    };

    private readonly OracleCatalogLoader _catalogLoader;
    private readonly IEnumerable<IVexConnectorOptionsValidator<OracleConnectorOptions>> _validators;

    private OracleConnectorOptions? _options;
    private OracleCatalogResult? _catalog;

    public OracleCsafConnector(
        OracleCatalogLoader catalogLoader,
        IEnumerable<IVexConnectorOptionsValidator<OracleConnectorOptions>> validators,
        ILogger<OracleCsafConnector> logger,
        TimeProvider timeProvider)
        : base(DescriptorInstance, logger, timeProvider)
    {
        _catalogLoader = catalogLoader ?? throw new ArgumentNullException(nameof(catalogLoader));
        _validators = validators ?? Array.Empty<IVexConnectorOptionsValidator<OracleConnectorOptions>>();
    }

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

        _catalog = await _catalogLoader.LoadAsync(_options, cancellationToken).ConfigureAwait(false);
        LogConnectorEvent(LogLevel.Information, "validate", "Oracle CSAF catalogue loaded.", new Dictionary<string, object?>
        {
            ["catalogEntryCount"] = _catalog.Metadata.Entries.Length,
            ["scheduleCount"] = _catalog.Metadata.CpuSchedule.Length,
            ["fromOffline"] = _catalog.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 (_catalog is null)
        {
            _catalog = await _catalogLoader.LoadAsync(_options, cancellationToken).ConfigureAwait(false);
        }

        LogConnectorEvent(LogLevel.Debug, "fetch", "Oracle CSAF discovery ready; document ingestion handled by follow-up task.", new Dictionary<string, object?>
        {
            ["since"] = context.Since?.ToString("O"),
        });

        yield break;
    }

    public override ValueTask<VexClaimBatch> NormalizeAsync(VexRawDocument document, CancellationToken cancellationToken)
        => throw new NotSupportedException("OracleCsafConnector relies on dedicated CSAF normalizers.");

    public OracleCatalogResult? GetCachedCatalog() => _catalog;
}
