using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace GameEngineI.Week07
{
    public enum RoundState { Ready, Playing, Won, Lost }

    // Week 5's collect -> goal / hazard -> start rules, with Week 7 screen states.
    [DefaultExecutionOrder(-200)]
    public sealed class Week07GameManager : MonoBehaviour
    {
        [Header("Rules")]
        [SerializeField, Min(1)] int targetScore = 3;
        [SerializeField, Min(1)] float roundDuration = 30f;
        [Header("Player")]
        [SerializeField] Rigidbody2D playerBody;
        [SerializeField] PlayerController movement;
        [SerializeField] PlayerDash dash;
        [SerializeField] PlayerAnimation animationDriver;
        [Header("UI")]
        [SerializeField] GameObject hud;
        [SerializeField] GameObject startPanel;
        [SerializeField] GameObject resultPanel;
        [SerializeField] TMP_Text scoreText;
        [SerializeField] TMP_Text timerText;
        [SerializeField] TMP_Text hintText;
        [SerializeField] TMP_Text resultText;
        [SerializeField] TMP_Text resultDetail;

        public RoundState CurrentState { get; private set; }
        public int Score { get; private set; }
        public int TargetScore => targetScore;
        public float TimeRemaining { get; private set; }
        public Vector2 SpawnPosition { get; private set; }
        float hintUntil;
        bool restarting;

        void Awake()
        {
            SpawnPosition = playerBody.position;
            Score = 0;
            TimeRemaining = roundDuration;
            CurrentState = RoundState.Ready;
            SetPlayerControl(false);
            Time.timeScale = 0;
            hud.SetActive(false);
            startPanel.SetActive(true);
            resultPanel.SetActive(false);
            RefreshHud();
        }

        void Update()
        {
            if (CurrentState != RoundState.Playing) return;
            TimeRemaining = Mathf.Max(0, TimeRemaining - Time.deltaTime);
            RefreshHud();
            if (TimeRemaining <= 0) Finish(RoundState.Lost);
            else if (playerBody.position.y < -6) Respawn();
        }

        public void StartRound()
        {
            if (CurrentState != RoundState.Ready) return;
            CurrentState = RoundState.Playing;
            startPanel.SetActive(false);
            resultPanel.SetActive(false);
            hud.SetActive(true);
            Time.timeScale = 1;
            SetPlayerControl(true);
            RefreshHud();
        }

        public bool TryCollect()
        {
            if (CurrentState != RoundState.Playing || Score >= targetScore) return false;
            Score++;
            hintUntil = 0;
            RefreshHud();
            // All gems unlock the goal; collecting the last gem does not end Week 5's level.
            return true;
        }

        public void TryGoal()
        {
            if (CurrentState != RoundState.Playing) return;
            if (Score < targetScore)
            {
                ShowHint($"Collect all {targetScore} gems before reaching the goal.");
                return;
            }
            Finish(RoundState.Won);
        }

        public void Respawn()
        {
            if (CurrentState != RoundState.Playing) return;
            SetPlayerControl(false);
            playerBody.position = SpawnPosition;
            playerBody.transform.position = new Vector3(SpawnPosition.x, SpawnPosition.y, playerBody.transform.position.z);
            playerBody.angularVelocity = 0;
            Physics2D.SyncTransforms();
            SetPlayerControl(true);
            ShowHint("Back at the start. Your collected gems are kept.");
        }

        public void RestartScene()
        {
            if (restarting || (CurrentState != RoundState.Won && CurrentState != RoundState.Lost)) return;
            restarting = true;
            Time.timeScale = 1;
            SceneManager.LoadScene(SceneManager.GetActiveScene().path);
        }

        void Finish(RoundState state)
        {
            if (CurrentState != RoundState.Playing) return;
            CurrentState = state;
            SetPlayerControl(false);
            Time.timeScale = 0;
            hud.SetActive(false);
            startPanel.SetActive(false);
            resultPanel.SetActive(true);
            resultText.text = state == RoundState.Won ? "Success" : "Time Up";
            resultDetail.text = state == RoundState.Won
                ? $"All {targetScore} gems collected. Goal reached!"
                : "Find your route and try again.";
        }

        void SetPlayerControl(bool active)
        {
            movement.enabled = active;
            dash.enabled = active;
            animationDriver.enabled = active;
            if (!active) playerBody.linearVelocity = Vector2.zero;
        }

        void ShowHint(string message)
        {
            hintUntil = Time.unscaledTime + 2.5f;
            hintText.text = message;
        }

        void RefreshHud()
        {
            scoreText.text = $"{Score} / {targetScore}";
            timerText.text = $"{TimeRemaining:0.0}";
            if (Time.unscaledTime >= hintUntil)
                hintText.text = Score >= targetScore
                    ? "All gems collected. Reach the goal!"
                    : $"Collect {targetScore} gems, then reach the goal.";
        }

        void OnDestroy()
        {
            // A reloaded scene establishes its own Ready pause in Awake.
            // The old manager must not unpause that new scene during teardown.
            if (!restarting) Time.timeScale = 1;
        }
    }
}
