using System;
using System.Collections.Generic;
using StellaOps.Feedser.Storage.Mongo.Documents;

namespace StellaOps.Feedser.Source.CertFr.Internal;

internal sealed record CertFrDocumentMetadata(
    string AdvisoryId,
    string Title,
    DateTimeOffset Published,
    Uri DetailUri,
    string? Summary)
{
    private const string AdvisoryIdKey = "certfr.advisoryId";
    private const string TitleKey = "certfr.title";
    private const string PublishedKey = "certfr.published";
    private const string SummaryKey = "certfr.summary";

    public static CertFrDocumentMetadata FromDocument(DocumentRecord document)
    {
        ArgumentNullException.ThrowIfNull(document);

        if (document.Metadata is null)
        {
            throw new InvalidOperationException("Cert-FR document metadata is missing.");
        }

        var metadata = document.Metadata;
        if (!metadata.TryGetValue(AdvisoryIdKey, out var advisoryId) || string.IsNullOrWhiteSpace(advisoryId))
        {
            throw new InvalidOperationException("Cert-FR advisory id metadata missing.");
        }

        if (!metadata.TryGetValue(TitleKey, out var title) || string.IsNullOrWhiteSpace(title))
        {
            throw new InvalidOperationException("Cert-FR title metadata missing.");
        }

        if (!metadata.TryGetValue(PublishedKey, out var publishedRaw) || !DateTimeOffset.TryParse(publishedRaw, out var published))
        {
            throw new InvalidOperationException("Cert-FR published metadata invalid.");
        }

        if (!Uri.TryCreate(document.Uri, UriKind.Absolute, out var detailUri))
        {
            throw new InvalidOperationException("Cert-FR document URI invalid.");
        }

        metadata.TryGetValue(SummaryKey, out var summary);

        return new CertFrDocumentMetadata(
            advisoryId.Trim(),
            title.Trim(),
            published.ToUniversalTime(),
            detailUri,
            string.IsNullOrWhiteSpace(summary) ? null : summary.Trim());
    }

    public static IReadOnlyDictionary<string, string> CreateMetadata(CertFrFeedItem item)
    {
        ArgumentNullException.ThrowIfNull(item);

        var metadata = new Dictionary<string, string>(StringComparer.Ordinal)
        {
            [AdvisoryIdKey] = item.AdvisoryId,
            [TitleKey] = item.Title ?? item.AdvisoryId,
            [PublishedKey] = item.Published.ToString("O"),
        };

        if (!string.IsNullOrWhiteSpace(item.Summary))
        {
            metadata[SummaryKey] = item.Summary!;
        }

        return metadata;
    }
}
