using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// PreMatchIntroUI — "3 vs 3" matchup splash + countdown before gameplay.
///
/// Flow:
///   1. Show team info (displayDuration seconds)
///   2. Countdown: 3 → 2 → 1 → FIGHT!
///   3. Fade out, set IsComplete = true
///   4. CashSystemManager waits for IsComplete before enabling combat
///
/// Assign portrait Image slots in the Inspector. The script loads character
/// sprites into those Image components by team index.
///
/// Press Space (or skipButton) to skip intro → fast countdown then complete.
///
/// Uses CanvasGroup to hide (NOT SetActive(false)) so the script stays alive.
/// </summary>
public class PreMatchIntroUI : MonoBehaviour
{
    [Header("Panel")]
    [SerializeField] private GameObject rootPanel;

    [Header("Player Team (Left) — Assign portrait Image slots")]
    [SerializeField] private Image[]               playerPortraits = new Image[3];
    [SerializeField] private TextMeshProUGUI[]      playerNames     = new TextMeshProUGUI[3];

    [Header("Enemy Team (Right) — Assign portrait Image slots")]
    [SerializeField] private Image[]               enemyPortraits = new Image[3];
    [SerializeField] private TextMeshProUGUI[]      enemyNames     = new TextMeshProUGUI[3];

    [Header("Centre")]
    [SerializeField] private TextMeshProUGUI vsText;

    [Header("Countdown")]
    [Tooltip("Text element for countdown (3, 2, 1, FIGHT!)")]
    [SerializeField] private TextMeshProUGUI countdownText;

    [Header("Skip")]
    [Tooltip("Optional skip button — user can also press Space")]
    [SerializeField] private Button skipButton;
    [Tooltip("Text shown at bottom: 'Press Space to Skip'")]
    [SerializeField] private TextMeshProUGUI skipHintText;

    [Header("Game Mode Info (optional)")]
    [SerializeField] private TextMeshProUGUI modeTitle;
    [SerializeField] private TextMeshProUGUI objectiveText;

    [Header("Timing")]
    [SerializeField] private float displayDuration = 3.5f;
    [SerializeField] private float fadeInDuration  = 0.4f;
    [SerializeField] private float fadeOutDuration = 0.5f;
    [SerializeField] private float countdownStepTime = 1f;

    [Header("Audio")]
    [SerializeField] private AudioClip introSFX;
    [SerializeField] private AudioClip countdownBeepSFX;
    [SerializeField] private AudioClip fightSFX;
    [SerializeField] private float sfxVolume = 1f;

    [Header("Colors")]
    [SerializeField] private Color playerTeamColor = new Color(0.13f, 0.59f, 0.95f);
    [SerializeField] private Color enemyTeamColor  = new Color(0.96f, 0.26f, 0.21f);
    [SerializeField] private Color countdownColor  = Color.white;
    [SerializeField] private Color fightColor      = new Color(1f, 0.84f, 0f); // Gold

    // runtime
    private AudioSource _audio;
    private CanvasGroup _canvasGroup;
    private Coroutine   _sequenceCoroutine;
    private bool        _skipRequested;

    /// <summary>True once intro sequence (including countdown) is fully done.</summary>
    public bool IsComplete { get; private set; }

    private static PreMatchIntroUI _instance;
    public static PreMatchIntroUI Instance => _instance;

