using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class CableMiniGame : MonoBehaviour, ITask
{
    [System.Serializable]
    public class Cable
    {
        public string colorName;
        public Button sourceButton;
        public Button targetButton;

        [HideInInspector] public bool connected;

        // Line UI
        [HideInInspector] public GameObject lineObject;
        [HideInInspector] public RectTransform lineRect;
        [HideInInspector] public Image lineImage;
    }

    public string TaskID { get; set; }
    public TaskType TaskType { get; set; }
    public string TaskName { get; set; }
    public (double, double) TaskLocation { get; set; }
    public bool IsCompleted { get; private set; }

    private Action<ITask> _onCompleted;
    private Action<ITask> _onExit;

    [Header("MiniGame Settings")]
    public Cable[] cables;
    public Canvas canvas; // Assign your Canvas here in the inspector
    public string previousSceneName;
    public Color wrongAttemptColor = Color.white;
    public float blinkDuration = 0.2f;
    public float cableWidth = 5f;

    private string selectedColor = null;

    // ------------------------------
    // Initialization / ITask Methods
    // ------------------------------

    public void Initialize(Action<ITask> onCompleted)
    {
        Debug.Log("[Init] Initializing mini game...");
        IsCompleted = false;
        _onCompleted = onCompleted;

        foreach (var cable in cables)
        {
            cable.connected = false;
        }

        PrintAllCableStates("After Initialization");
    }

    public void Complete()
    {
        if (IsCompleted) return;

        IsCompleted = true;
        Debug.Log("[Complete] Task completed successfully!");
        _onCompleted?.Invoke(this);
        ExitTask(_onExit);
    }

    public void ExitTask(Action<ITask> onExit)
    {
        Debug.Log("[ExitTask] Exiting task...");
        onExit?.Invoke(this);
    }

    // ------------------------------
    // Unity Lifecycle
    // ------------------------------

    void Start()
    {
        if (canvas == null)
            canvas = FindObjectOfType<Canvas>();

        if (canvas == null)
            Debug.LogError("[CableMiniGame] No Canvas found in scene!");

        foreach (var cable in cables)
        {
            Cable localCable = cable;
            cable.sourceButton.onClick.AddListener(() => OnSourceClicked(localCable));
            cable.targetButton.onClick.AddListener(() => OnTargetClicked(localCable));
        }

        PrintAllCableStates("At Start");
    }

    // ------------------------------
    // Button Handlers
    // ------------------------------

    void OnSourceClicked(Cable cable)
    {
        Debug.Log($"[SourceClick] Clicked source of cable '{cable.colorName}'");
        if (cable.connected)
        {
            Debug.Log($"[SourceClick] Cable '{cable.colorName}' is already connected, ignoring.");
            return;
        }

        selectedColor = cable.colorName;
        Debug.Log($"[SourceClick] Selected color set to '{selectedColor}'");
        PrintAllCableStates("After Source Click");
    }

    void OnTargetClicked(Cable cable)
    {
        Debug.Log($"[TargetClick] Clicked target of cable '{cable.colorName}'");

        if (selectedColor == null)
        {
            Debug.Log("[TargetClick] No color selected, ignoring click.");
            return;
        }

        if (cable.connected)
        {
            Debug.Log($"[TargetClick] Cable '{cable.colorName}' already connected, ignoring click.");
            return;
        }

        if (selectedColor == cable.colorName)
        {
            cable.connected = true;
            Debug.Log($"[TargetClick] Correct connection! '{selectedColor}' connected successfully.");

            CreateLineUI(cable);
            DrawLine(cable);

            PrintAllCableStates("After Correct Connection");
            CheckCompletion();
        }
        else
        {
            Debug.Log($"[TargetClick] Wrong connection attempt! Selected: '{selectedColor}', Target: '{cable.colorName}'");
            PrintAllCableStates("Before BlinkAndExit");
            StartCoroutine(BlinkAndExit(cable));
        }

        selectedColor = null;
        Debug.Log("[TargetClick] Reset selected color to null");
    }

    // ------------------------------
    // Cable Rendering
    // ------------------------------

    private void CreateLineUI(Cable cable)
    {
        if (cable.lineObject != null) return;

        GameObject lineGO = new GameObject($"Line_{cable.colorName}");
        lineGO.transform.SetParent(canvas.transform, false);
        lineGO.transform.SetAsLastSibling();

        Image img = lineGO.AddComponent<Image>();
        img.color = Color.white;
        img.raycastTarget = false;

        RectTransform rt = lineGO.GetComponent<RectTransform>();
        rt.pivot = new Vector2(0, 0.5f);
        rt.localScale = Vector3.one;
        rt.sizeDelta = new Vector2(0, cableWidth);
        rt.localPosition = Vector3.zero;

        cable.lineObject = lineGO;
        cable.lineRect = rt;
        cable.lineImage = img;

        lineGO.SetActive(false);
    }

    private void DrawLine(Cable cable)
    {
        if (!cable.connected || cable.lineRect == null) return;

        RectTransform canvasRect = canvas.transform as RectTransform;
        Vector2 startPos, endPos;

        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            canvasRect,
            cable.sourceButton.transform.position,
            canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera,
            out startPos
        );

        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            canvasRect,
            cable.targetButton.transform.position,
            canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera,
            out endPos
        );

        Vector2 diff = endPos - startPos;
        float distance = diff.magnitude;

        cable.lineRect.sizeDelta = new Vector2(distance, cableWidth);
        cable.lineRect.anchoredPosition = startPos;
        cable.lineRect.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg);

        cable.lineImage.color = GetColorFromName(cable.colorName);
        cable.lineObject.SetActive(true);
    }

    // ------------------------------
    // Completion Check
    // ------------------------------

    void CheckCompletion()
    {
        foreach (var cable in cables)
        {
            if (!cable.connected)
            {
                Debug.Log($"[CheckCompletion] Cable '{cable.colorName}' not yet connected.");
                return;
            }
        }

        Debug.Log("[CheckCompletion] All cables connected!");
        Complete();
    }

    // ------------------------------
    // Helpers
    // ------------------------------

    Color GetColorFromName(string name)
    {
        switch (name.ToLower())
        {
            case "red": return Color.red;
            case "blue": return Color.blue;
            case "green": return Color.green;
            case "yellow": return Color.yellow;
            default: return Color.white;
        }
    }

    IEnumerator BlinkAndExit(Cable cable)
    {
        if (cable.lineObject == null) CreateLineUI(cable);
        if (cable.lineImage == null)
        {
            Debug.LogWarning("[BlinkAndExit] No lineImage, skipping blink.");
            ExitTask(_onExit);
            yield break;
        }

        Debug.Log("[BlinkAndExit] Wrong attempt, blinking...");
        Color original = cable.lineImage.color;
        cable.lineImage.color = wrongAttemptColor;

        yield return new WaitForSeconds(blinkDuration);

        cable.lineImage.color = original;
        Debug.Log("[BlinkAndExit] Restored original color, exiting task.");

        ExitTask(_onExit);
        // NOTE: no SceneManager.LoadScene here — TaskManager handles unloading
    }

    void PrintAllCableStates(string context)
    {
        string states = $"[CableStates] {context} => ";
        foreach (var cable in cables)
        {
            states += $"'{cable.colorName}': {(cable.connected ? "Connected" : "Not Connected")}, ";
        }
        Debug.Log(states.TrimEnd(' ', ','));
    }
}