using UnityEngine;
using UnityEngine.Events;
using TMPro;

/// <summary>
/// GAME 1303 Tier 4 — Times the run, shows it, and saves the best. Zap Attack's time
/// attack; optional for Cutthroat Course.
///
/// SETUP
///  1. Empty GameObject "LevelTimer" with this script (or put it on your HUD).
///  2. Level Id: must match the LevelData asset for this scene, or the best time saves
///     under the wrong key. Leave blank to use the scene name.
///  3. Drag in TMP texts for the running timer and the best time (both optional).
///  4. Mode:
///       CountUp   – classic speedrun timer.
///       CountDown – set Start Time; OnTimedOut fires at zero (wire to Health.Kill or
///                   GameManager.GameOver). Nicholas explicitly wants NO time limit,
///                   so his stays CountUp or off entirely.
///  5. Stopping: wire LevelExit.OnCompleted -> LevelTimer.StopAndRecord. That saves the
///     best time and fires OnNewRecord if it beat the old one.
///  6. Auto Start runs from scene load; otherwise call StartTimer() (a starting-line trigger).
///
/// The timer pauses automatically while GameManager is paused, because it uses
/// Time.deltaTime and pausing sets timeScale to 0.
/// </summary>
public class LevelTimer : MonoBehaviour
{
    public enum Mode { CountUp, CountDown }

    public Mode mode = Mode.CountUp;
    [Tooltip("Match the LevelData asset's Level Id. Blank = use the scene name.")]
    public string levelId = "";
    public bool autoStart = true;
    [Tooltip("CountDown mode: seconds on the clock.")]
    public float startTime = 60f;

    [Header("Display (optional)")]
    public TMP_Text timerText;
    public TMP_Text bestTimeText;
    public string bestTimePrefix = "Best: ";
    [Tooltip("Turn the timer red under this many seconds (CountDown).")]
    public float warningThreshold = 10f;
    public Color warningColor = Color.red;

    [Header("Events")]
    public UnityEvent OnTimedOut;
    public UnityEvent<float> OnNewRecord;   // the new best time
    public UnityEvent<float> OnStopped;     // final time either way

    public float Time_ { get; private set; }
    public bool IsRunning { get; private set; }

    private Color normalColor = Color.white;
    private bool timedOut;

    void Awake()
    {
        if (string.IsNullOrEmpty(levelId))
            levelId = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
        if (timerText != null) normalColor = timerText.color;
    }

    void Start()
    {
        Time_ = mode == Mode.CountDown ? startTime : 0f;
        ShowBest();
        Display();
        if (autoStart) StartTimer();
    }

    void Update()
    {
        if (!IsRunning) return;

        Time_ += (mode == Mode.CountDown ? -1f : 1f) * Time.deltaTime;

        if (mode == Mode.CountDown && Time_ <= 0f)
        {
            Time_ = 0f;
            IsRunning = false;
            timedOut = true;
            OnTimedOut?.Invoke();
        }
        Display();
    }

    public void StartTimer()
    {
        timedOut = false;
        IsRunning = true;
    }

    public void PauseTimer() => IsRunning = false;

    /// <summary>Wire LevelExit.OnCompleted here.</summary>
    public void StopAndRecord()
    {
        if (timedOut) return;
        IsRunning = false;

        float finalTime = mode == Mode.CountDown ? startTime - Time_ : Time_;
        bool record = LevelProgress.IsNewRecord(levelId, finalTime);

        LevelProgress.MarkCleared(levelId);
        LevelProgress.RecordTime(levelId, finalTime);
        ShowBest();

        if (record) OnNewRecord?.Invoke(finalTime);
        OnStopped?.Invoke(finalTime);
    }

    void Display()
    {
        if (timerText == null) return;
        timerText.text = Format(Time_);
        timerText.color = (mode == Mode.CountDown && Time_ <= warningThreshold) ? warningColor : normalColor;
    }

    void ShowBest()
    {
        if (bestTimeText == null) return;
        float best = LevelProgress.GetBestTime(levelId);
        bestTimeText.text = best < 0f ? bestTimePrefix + "--:--.--" : bestTimePrefix + Format(best);
    }

    /// <summary>mm:ss.hh — the standard speedrun readout.</summary>
    public static string Format(float t)
    {
        if (t < 0f) t = 0f;
        int minutes = (int)(t / 60f);
        int seconds = (int)(t % 60f);
        int hundredths = (int)((t * 100f) % 100f);
        return $"{minutes:00}:{seconds:00}.{hundredths:00}";
    }
}