    /// <summary>
    /// Ensures a PreMatchIntroUI instance exists in the scene.
    /// Finds inactive instances first, or creates a minimal one on the existing Canvas.
    /// Call from CashSystemManager.Start() so the intro always works.
    /// </summary>
    public static void EnsureExists()
    {
        if (_instance != null) return;

        // 1. Try to find an inactive instance already in the scene
        PreMatchIntroUI[] all = Resources.FindObjectsOfTypeAll<PreMatchIntroUI>();
        foreach (var p in all)
        {
            // Skip assets (prefabs) — only want scene objects
            if (p.gameObject.scene.name == null) continue;
            // Activate parents top-down first, then the object itself
            // (Awake only fires when the ENTIRE chain is active)
            List<GameObject> chain = new List<GameObject>();
            Transform t = p.transform;
            while (t != null)
            {
                if (!t.gameObject.activeSelf)
                    chain.Add(t.gameObject);
                t = t.parent;
            }
            // Activate top-down
            for (int i = chain.Count - 1; i >= 0; i--)
                chain[i].SetActive(true);

            if (_instance != null)
            {
                Debug.Log("[PreMatchIntroUI] Found existing inactive panel, activated it");
                return;
            }
        }

        // 2. Create a minimal panel on an existing Canvas
        Canvas canvas = Object.FindObjectOfType<Canvas>();
        if (canvas == null)
        {
            GameObject canvasObj = new GameObject("UICanvas");
            canvas = canvasObj.AddComponent<Canvas>();
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            canvas.sortingOrder = 100;
            canvasObj.AddComponent<UnityEngine.UI.CanvasScaler>();
            canvasObj.AddComponent<UnityEngine.UI.GraphicRaycaster>();
        }

        GameObject panelRoot = new GameObject("PreMatchIntroUI_Auto");
        panelRoot.transform.SetParent(canvas.transform, false);

        // Stretch to fill canvas
        RectTransform rt = panelRoot.AddComponent<RectTransform>();
        rt.anchorMin = Vector2.zero;
        rt.anchorMax = Vector2.one;
        rt.offsetMin = Vector2.zero;
        rt.offsetMax = Vector2.zero;

        // Background image (dark overlay)
        Image bg = panelRoot.AddComponent<Image>();
        bg.color = new Color(0.05f, 0.05f, 0.1f, 0.85f);

        // Countdown text in centre
        GameObject textObj = new GameObject("CountdownText");
        textObj.transform.SetParent(panelRoot.transform, false);
        RectTransform trt = textObj.AddComponent<RectTransform>();
        trt.anchorMin = new Vector2(0.3f, 0.3f);
        trt.anchorMax = new Vector2(0.7f, 0.7f);
        trt.offsetMin = Vector2.zero;
        trt.offsetMax = Vector2.zero;
        TextMeshProUGUI txt = textObj.AddComponent<TextMeshProUGUI>();
        txt.text = "";
        txt.fontSize = 120;
        txt.alignment = TextAlignmentOptions.Center;
        txt.color = Color.white;

        // VS text
        GameObject vsObj = new GameObject("VSText");
        vsObj.transform.SetParent(panelRoot.transform, false);
        RectTransform vrt = vsObj.AddComponent<RectTransform>();
        vrt.anchorMin = new Vector2(0.35f, 0.55f);
        vrt.anchorMax = new Vector2(0.65f, 0.75f);
        vrt.offsetMin = Vector2.zero;
        vrt.offsetMax = Vector2.zero;
        TextMeshProUGUI vsTxt = vsObj.AddComponent<TextMeshProUGUI>();
        vsTxt.text = "VS";
        vsTxt.fontSize = 80;
        vsTxt.alignment = TextAlignmentOptions.Center;
        vsTxt.color = Color.yellow;

        PreMatchIntroUI intro = panelRoot.AddComponent<PreMatchIntroUI>();
        intro.countdownText = txt;
        intro.vsText = vsTxt;

        Debug.Log("[PreMatchIntroUI] Auto-created minimal intro panel on Canvas");
    }

    private void Awake()
    {
        _instance = this;
        if (rootPanel == null) rootPanel = gameObject;

        _audio = GetComponent<AudioSource>();
        if (_audio == null) _audio = gameObject.AddComponent<AudioSource>();
        _audio.playOnAwake = false;
        _audio.spatialBlend = 0f;

        _canvasGroup = rootPanel.GetComponent<CanvasGroup>();
        if (_canvasGroup == null) _canvasGroup = rootPanel.AddComponent<CanvasGroup>();

        // Hide via CanvasGroup — keep MonoBehaviour alive for Show() calls
        HideImmediate();

        // Wire skip button
        if (skipButton != null)
            skipButton.onClick.AddListener(Skip);
    }

