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

public class RobotBootSequence : MonoBehaviour
{
    [Header("References")]
    public PlayerInputController InputController;
    public Transform CameraTransform;

    [Header("Timing")]
    public bool PlayOnStart = true;
    [Min(0.1f)] public float BootDuration = 2.4f;
    [Min(0.1f)] public float CharacterPerSecond = 40f;
    [Min(0f)] public float LinePause = 0.35f;
    [Min(0f)] public float DelayBeforeReveal = 0.4f;

    [Header("Motion")]
    public Vector2 StartYawPitch = new Vector2(-30f, -20f);
    public float RollWobble = 2.5f;
    public float WobbleFrequency = 16f;
    public AnimationCurve EaseCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);

    [Header("Boot Text")]
    public Color BootTextColor = new Color(0.62f, 1f, 0.7f, 1f);
    public string[] BootLines =
    {
        "UNIT SB-3954 | preparing startup . . .",
        "verification of OS-5 . . . 4 . . . 3 . . . 2 . . . 1",
        "system integrity: OK",
        "motor bus: OK",
        "vision pipeline: ONLINE",
        "SYSTEM OK"
    };

    [Header("Optional Audio")]
    public AudioSource BootAudioSource;

    private bool m_IsPlaying;

    private struct BootUI
    {
        public Canvas Canvas;
        public RectTransform LeftPanel;
        public RectTransform RightPanel;
        public TextMeshProUGUI Text;
    }

    private void Awake()
    {
        if (InputController == null)
        {
            InputController = GetComponent<PlayerInputController>();
        }
    }

    private void Start()
    {
        if (PlayOnStart)
        {
            StartCoroutine(PlayBootSequence());
        }
    }

    [ContextMenu("Play Boot Sequence")]
    public void PlayBootSequenceFromMenu()
    {
        if (!Application.isPlaying || m_IsPlaying)
        {
            return;
        }

        StartCoroutine(PlayBootSequence());
    }

    public IEnumerator PlayBootSequence()
    {
        if (m_IsPlaying)
        {
            yield break;
        }

        m_IsPlaying = true;

        if (InputController != null)
        {
            InputController.SetInputEnabled(false);
        }

        if (BootAudioSource != null)
        {
            BootAudioSource.Play();
        }

        if (CameraTransform == null)
        {
            m_IsPlaying = false;
            if (InputController != null)
            {
                InputController.SetInputEnabled(true);
            }
            yield break;
        }

        Quaternion gameplayRotation = CameraTransform.localRotation;
        Quaternion fromRotation = Quaternion.Euler(StartYawPitch.y, StartYawPitch.x, 0f) * gameplayRotation;
        CameraTransform.localRotation = fromRotation;

        BootUI bootUI = CreateBootUI();

        yield return StartCoroutine(PlayBootText(bootUI.Text));

        if (DelayBeforeReveal > 0f)
        {
            yield return new WaitForSeconds(DelayBeforeReveal);
        }

        float elapsed = 0f;
        while (elapsed < BootDuration)
        {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / BootDuration);
            float eased = EaseCurve.Evaluate(t);

            float wobbleFade = 1f - eased;
            float roll = Mathf.Sin(Time.time * WobbleFrequency) * RollWobble * wobbleFade;
            Quaternion wobbleRotation = Quaternion.Euler(0f, 0f, roll);

            CameraTransform.localRotation = Quaternion.Slerp(fromRotation, gameplayRotation, eased) * wobbleRotation;

            RectTransform rootRect = bootUI.Canvas.GetComponent<RectTransform>();
            float halfWidth = rootRect.rect.width * 0.5f;
            float leftTarget = -(halfWidth + 24f);
            float rightTarget = halfWidth + 24f;
            bootUI.LeftPanel.anchoredPosition = new Vector2(Mathf.Lerp(0f, leftTarget, eased), 0f);
            bootUI.RightPanel.anchoredPosition = new Vector2(Mathf.Lerp(0f, rightTarget, eased), 0f);

            Color textColor = bootUI.Text.color;
            textColor.a = 1f - eased;
            bootUI.Text.color = textColor;

            yield return null;
        }

        CameraTransform.localRotation = gameplayRotation;

        if (bootUI.Canvas != null)
        {
            Destroy(bootUI.Canvas.gameObject);
        }

        if (InputController != null)
        {
            InputController.SetInputEnabled(true);
        }

        m_IsPlaying = false;
    }

    private IEnumerator PlayBootText(TextMeshProUGUI label)
    {
        if (label == null || BootLines == null || BootLines.Length == 0)
        {
            yield break;
        }

        label.text = string.Empty;
        float charDelay = CharacterPerSecond <= 0f ? 0f : 1f / CharacterPerSecond;

        for (int i = 0; i < BootLines.Length; i++)
        {
            string line = BootLines[i];
            for (int c = 0; c < line.Length; c++)
            {
                label.text += line[c];
                if (charDelay > 0f)
                {
                    yield return new WaitForSeconds(charDelay);
                }
            }

            if (i < BootLines.Length - 1)
            {
                label.text += "\n";
            }

            if (LinePause > 0f)
            {
                yield return new WaitForSeconds(LinePause);
            }
        }
    }

    private BootUI CreateBootUI()
    {
        BootUI ui = new BootUI();

        GameObject canvasGO = new GameObject("RobotBootCanvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
        Canvas canvas = canvasGO.GetComponent<Canvas>();
        canvas.renderMode = RenderMode.ScreenSpaceOverlay;
        canvas.sortingOrder = 5000;

        CanvasScaler scaler = canvasGO.GetComponent<CanvasScaler>();
        scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        scaler.referenceResolution = new Vector2(1920f, 1080f);
        scaler.matchWidthOrHeight = 0.5f;

        RectTransform root = canvasGO.GetComponent<RectTransform>();
        root.anchorMin = Vector2.zero;
        root.anchorMax = Vector2.one;
        root.offsetMin = Vector2.zero;
        root.offsetMax = Vector2.zero;

        RectTransform leftPanel = CreatePanel("LeftPanel", root, true);
        RectTransform rightPanel = CreatePanel("RightPanel", root, false);
        TextMeshProUGUI label = CreateBootLabel(root);

        ui.Canvas = canvas;
        ui.LeftPanel = leftPanel;
        ui.RightPanel = rightPanel;
        ui.Text = label;

        return ui;
    }

    private RectTransform CreatePanel(string panelName, RectTransform parent, bool isLeft)
    {
        GameObject panelGO = new GameObject(panelName, typeof(RectTransform), typeof(Image));
        RectTransform rect = panelGO.GetComponent<RectTransform>();
        rect.SetParent(parent, false);
        rect.anchorMin = isLeft ? new Vector2(0f, 0f) : new Vector2(0.5f, 0f);
        rect.anchorMax = isLeft ? new Vector2(0.5f, 1f) : new Vector2(1f, 1f);
        rect.pivot = new Vector2(0.5f, 0.5f);
        rect.offsetMin = Vector2.zero;
        rect.offsetMax = Vector2.zero;
        rect.anchoredPosition = Vector2.zero;

        Image image = panelGO.GetComponent<Image>();
        image.color = Color.black;

        return rect;
    }

    private TextMeshProUGUI CreateBootLabel(RectTransform parent)
    {
        GameObject textGO = new GameObject("BootText", typeof(RectTransform), typeof(TextMeshProUGUI));
        RectTransform rect = textGO.GetComponent<RectTransform>();
        rect.SetParent(parent, false);
        rect.anchorMin = new Vector2(0.13f, 0.5f);
        rect.anchorMax = new Vector2(0.13f, 0.5f);
        rect.pivot = new Vector2(0f, 0.5f);
        rect.sizeDelta = new Vector2(980f, 380f);

        TextMeshProUGUI text = textGO.GetComponent<TextMeshProUGUI>();
        text.text = string.Empty;
        text.fontSize = 40f;
        text.alignment = TextAlignmentOptions.Left;
        text.color = BootTextColor;
        text.textWrappingMode = TextWrappingModes.Normal;

        return text;
    }
}
