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

namespace StellaOps.Excititor.Connectors.MyProvider;

public sealed class MyConnector : VexConnectorBase
{
    private readonly IEnumerable<IVexConnectorOptionsValidator<MyConnectorOptions>> _validators;
    private MyConnectorOptions? _options;

    public MyConnector(VexConnectorDescriptor descriptor, ILogger<MyConnector> logger, TimeProvider timeProvider, IEnumerable<IVexConnectorOptionsValidator<MyConnectorOptions>> validators)
        : base(descriptor, logger, timeProvider)
    {
        _validators = validators;
    }

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

        LogConnectorEvent(LogLevel.Information, "validate", "MyConnector configuration loaded.",
            new Dictionary<string, object?>
            {
                ["catalogUri"] = _options.CatalogUri,
                ["maxParallelRequests"] = _options.MaxParallelRequests,
            });

        return ValueTask.CompletedTask;
    }

    public override IAsyncEnumerable<VexRawDocument> FetchAsync(VexConnectorContext context, CancellationToken cancellationToken)
    {
        if (_options is null)
        {
            throw new InvalidOperationException("Connector not validated.");
        }

        return FetchInternalAsync(context, cancellationToken);
    }

    private async IAsyncEnumerable<VexRawDocument> FetchInternalAsync(VexConnectorContext context, [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        LogConnectorEvent(LogLevel.Information, "fetch", "Fetching catalog window...");

        // Replace with real HTTP logic.
        await Task.Delay(10, cancellationToken);

        var metadata = BuildMetadata(builder => builder
            .Add("sourceUri", _options!.CatalogUri)
            .Add("window", context.Since?.ToString("O") ?? "full"));

        yield return CreateRawDocument(
            VexDocumentFormat.CsafJson,
            new Uri($"{_options.CatalogUri.TrimEnd('/')}/sample.json"),
            new byte[] { 0x7B, 0x7D },
            metadata);
    }

    public override ValueTask<VexClaimBatch> NormalizeAsync(VexRawDocument document, CancellationToken cancellationToken)
    {
        var claims = ImmutableArray<VexClaim>.Empty;
        var diagnostics = ImmutableDictionary<string, string>.Empty;
        return ValueTask.FromResult(new VexClaimBatch(document, claims, diagnostics));
    }
}