    private void Update()
    {
        // Space key skip
        if (!IsComplete && Input.GetKeyDown(KeyCode.Space))
            _skipRequested = true;
    }

    // ─── Public API ──────────────────────────────────────────

    public void Show()
    {
        Debug.Log("[PreMatchIntroUI] Show() called");
        IsComplete = false;
        _skipRequested = false;

        rootPanel.SetActive(true);
        _canvasGroup.alpha = 0f;
        _canvasGroup.blocksRaycasts = true;
        _canvasGroup.interactable = true;

        // Populate from SelectionOptions
        string[] playerTeam = SelectionOptions.Instance != null ? SelectionOptions.Instance.playerTeam : null;
        string[] enemyTeam  = SelectionOptions.Instance != null ? SelectionOptions.Instance.enemyTeam  : null;

        PopulateSide(playerTeam, playerPortraits, playerNames, playerTeamColor);
        PopulateSide(enemyTeam,  enemyPortraits,  enemyNames,  enemyTeamColor);

        if (vsText != null) vsText.text = "VS";

        // Game mode info
        if (modeTitle != null) modeTitle.text = "CASH SYSTEM";
        if (objectiveText != null) objectiveText.text = "Collect cash and deposit it in your vault!";

        // Skip hint
        if (skipHintText != null) skipHintText.text = "Press Space to Skip";

        // Clear countdown at start
        if (countdownText != null) countdownText.text = "";

        // Play intro sound
        if (introSFX != null) _audio.PlayOneShot(introSFX, sfxVolume);

        // Start the full intro sequence (fade in → display → countdown → fade out)
        if (_sequenceCoroutine != null) StopCoroutine(_sequenceCoroutine);
        _sequenceCoroutine = StartCoroutine(IntroSequence());
    }

    /// <summary>Force hide — called if CashSystemManager needs to tear down early.</summary>
    public void Hide()
    {
        if (_sequenceCoroutine != null) StopCoroutine(_sequenceCoroutine);
        HideImmediate();
        IsComplete = true;
    }

    /// <summary>Skip the intro — jumps to fast countdown then completes.</summary>
    public void Skip()
    {
        _skipRequested = true;
    }

    // ─── Intro Sequence ──────────────────────────────────────

    private IEnumerator IntroSequence()
    {
        // Phase 1: Fade in
        yield return StartCoroutine(FadeIn());

        // Phase 2: Display team info for displayDuration (or until skip)
        float elapsed = 0f;
        while (elapsed < displayDuration && !_skipRequested)
        {
            elapsed += Time.unscaledDeltaTime;
            yield return null;
        }

        // Phase 3: Countdown (3, 2, 1, FIGHT!)
        // If skip was requested, do a fast countdown
        float stepTime = _skipRequested ? 0.25f : countdownStepTime;

        // Hide skip hint during countdown
        if (skipHintText != null) skipHintText.text = "";

        string[] steps = { "3", "2", "1", "FIGHT!" };
        foreach (string step in steps)
        {
            if (countdownText != null)
            {
                countdownText.text = step;
                countdownText.color = (step == "FIGHT!") ? fightColor : countdownColor;

                // Scale punch — make text pop
                countdownText.transform.localScale = Vector3.one * 1.5f;
                float scaleTimer = 0f;
                float scaleDuration = stepTime * 0.6f;
                while (scaleTimer < scaleDuration)
                {
                    scaleTimer += Time.unscaledDeltaTime;
                    float t = Mathf.Clamp01(scaleTimer / scaleDuration);
                    countdownText.transform.localScale = Vector3.Lerp(
                        Vector3.one * 1.5f, Vector3.one, t);
                    yield return null;
                }
                countdownText.transform.localScale = Vector3.one;
            }

            // Fire event so other systems (like existing countdown UI) can react
            GameEvents.FireCountdownTick(step);

            // SFX
            if (step == "FIGHT!")
            {
                if (fightSFX != null) _audio.PlayOneShot(fightSFX, sfxVolume);
            }
            else
            {
                if (countdownBeepSFX != null) _audio.PlayOneShot(countdownBeepSFX, sfxVolume);
            }

            // If skipping again during countdown, accelerate further
            if (_skipRequested) stepTime = 0.15f;

            yield return new WaitForSecondsRealtime(Mathf.Max(0.05f, stepTime - (stepTime * 0.6f)));
        }

        // Brief hold on "FIGHT!" before fading
        yield return new WaitForSecondsRealtime(_skipRequested ? 0.2f : 0.8f);

        // Clear countdown text
        if (countdownText != null) countdownText.text = "";
        GameEvents.FireCountdownTick("");

        // Phase 4: Fade out
        yield return StartCoroutine(FadeOut());

        // Done — CashSystemManager checks this to enable combat
        IsComplete = true;
        Debug.Log("[PreMatchIntroUI] Intro complete");
    }

