using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components;
using RpgRoller.Contracts;

namespace RpgRoller.Components.Pages.HomeControls;

[ExcludeFromCodeCoverage]
public partial class RollDiceStrip
{
    private static string RollDieGlyph(int roll)
    {
        return roll switch
        {
            1 => "\u2680",
            2 => "\u2681",
            3 => "\u2682",
            4 => "\u2683",
            5 => "\u2684",
            6 => "\u2685",
            _ => roll.ToString()
        };
    }

    private static string RollDieDisplay(RollDieResult die)
    {
        if (string.Equals(die.Kind, RollDieKinds.RolemasterOpenEndedInitial, StringComparison.Ordinal) && !die.SignedContribution.HasValue)
            return $"({die.Roll:00})";

        if (IsRolemasterDie(die))
        {
            return die.Kind switch
            {
                RollDieKinds.RolemasterOpenEndedHigh        => $"+{die.Roll:00}",
                RollDieKinds.RolemasterOpenEndedLowSubtract => $"-{die.Roll:00}",
                _                                           => die.Roll.ToString("00")
            };
        }

        return die.Kind switch
        {
            _ => RollDieGlyph(die.Roll)
        };
    }

    private static string RollDieCssClass(RollDieResult die)
    {
        var classes = new List<string> { "die-chip" };
        if (die.Wild)
            classes.Add("wild");

        if (die.Crit)
            classes.Add("crit");

        if (die.Fumble)
            classes.Add("fumble");

        if (die.Removed)
            classes.Add("removed");

        if (die.Added)
            classes.Add("added");

        switch (die.Kind)
        {
            case RollDieKinds.RolemasterStandard:
                classes.Add("rolemaster-standard");
                break;
            case RollDieKinds.RolemasterOpenEndedInitial:
                classes.Add("rolemaster-open-ended-initial");
                break;
            case RollDieKinds.RolemasterOpenEndedHigh:
                classes.Add("rolemaster-open-ended-high");
                break;
            case RollDieKinds.RolemasterOpenEndedLowSubtract:
                classes.Add("rolemaster-open-ended-low-subtract");
                break;
        }

        return string.Join(" ", classes);
    }

    private static bool IsRolemasterDie(RollDieResult die)
    {
        return die.Kind is RollDieKinds.RolemasterStandard or RollDieKinds.RolemasterOpenEndedInitial or RollDieKinds.RolemasterOpenEndedHigh or RollDieKinds.RolemasterOpenEndedLowSubtract;
    }

    private static string RollDieTitle(RollDieResult die)
    {
        var labels = new List<string> { $"Roll {die.Roll}" };
        if (die.Sequence.HasValue)
            labels.Add($"step {die.Sequence.Value}");

        if (die.Attempt.HasValue)
            labels.Add(die.Attempt.Value == 1 ? "attempt 1" : $"retry attempt {die.Attempt.Value}");

        if (die.Wild)
            labels.Add("wild");

        if (die.Crit)
            labels.Add("critical");

        if (die.Fumble)
            labels.Add("fumble");

        if (die.Removed)
            labels.Add("removed");

        if (die.Added)
            labels.Add("added");

        switch (die.Kind)
        {
            case RollDieKinds.RolemasterStandard:
                labels.Add("Rolemaster roll");
                break;
            case RollDieKinds.RolemasterOpenEndedInitial:
                labels.Add(die.SignedContribution.HasValue ? "Rolemaster open-ended initial" : "Rolemaster low-end trigger (ignored in total)");
                break;
            case RollDieKinds.RolemasterOpenEndedHigh:
                labels.Add($"Rolemaster high follow-up (+{die.Roll})");
                break;
            case RollDieKinds.RolemasterOpenEndedLowSubtract:
                labels.Add($"Rolemaster low-end subtraction (-{die.Roll})");
                break;
        }

        return string.Join(", ", labels);
    }

    [Parameter]
    public IReadOnlyList<RollDieResult> Dice { get; set; } = [];

    [Parameter]
    public string AriaLabel { get; set; } = "Rolled dice";
}