using System;
using System.Collections;
using FishDice.LuckyDice;
using UnityEngine.EventSystems;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;

namespace FishDice.Demo
{
    public sealed class LuckyDiceDemoController : MonoBehaviour
    {
        private static readonly string[] NormalPreviewFaces = { "2", "3", "4", "5", "6", "Clover" };
        private static readonly string[] LuckyPreviewFaces = { "Rocket", "Thief" };
        public const string BuiltinFontResourcePath = "LegacyRuntime.ttf";

        private readonly SystemRandomSource _flowRandom = new SystemRandomSource(new System.Random());
        private Text _titleText;
        private Text _statusText;
        private Text _detailText;
        private Text _rewardText;
        private Text[] _normalDiceTexts;
        private Text[] _luckyDiceTexts;
        private Button _primaryButton;
        private Text _primaryButtonText;
        private Coroutine _flowRoutine;
        private LuckyDiceDemoSnapshot _lastSnapshot;
        private Font _uiFont;

        private void Awake()
        {
            BuildUi();
            ShowReady();
        }

        private void StartRoll()
        {
            if (_flowRoutine != null)
            {
                StopCoroutine(_flowRoutine);
            }

            _flowRoutine = StartCoroutine(PlayRollFlow());
        }

        private IEnumerator PlayRollFlow()
        {
            _primaryButton.interactable = false;
            _primaryButtonText.text = "投掷中";
            _rewardText.text = string.Empty;
            _detailText.text = string.Empty;
            SetLuckyDiceVisible(false);
            SetStatus("摇动普通骰子");

            _lastSnapshot = LuckyDiceDemoRunner.RunRandom(_flowRandom);
            yield return AnimateDice(_normalDiceTexts, NormalPreviewFaces, 0.9f);
            ApplyDiceTexts(_normalDiceTexts, _lastSnapshot.NormalFaces);
            SetStatus("组合判定");
            _detailText.text = _lastSnapshot.ComboLine;
            yield return new WaitForSeconds(0.55f);

            if (_lastSnapshot.OutcomeKind == "lucky_dice")
            {
                SetStatus("触发 Lucky Dice");
                _rewardText.text = "双 Clover 命中";
                yield return new WaitForSeconds(0.45f);
                SetLuckyDiceVisible(true);
                SetStatus("揭示特殊骰子");
                yield return AnimateDice(_luckyDiceTexts, LuckyPreviewFaces, 1.0f);
                ApplyDiceTexts(_luckyDiceTexts, _lastSnapshot.LuckyDiceSlotKeys);
            }

            ShowResult(_lastSnapshot);
            _flowRoutine = null;
        }

        private IEnumerator AnimateDice(Text[] diceTexts, string[] previewFaces, float duration)
        {
            var elapsed = 0f;
            while (elapsed < duration)
            {
                for (var i = 0; i < diceTexts.Length; i++)
                {
                    diceTexts[i].text = previewFaces[Random.Range(0, previewFaces.Length)];
                }

                yield return new WaitForSeconds(0.08f);
                elapsed += 0.08f;
            }
        }

        private void ShowReady()
        {
            _titleText.text = "Lucky Dice";
            SetStatus("准备投骰");
            _detailText.text = "普通骰子会随机落点，命中双 Clover 后进入 Lucky Dice。";
            _rewardText.text = string.Empty;
            ApplyDiceTexts(_normalDiceTexts, new[] { "?", "?" });
            ApplyDiceTexts(_luckyDiceTexts, new[] { "?", "?", "?" });
            SetLuckyDiceVisible(false);
            _primaryButton.interactable = true;
            _primaryButtonText.text = "投骰";
        }