    // ─── Population ──────────────────────────────────────────

    private void PopulateSide(string[] names, Image[] portraits, TextMeshProUGUI[] labels, Color teamColor)
    {
        bool isPlayerSide = (portraits == playerPortraits);
        string sideLabel = isPlayerSide ? "Player" : "Enemy";

        // Get portrait sprites stored from the selection screen (via SelectionOptions)
        Sprite[] teamSprites = null;
        if (SelectionOptions.Instance != null)
            teamSprites = isPlayerSide
                ? SelectionOptions.Instance.playerTeamSprites
                : SelectionOptions.Instance.enemyTeamSprites;

        Debug.Log($"[PreMatchIntroUI] PopulateSide({sideLabel}) — names: {(names != null ? string.Join(", ", names) : "null")}, sprites: {(teamSprites != null ? teamSprites.Length.ToString() : "null")}");

        for (int i = 0; i < 3; i++)
        {
            bool hasChar = names != null && i < names.Length && !string.IsNullOrEmpty(names[i]);

            if (portraits != null && i < portraits.Length && portraits[i] != null)
            {
                if (hasChar)
                {
                    // Use the sprite stored from the selection screen
                    Sprite portrait = (teamSprites != null && i < teamSprites.Length) ? teamSprites[i] : null;

                    if (portrait != null)
                    {
                        portraits[i].sprite = portrait;
                        portraits[i].color  = Color.white;
                        portraits[i].preserveAspect = true;
                        Debug.Log($"[PreMatchIntroUI] {sideLabel}[{i}] portrait set for {names[i]} ({portrait.name})");
                    }
                    else
                    {
                        portraits[i].color = teamColor * 0.6f;
                        Debug.LogWarning($"[PreMatchIntroUI] {sideLabel}[{i}] no portrait for {names[i]}, using team color");
                    }
                    portraits[i].gameObject.SetActive(true);
                }
                else
                {
                    portraits[i].gameObject.SetActive(false);
                }
            }

            if (labels != null && i < labels.Length && labels[i] != null)
            {
                labels[i].text  = hasChar ? names[i].ToUpper() : "";
                labels[i].color = teamColor;
            }
        }
    }

    // ─── Fade / Hide ─────────────────────────────────────────

    private void HideImmediate()
    {
        _canvasGroup.alpha = 0f;
        _canvasGroup.blocksRaycasts = false;
        _canvasGroup.interactable = false;
    }

    private IEnumerator FadeIn()
    {
        float elapsed = 0f;
        while (elapsed < fadeInDuration)
        {
            elapsed += Time.unscaledDeltaTime;
            _canvasGroup.alpha = Mathf.Clamp01(elapsed / fadeInDuration);
            yield return null;
        }
        _canvasGroup.alpha = 1f;
    }

    private IEnumerator FadeOut()
    {
        float elapsed = 0f;
        float startAlpha = _canvasGroup.alpha;
        while (elapsed < fadeOutDuration)
        {
            elapsed += Time.unscaledDeltaTime;
            _canvasGroup.alpha = Mathf.Lerp(startAlpha, 0f, elapsed / fadeOutDuration);
            yield return null;
        }
        HideImmediate();
    }
}
