using System;
using System.Collections.Generic;
using UnityEngine;
using YachtDice.Dice;

namespace YachtDice.Game
{
    public class DiceManager : MonoBehaviour
    {
        [SerializeField] private List<DiceRoller> diceRollers = new();

        public event Action OnAllDiceSettled;
        public event Action<int, int> OnDieSettled;

        public int DiceCount => diceRollers.Count;

        private DieInstance[] diceInstances;
        private int pendingCount;

        private void Awake()
        {
            int count = diceRollers.Count;
            diceInstances = new DieInstance[count];

            for (int i = 0; i < count; i++)
            {
                var definition = diceRollers[i].Definition;
                diceInstances[i] = new DieInstance(definition);
            }
        }

        public bool IsLocked(int index) => diceInstances[index].IsLocked;

        public void ToggleLock(int index)
        {
            diceInstances[index].IsLocked = !diceInstances[index].IsLocked;
        }

        public void SetLocked(int index, bool isLocked)
        {
            diceInstances[index].IsLocked = isLocked;
        }

        public void UnlockAll()
        {
            for (int i = 0; i < diceInstances.Length; i++)
                diceInstances[i].IsLocked = false;
        }

        public void RollUnlocked()
        {
            for (int i = 0; i < diceRollers.Count; i++)
                if (diceRollers[i].IsRolling) return;

            pendingCount = 0;

            for (int i = 0; i < diceRollers.Count; i++)
            {
                if (diceInstances[i].IsLocked) continue;

                pendingCount++;
                int capturedIndex = i;

                void Handler(int value)
                {
                    diceRollers[capturedIndex].OnRollFinished -= Handler;
                    diceInstances[capturedIndex].Value = value;
                    OnDieSettled?.Invoke(capturedIndex, value);

                    pendingCount--;
                    if (pendingCount <= 0)
                        OnAllDiceSettled?.Invoke();
                }

                diceRollers[i].OnRollFinished += Handler;
                diceRollers[i].Roll();
            }

            if (pendingCount == 0)
                OnAllDiceSettled?.Invoke();
        }

        /// <summary>Возвращает абстрактный список дайсов (основной API).</summary>
        public IReadOnlyList<IDie> GetDice() => diceInstances;

        /// <summary>Возвращает копию текущих значений (обратная совместимость).</summary>
        public int[] GetCurrentValues()
        {
            int[] values = new int[diceInstances.Length];
            for (int i = 0; i < diceInstances.Length; i++)
                values[i] = diceInstances[i].Value;
            return values;
        }

        public int GetValue(int index) => diceInstances[index].Value;

        public bool IsAnyRolling
        {
            get
            {
                for (int i = 0; i < diceRollers.Count; i++)
                    if (diceRollers[i].IsRolling) return true;
                return false;
            }
        }

        public void ReadAllValues()
        {
            for (int i = 0; i < diceRollers.Count; i++)
            {
                var diceComponent = diceRollers[i].GetComponent<Dice.Dice>();
                if (diceComponent != null && diceComponent.TryGetTopValue(out int val))
                    diceInstances[i].Value = val;
            }
        }
    }
}
