// Assets/_Project/Scripts/Gameplay/MatchState.cs
using Unity.Netcode;
using UnityEngine;
using TD.Core;

namespace TD.Gameplay
{
    /// <summary>
    /// Singleton NetworkBehaviour that tracks global match data.
    /// Lives on a persistent scene object.
    ///
    /// All state is server-authoritative (Server-write NetworkVariables).
    /// Clients react to OnValueChanged events on individual fields.
    /// Phase transitions (Lobby → CountDown → Playing → Victory/Defeat)
    /// and wave/lives logic are wired in Phases 1.4–1.6 and 1.8.
    /// </summary>
    public class MatchState : NetworkBehaviour
    {
        // --- Singleton ---------------------------------------------------

        public static MatchState Instance { get; private set; }

        // --- Networked state ---------------------------------------------

        private readonly NetworkVariable<MatchPhase> phase = new NetworkVariable<MatchPhase>(
            value: MatchPhase.Playing,
            readPerm: NetworkVariableReadPermission.Everyone,
            writePerm: NetworkVariableWritePermission.Server
        );

        /// <summary>Current match phase. Authoritative on the server, replicated to all clients.</summary>
        public MatchPhase Phase => phase.Value;

        // STUBBED — written by the wave system (Phase 1.5/1.6). Zero until waves begin.
        [Tooltip("STUBBED — not written until the wave system lands (Phase 1.5/1.6).")]
        private readonly NetworkVariable<int> currentWave = new NetworkVariable<int>(
            value: 0,
            readPerm: NetworkVariableReadPermission.Everyone,
            writePerm: NetworkVariableWritePermission.Server
        );

        /// <summary>STUBBED. Current wave index. Zero until the wave system (Phase 1.5/1.6) writes it.</summary>
        public int CurrentWave => currentWave.Value;

        // STUBBED — written by the combat/leak system (Phase 1.4). Zero until then.
        [Tooltip("STUBBED — not written until the combat/leak system lands (Phase 1.4).")]
        private readonly NetworkVariable<int> lives = new NetworkVariable<int>(
            value: 0,
            readPerm: NetworkVariableReadPermission.Everyone,
            writePerm: NetworkVariableWritePermission.Server
        );

        /// <summary>STUBBED. Shared lives pool. Zero until the combat/leak system (Phase 1.4) writes it.</summary>
        public int Lives => lives.Value;

        // STUBBED — driven by the race-pick UI (Phase 1.8). Zero when no pick is in progress.
        [Tooltip("STUBBED — not driven until the race-pick system lands (Phase 1.8).")]
        private readonly NetworkVariable<float> racePickTimer = new NetworkVariable<float>(
            value: 0f,
            readPerm: NetworkVariableReadPermission.Everyone,
            writePerm: NetworkVariableWritePermission.Server
        );

        /// <summary>STUBBED. Seconds remaining in the race-pick countdown. Zero when no pick is in progress.</summary>
        public float RacePickTimer => racePickTimer.Value;

        /// <summary>
        /// Fired on every peer (server and clients) when the phase changes.
        /// Subscribe to react to phase transitions without polling.
        /// </summary>
        public event System.Action<MatchPhase, MatchPhase> OnPhaseChanged;

        // --- Lifecycle ---------------------------------------------------

        public override void OnNetworkSpawn()
        {
            if (Instance != null && Instance != this)
            {
                Debug.LogError("[MatchState] Duplicate MatchState detected — only one may exist per scene. " +
                               "Despawning the duplicate.");
                NetworkObject.Despawn();
                return;
            }

            Instance = this;
            phase.OnValueChanged += HandlePhaseChanged;

            Debug.Log($"[MatchState] Spawned. Phase={phase.Value}");
        }

        public override void OnNetworkDespawn()
        {
            phase.OnValueChanged -= HandlePhaseChanged;
            if (Instance == this) Instance = null;
        }

        // --- Server API --------------------------------------------------

        /// <summary>
        /// Transitions to a new phase. Server-only; no-op on clients with a log warning.
        /// </summary>
        public void SetPhase(MatchPhase next)
        {
            if (!IsServer) { Debug.LogWarning("[MatchState] SetPhase called on a client — ignored."); return; }
            if (phase.Value == next) return;
            phase.Value = next;
        }

        /// <summary>STUBBED. Sets the current wave index. Called by the wave system (Phase 1.5/1.6).</summary>
        public void SetCurrentWave(int wave)
        {
            if (!IsServer) { Debug.LogWarning("[MatchState] SetCurrentWave called on a client — ignored."); return; }
            currentWave.Value = wave;
        }

        /// <summary>STUBBED. Sets the shared lives pool. Called by the combat/leak system (Phase 1.4).</summary>
        public void SetLives(int value)
        {
            if (!IsServer) { Debug.LogWarning("[MatchState] SetLives called on a client — ignored."); return; }
            lives.Value = Mathf.Max(0, value);
        }

        /// <summary>STUBBED. Sets the race-pick countdown timer. Called by the race-pick system (Phase 1.8).</summary>
        public void SetRacePickTimer(float seconds)
        {
            if (!IsServer) { Debug.LogWarning("[MatchState] SetRacePickTimer called on a client — ignored."); return; }
            racePickTimer.Value = Mathf.Max(0f, seconds);
        }

        // --- Handlers ----------------------------------------------------

        private void HandlePhaseChanged(MatchPhase previous, MatchPhase current)
        {
            Debug.Log($"[MatchState] Phase: {previous} → {current}");
            OnPhaseChanged?.Invoke(previous, current);
        }
    }
}
