using System.Linq;

namespace FishDice.LuckyDice
{
    public sealed class LuckyDiceSelectedResult
    {
        internal LuckyDiceSelectedResult(string resultKey, string targetKey, int slotCount)
        {
            ResultKey = resultKey;
            TargetKey = targetKey;
            SlotCount = slotCount;
        }

        public string ResultKey { get; }

        public string TargetKey { get; }

        public int SlotCount { get; }
    }

    public sealed class LuckyDiceSelectionResult
    {
        internal LuckyDiceSelectionResult(
            LuckyDiceCandidateConfig selectedCandidate,
            int initialCandidateCount,
            int filteredCandidateCount,
            int? randomValue,
            string fallbackType,
            int slotCount)
        {
            InitialCandidateCount = initialCandidateCount;
            FilteredCandidateCount = filteredCandidateCount;
            RandomValue = randomValue;
            FallbackType = fallbackType;
            SlotCount = selectedCandidate == null ? 0 : slotCount;
            Selected = selectedCandidate == null
                ? null
                : new LuckyDiceSelectedResult(selectedCandidate.ResultKey, selectedCandidate.TargetKey, SlotCount);
            SlotResultKeys = selectedCandidate == null ? null : Enumerable.Repeat(selectedCandidate.ResultKey, SlotCount).ToArray();
        }

        public LuckyDiceSelectedResult Selected { get; }

        public int InitialCandidateCount { get; }

        public int FilteredCandidateCount { get; }

        public int? RandomValue { get; }

        public string FallbackType { get; }

        public int SlotCount { get; }

        public string[] SlotResultKeys { get; }
    }

    public sealed class TargetModeEntry
    {
        private TargetModeEntry(
            string targetKey,
            string modeKey,
            string resultKey,
            int multiplier,
            string triggerSource,
            string rollSessionId)
        {
            TargetKey = targetKey;
            ModeKey = modeKey;
            ResultKey = resultKey;
            Multiplier = multiplier;
            TriggerSource = triggerSource;
            RollSessionId = rollSessionId;
        }

        public string TargetKey { get; }

        public string ModeKey { get; }

        public string ResultKey { get; }

        public int Multiplier { get; }

        public string TriggerSource { get; }

        public string RollSessionId { get; }

        internal static TargetModeEntry From(TargetModeConfig definition, RollFlowRequest request, int multiplier)
        {
            return new TargetModeEntry(
                definition.TargetKey,
                definition.ModeKey,
                definition.ResultKey,
                multiplier,
                request.TriggerSource,
                request.RollSessionId);
        }
    }

    public sealed class TargetModeResolveResult
    {
        private TargetModeResolveResult(bool success, TargetModeEntry entry, string failureReason, string fallbackMode)
        {
            Success = success;
            Entry = entry;
            FailureReason = failureReason;
            FallbackMode = fallbackMode;
        }

        public bool Success { get; }

        public TargetModeEntry Entry { get; }

        public string FailureReason { get; }

        public string FallbackMode { get; }

        public static TargetModeResolveResult Resolved(TargetModeEntry entry)
        {
            return new TargetModeResolveResult(true, entry, null, null);
        }

        public static TargetModeResolveResult Failed(string failureReason, string fallbackMode = null)
        {
            return new TargetModeResolveResult(false, null, failureReason, fallbackMode);
        }
    }
}