        private void ShowResult(LuckyDiceDemoSnapshot snapshot)
        {
            SetStatus(ResolveResultStatus(snapshot));
            _detailText.text = $"{snapshot.FaceLine}\n{snapshot.RuleLine}\n{snapshot.EffectLine}";
            _rewardText.text = snapshot.TargetModeLine == "Target Mode: -"
                ? snapshot.Summary
                : $"{snapshot.Summary}\n{snapshot.TargetModeLine}";
            _primaryButton.interactable = true;
            _primaryButtonText.text = "再投一次";
        }

        private static string ResolveResultStatus(LuckyDiceDemoSnapshot snapshot)
        {
            switch (snapshot.OutcomeKind)
            {
                case "lucky_dice":
                    return "进入目标玩法";
                case "clover_bonus":
                    return "获得 Clover Bonus";
                case "normal_reward":
                    return "获得普通奖励";
                default:
                    return "本轮结束";
            }
        }

        private void BuildUi()
        {
            EnsureEventSystem();

            var canvasObject = new GameObject("LuckyDiceCanvas");
            canvasObject.transform.SetParent(transform, false);
            var canvas = canvasObject.AddComponent<Canvas>();
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            canvas.pixelPerfect = true;
            var scaler = canvasObject.AddComponent<CanvasScaler>();
            scaler.uiScaleMode = CanvasScaler.ScaleMode.ConstantPixelSize;
            scaler.scaleFactor = 1f;
            scaler.referencePixelsPerUnit = 100f;
            canvasObject.AddComponent<GraphicRaycaster>();

            var root = CreatePanel("Root", canvasObject.transform, new Color(0.06f, 0.09f, 0.13f, 1f));
            Stretch(root.rectTransform);

            var board = CreatePanel("Board", root.transform, new Color(0.12f, 0.16f, 0.22f, 0.96f));
            Center(board.rectTransform, new Vector2(760f, 600f));

            _titleText = CreateText("Title", board.transform, "Lucky Dice", 34, FontStyle.Bold, Color.white);
            SetRect(_titleText.rectTransform, new Vector2(0f, 194f), new Vector2(680f, 48f));

            _statusText = CreateText("Status", board.transform, string.Empty, 24, FontStyle.Bold, new Color(1f, 0.84f, 0.38f));
            SetRect(_statusText.rectTransform, new Vector2(0f, 142f), new Vector2(680f, 40f));

            _normalDiceTexts = new[]
            {
                CreateDiceText("NormalDiceA", board.transform, new Vector2(-96f, 64f), new Color(0.96f, 0.97f, 1f)),
                CreateDiceText("NormalDiceB", board.transform, new Vector2(96f, 64f), new Color(0.96f, 0.97f, 1f))
            };

            _luckyDiceTexts = new[]
            {
                CreateDiceText("LuckySlotA", board.transform, new Vector2(-150f, -48f), new Color(1f, 0.86f, 0.46f)),
                CreateDiceText("LuckySlotB", board.transform, new Vector2(0f, -48f), new Color(1f, 0.86f, 0.46f)),
                CreateDiceText("LuckySlotC", board.transform, new Vector2(150f, -48f), new Color(1f, 0.86f, 0.46f))
            };

            _detailText = CreateText("Detail", board.transform, string.Empty, 16, FontStyle.Normal, new Color(0.82f, 0.88f, 0.94f));
            SetRect(_detailText.rectTransform, new Vector2(0f, -142f), new Vector2(650f, 86f));

            _rewardText = CreateText("Reward", board.transform, string.Empty, 19, FontStyle.Bold, new Color(0.55f, 0.92f, 0.75f));
            SetRect(_rewardText.rectTransform, new Vector2(0f, -210f), new Vector2(650f, 56f));

            _primaryButton = CreateButton("PrimaryButton", board.transform, "投骰", new Vector2(0f, -254f), new Vector2(190f, 48f));
            _primaryButton.onClick.AddListener(StartRoll);
        }

