#nullable enable

using System.Globalization;

namespace MBN_STOCK_WEBVIEW.DbWriteSmoke;

internal sealed record SmokeRunIdentity(string BaseName)
{
    internal const string Prefix = "MBW";

    private static readonly IReadOnlyDictionary<string, char> ScenarioCodes =
        new Dictionary<string, char>(StringComparer.Ordinal)
        {
            ["G_PIE"] = 'P',
            ["G_GROW"] = 'G',
            ["G_SELL"] = 'S',
            ["G_PROFIT"] = 'O',
            ["PLAYLIST"] = 'L',
            ["THEME_KRX"] = 'K',
            ["THEME_NXT"] = 'N',
            ["EXPERT"] = 'E'
        };

    internal static SmokeRunIdentity Create(DateTimeOffset utcNow, Guid nonce)
    {
        if (nonce == Guid.Empty)
        {
            throw new ArgumentException("A non-empty smoke nonce is required.", nameof(nonce));
        }

        var utc = utcNow.ToUniversalTime();
        var timestamp = utc.ToString("yyMMdd", CultureInfo.InvariantCulture);
        var suffix = nonce.ToString("N", CultureInfo.InvariantCulture)[..10]
            .ToUpperInvariant();
        return new SmokeRunIdentity(Prefix + timestamp + suffix);
    }

    internal string For(string suffix)
    {
        if (!ScenarioCodes.TryGetValue(suffix, out var scenarioCode))
        {
            throw new ArgumentException("The smoke identity suffix is invalid.", nameof(suffix));
        }

        var value = BaseName + scenarioCode;
        if (value.Length != 20 ||
            value.Any(static character =>
                !(character is >= 'A' and <= 'Z' or >= '0' and <= '9')))
        {
            throw new InvalidOperationException("The smoke identity is outside its closed boundary.");
        }

        return value;
    }
}
