using System.Collections.Generic;
using System.Linq;

namespace FishDice.LuckyDice
{
    public sealed class RollTrace
    {
        private readonly List<string> _executedActions = new List<string>();
        private readonly List<ComboRuleMatch> _matchedRules = new List<ComboRuleMatch>();
        private readonly List<RollActionResult> _actionResults = new List<RollActionResult>();

        public RollTrace(string rollSessionId)
        {
            RollSessionId = rollSessionId;
        }

        public string RollSessionId { get; }

        public IReadOnlyList<string> NormalFaces { get; private set; }

        public int NormalDiceCount { get; private set; }

        public string ComboNormalizedKey { get; private set; }

        public string MatchedRuleId { get; private set; }

        public int? MatchedRulePriority { get; private set; }

        public IReadOnlyList<ComboRuleMatch> MatchedRules => _matchedRules;

        public IReadOnlyList<string> ExecutedActions => _executedActions;

        public IReadOnlyList<RollActionResult> ActionResults => _actionResults;

        public int LuckyDiceInitialCandidateCount { get; private set; }

        public int LuckyDiceFilteredCandidateCount { get; private set; }

        public string LuckyDiceFallbackType { get; private set; }

        public int? LuckyDiceRandomValue { get; private set; }

        public string LuckyDiceSelectedResultKey { get; private set; }

        public string LuckyDiceSelectedTargetKey { get; private set; }

        public int LuckyDiceResultSlotCount { get; private set; }

        public IReadOnlyList<string> LuckyDiceSlotResultKeys { get; private set; }

        public string ResolvedTargetKey { get; private set; }

        public string ResolvedModeKey { get; private set; }

        public string TargetModeFailureReason { get; private set; }

        public string FinalOutcome { get; private set; }

        public void RecordComboFacts(ComboFacts facts)
        {
            NormalFaces = facts.Faces.Select(face => face.Key).ToArray();
            NormalDiceCount = facts.DiceCount;
            ComboNormalizedKey = facts.NormalizedKey;
        }

        public void RecordRuleMatch(ComboRuleMatchResult matchResult)
        {
            _matchedRules.Clear();
            _matchedRules.AddRange(matchResult.Matches);

            var first = matchResult.Matches.FirstOrDefault();
            if (first == null)
            {
                return;
            }

            MatchedRuleId = first.RuleId;
            MatchedRulePriority = first.Priority;
        }

        public void RecordActionResult(RollActionResult result)
        {
            _executedActions.Add(result.ActionType);
            _actionResults.Add(result);
            if (result.Success && !string.IsNullOrEmpty(result.Outcome))
            {
                FinalOutcome = result.Outcome;
            }
        }

        public void RecordLuckyDiceSelection(LuckyDiceSelectionResult result)
        {
            LuckyDiceInitialCandidateCount = result.InitialCandidateCount;
            LuckyDiceFilteredCandidateCount = result.FilteredCandidateCount;
            LuckyDiceFallbackType = result.FallbackType;
            LuckyDiceRandomValue = result.RandomValue;
            LuckyDiceSelectedResultKey = result.Selected == null ? null : result.Selected.ResultKey;
            LuckyDiceSelectedTargetKey = result.Selected == null ? null : result.Selected.TargetKey;
            LuckyDiceResultSlotCount = result.SlotCount;
            LuckyDiceSlotResultKeys = result.SlotResultKeys;
        }

        public void RecordTargetMode(TargetModeEntry entry)
        {
            if (entry == null)
            {
                return;
            }

            ResolvedTargetKey = entry.TargetKey;
            ResolvedModeKey = entry.ModeKey;
            FinalOutcome = "TargetModeResolved";
        }

        public void RecordTargetModeFailure(string failureReason)
        {
            TargetModeFailureReason = failureReason;
            FinalOutcome = "TargetModeFailed";
        }
    }
}