        private static void EnsureEventSystem()
        {
            if (FindObjectOfType<EventSystem>() != null)
            {
                return;
            }

            var eventSystemObject = new GameObject("EventSystem");
            eventSystemObject.AddComponent<EventSystem>();
            eventSystemObject.AddComponent<StandaloneInputModule>();
        }

        private Text CreateDiceText(string name, Transform parent, Vector2 anchoredPosition, Color faceColor)
        {
            var background = CreatePanel(name, parent, new Color(0.2f, 0.25f, 0.33f, 1f));
            SetRect(background.rectTransform, anchoredPosition, new Vector2(116f, 84f));

            var text = CreateText(name + "Text", background.transform, "?", 24, FontStyle.Bold, faceColor);
            Stretch(text.rectTransform);
            return text;
        }

        private Button CreateButton(string name, Transform parent, string label, Vector2 anchoredPosition, Vector2 size)
        {
            var image = CreatePanel(name, parent, new Color(0.92f, 0.56f, 0.16f, 1f));
            SetRect(image.rectTransform, anchoredPosition, size);
            var button = image.gameObject.AddComponent<Button>();
            _primaryButtonText = CreateText(name + "Text", image.transform, label, 20, FontStyle.Bold, Color.white);
            Stretch(_primaryButtonText.rectTransform);
            return button;
        }

        private Image CreatePanel(string name, Transform parent, Color color)
        {
            var gameObject = new GameObject(name, typeof(RectTransform), typeof(Image));
            gameObject.transform.SetParent(parent, false);
            var image = gameObject.GetComponent<Image>();
            image.color = color;
            return image;
        }

        private Text CreateText(string name, Transform parent, string text, int fontSize, FontStyle fontStyle, Color color)
        {
            var gameObject = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(Text));
            gameObject.transform.SetParent(parent, false);
            var label = gameObject.GetComponent<Text>();
            label.font = GetUiFont();
            label.text = text;
            label.fontSize = fontSize;
            label.fontStyle = fontStyle;
            label.color = color;
            label.alignment = TextAnchor.MiddleCenter;
            label.horizontalOverflow = HorizontalWrapMode.Wrap;
            label.verticalOverflow = VerticalWrapMode.Overflow;
            label.alignByGeometry = true;
            label.raycastTarget = false;
            return label;
        }

        private Font GetUiFont()
        {
            if (_uiFont == null)
            {
                _uiFont = Resources.GetBuiltinResource<Font>(BuiltinFontResourcePath);
            }

            return _uiFont;
        }

        private void SetStatus(string text)
        {
            _statusText.text = text;
        }

        private void ApplyDiceTexts(Text[] diceTexts, string[] values)
        {
            for (var i = 0; i < diceTexts.Length; i++)
            {
                diceTexts[i].text = i < values.Length ? FormatFace(values[i]) : "-";
            }
        }

        private static string FormatFace(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return "-";
            }

            return char.ToUpperInvariant(value[0]) + value.Substring(1);
        }

        private void SetLuckyDiceVisible(bool visible)
        {
            foreach (var text in _luckyDiceTexts)
            {
                text.transform.parent.gameObject.SetActive(visible);
            }
        }

        private static void Center(RectTransform rectTransform, Vector2 size)
        {
            rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
            rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
            rectTransform.pivot = new Vector2(0.5f, 0.5f);
            rectTransform.sizeDelta = size;
            rectTransform.anchoredPosition = Vector2.zero;
        }

        private static void SetRect(RectTransform rectTransform, Vector2 position, Vector2 size)
        {
            rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
            rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
            rectTransform.pivot = new Vector2(0.5f, 0.5f);
            rectTransform.sizeDelta = size;
            rectTransform.anchoredPosition = position;
        }

        private static void Stretch(RectTransform rectTransform)
        {
            rectTransform.anchorMin = Vector2.zero;
            rectTransform.anchorMax = Vector2.one;
            rectTransform.offsetMin = Vector2.zero;
            rectTransform.offsetMax = Vector2.zero;
        }
    }
}
