using System.Text.RegularExpressions;
using RolemasterDb.CriticalParsing;

namespace RolemasterDb.App.Features;

public static class CriticalQuickNotationFormatter
{
    public static string Format(
        string descriptionText,
        IReadOnlyList<CriticalEffectEditorItem> effects,
        IReadOnlyList<CriticalBranchEditorItem> branches)
    {
        var lines = new List<string>
        {
            CollapseWhitespace(descriptionText)
        };

        var baseAffixLine = FormatEffects(effects);
        if (!string.IsNullOrWhiteSpace(baseAffixLine))
        {
            lines.Add(baseAffixLine);
        }

        foreach (var branch in branches.OrderBy(item => item.SortOrder))
        {
            var payloadParts = new List<string>();
            var branchDescription = CollapseWhitespace(branch.DescriptionText);
            if (!string.IsNullOrWhiteSpace(branchDescription))
            {
                payloadParts.Add(branchDescription);
            }

            var branchAffixLine = FormatEffects(branch.Effects);
            if (!string.IsNullOrWhiteSpace(branchAffixLine))
            {
                payloadParts.Add(branchAffixLine);
            }

            if (payloadParts.Count == 0)
            {
                continue;
            }

            lines.Add($"{CollapseWhitespace(branch.ConditionText)}: {string.Join(", ", payloadParts)}");
        }

        return string.Join(Environment.NewLine, lines.Where(line => !string.IsNullOrWhiteSpace(line)));
    }

    private static string? FormatEffects(IReadOnlyList<CriticalEffectEditorItem> effects)
    {
        var tokens = effects
            .Select(FormatEffect)
            .Where(token => !string.IsNullOrWhiteSpace(token))
            .ToList();

        return tokens.Count == 0 ? null : string.Join(", ", tokens);
    }

    private static string? FormatEffect(CriticalEffectEditorItem effect) =>
        effect.EffectCode switch
        {
            Domain.CriticalEffectCodes.DirectHits => effect.ValueInteger is int hits ? $"+{hits}" : effect.SourceText,
            Domain.CriticalEffectCodes.StunnedRounds => effect.DurationRounds is int rounds ? $"{rounds}s" : effect.SourceText,
            Domain.CriticalEffectCodes.MustParryRounds => effect.DurationRounds is int rounds ? $"{rounds}mp" : effect.SourceText,
            Domain.CriticalEffectCodes.NoParryRounds => effect.DurationRounds is int rounds ? $"{rounds}np" : effect.SourceText,
            Domain.CriticalEffectCodes.BleedPerRound => effect.PerRound is int bleed ? $"{bleed}hpr" : effect.SourceText,
            Domain.CriticalEffectCodes.FoePenalty => effect.Modifier is int penalty ? penalty.ToString(System.Globalization.CultureInfo.InvariantCulture) : effect.SourceText,
            Domain.CriticalEffectCodes.AttackerBonusNextRound => effect.Modifier is int bonus ? $"+{bonus}b" : effect.SourceText,
            Domain.CriticalEffectCodes.PowerPointModifier => FormatPowerPointModifier(effect.ValueExpression, effect.SourceText),
            _ => effect.SourceText ?? effect.EffectCode
        };

    private static string? FormatPowerPointModifier(string? valueExpression, string? sourceText)
    {
        var expression = PowerPointModifierNotation.FormatSignedExpression(valueExpression);
        return string.IsNullOrWhiteSpace(expression)
            ? sourceText
            : $"{expression}pp";
    }

    private static string CollapseWhitespace(string? value) =>
        string.IsNullOrWhiteSpace(value)
            ? string.Empty
            : Regex.Replace(value.Trim(), @"\s+", " ");
}
