using System.Text.Json;

namespace RolemasterDb.App.Features;

public static class CriticalCellComparisonEvaluator
{
    private static readonly JsonSerializerOptions ComparisonJsonOptions = new(JsonSerializerDefaults.Web);

    public static int GetDifferenceCount(
        string? currentDescription,
        IReadOnlyList<CriticalEffectLookupResponse> currentEffects,
        IReadOnlyList<CriticalBranchLookupResponse> currentBranches,
        CriticalCellComparisonState generatedState)
    {
        var count = 0;

        if (DescriptionDiffers(currentDescription, generatedState.DescriptionText))
        {
            count++;
        }

        if (EffectsDiffer(currentEffects, generatedState.Effects))
        {
            count++;
        }

        if (BranchesDiffer(currentBranches, generatedState.Branches))
        {
            count++;
        }

        return count;
    }

    public static bool DescriptionDiffers(string? currentDescription, string? generatedDescription) =>
        !string.Equals(
            NormalizeText(currentDescription),
            NormalizeText(generatedDescription),
            StringComparison.Ordinal);

    public static bool EffectsDiffer(
        IReadOnlyList<CriticalEffectLookupResponse> currentEffects,
        IReadOnlyList<CriticalEffectLookupResponse> generatedEffects) =>
        SerializeComparisonValue(currentEffects.Select(ProjectEffectForComparison).ToList()) !=
        SerializeComparisonValue(generatedEffects.Select(ProjectEffectForComparison).ToList());

    public static bool BranchesDiffer(
        IReadOnlyList<CriticalBranchLookupResponse> currentBranches,
        IReadOnlyList<CriticalBranchLookupResponse> generatedBranches) =>
        SerializeComparisonValue(currentBranches.Select(ProjectBranchForComparison).ToList()) !=
        SerializeComparisonValue(generatedBranches.Select(ProjectBranchForComparison).ToList());

    private static string NormalizeText(string? value) =>
        value?.Trim() ?? string.Empty;

    private static string SerializeComparisonValue<TValue>(TValue value) =>
        JsonSerializer.Serialize(value, ComparisonJsonOptions);

    private static object ProjectEffectForComparison(CriticalEffectLookupResponse effect) => new
    {
        effect.EffectCode,
        Target = NormalizeText(effect.Target),
        effect.ValueInteger,
        ValueExpression = NormalizeText(effect.ValueExpression),
        effect.DurationRounds,
        effect.PerRound,
        effect.Modifier,
        BodyPart = NormalizeText(effect.BodyPart),
        effect.IsPermanent
    };

    private static object ProjectBranchForComparison(CriticalBranchLookupResponse branch) => new
    {
        Condition = NormalizeText(branch.ConditionText),
        Description = NormalizeText(branch.Description),
        Effects = branch.Effects
            .Select(ProjectEffectForComparison)
            .ToList()
    };
}
