using System;
using System.Collections.Generic;
using System.Text;

namespace StellaOps.Feedser.Models;

/// <summary>
/// Provides helpers to normalize vendor-provided severity labels into canonical values.
/// </summary>
public static class SeverityNormalization
{
    private static readonly IReadOnlyDictionary<string, string> SeverityMap = new Dictionary<string, string>
    {
        ["critical"] = "critical",
        ["crit"] = "critical",
        ["sevcritical"] = "critical",
        ["extreme"] = "critical",
        ["verycritical"] = "critical",
        ["veryhigh"] = "critical",
        ["p0"] = "critical",
        ["priority0"] = "critical",
        ["high"] = "high",
        ["sevhigh"] = "high",
        ["important"] = "high",
        ["severe"] = "high",
        ["major"] = "high",
        ["urgent"] = "high",
        ["elevated"] = "high",
        ["p1"] = "high",
        ["priority1"] = "high",
        ["medium"] = "medium",
        ["moderate"] = "medium",
        ["normal"] = "medium",
        ["avg"] = "medium",
        ["average"] = "medium",
        ["standard"] = "medium",
        ["p2"] = "medium",
        ["priority2"] = "medium",
        ["low"] = "low",
        ["minor"] = "low",
        ["minimal"] = "low",
        ["limited"] = "low",
        ["p3"] = "low",
        ["priority3"] = "low",
        ["informational"] = "informational",
        ["info"] = "informational",
        ["informative"] = "informational",
        ["notice"] = "informational",
        ["advisory"] = "informational",
        ["none"] = "none",
        ["negligible"] = "none",
        ["insignificant"] = "none",
        ["notapplicable"] = "none",
        ["na"] = "none",
        ["unknown"] = "unknown",
        ["undetermined"] = "unknown",
        ["notdefined"] = "unknown",
        ["notspecified"] = "unknown",
        ["pending"] = "unknown",
        ["tbd"] = "unknown",
    };

    private static readonly char[] TokenSeparators =
    {
        ' ',
        '/',
        '\\',
        '-',
        '_',
        ',',
        ';',
        ':',
        '(',
        ')',
        '[',
        ']',
        '{',
        '}',
        '|',
        '+',
        '&'
    };

    public static readonly IReadOnlyCollection<string> CanonicalLevels = new[]
    {
        "critical",
        "high",
        "medium",
        "low",
        "informational",
        "none",
        "unknown",
    };

    public static string? Normalize(string? severity)
    {
        if (string.IsNullOrWhiteSpace(severity))
        {
            return null;
        }

        var trimmed = severity.Trim();

        if (TryNormalizeToken(trimmed, out var mapped))
        {
            return mapped;
        }

        foreach (var token in trimmed.Split(TokenSeparators, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
        {
            if (TryNormalizeToken(token, out mapped))
            {
                return mapped;
            }
        }

        return trimmed.ToLowerInvariant();
    }

    private static bool TryNormalizeToken(string value, out string mapped)
    {
        var normalized = NormalizeToken(value);
        if (normalized.Length == 0)
        {
            mapped = string.Empty;
            return false;
        }

        if (!SeverityMap.TryGetValue(normalized, out var mappedValue))
        {
            mapped = string.Empty;
            return false;
        }

        mapped = mappedValue;
        return true;
    }

    private static string NormalizeToken(string value)
    {
        var builder = new StringBuilder(value.Length);
        foreach (var ch in value)
        {
            if (char.IsLetterOrDigit(ch))
            {
                builder.Append(char.ToLowerInvariant(ch));
            }
        }

        return builder.ToString();
    }
}
