using System;
using UnityEngine;
using UnityEngine.Events;

public class ButtonSequenceDoorPuzzle : MonoBehaviour
{
    [Header("References")]
    [Tooltip("All available buttons for this puzzle.")]
    [SerializeField] private WallInteractButton[] buttons;

    [Tooltip("Door to open when the sequence is correct.")]
    [SerializeField] private SlidingDoor targetDoor;

    [Tooltip("Optional blocks controlled by this puzzle (reset with SetOff on start/wrong input).")]
    [SerializeField] private TestBlock[] puzzleBlocks;

    [Header("Sequence")]
    [Tooltip("Button indices (from the buttons array) that must be pressed in order. Example: 2,0,3")]
    [SerializeField] private int[] requiredSequence = { 0, 1, 2 };

    [Tooltip("If true, wrong input resets progress back to 0.")]
    [SerializeField] private bool resetOnWrongPress = true;

    [Tooltip("If true, puzzle can only be solved once.")]
    [SerializeField] private bool lockAfterSolved = true;

    [Header("Debug")]
    [SerializeField] private bool enableDebugLogs = true;

    private int m_progress;
    private bool m_isSolved;
    private UnityAction[] m_cachedListeners;

    private void OnEnable()
    {
        SetAllBlocksOff();
        RegisterAllButtons();
    }

    private void OnDisable()
    {
        UnregisterAllButtons();
    }

    private void RegisterAllButtons()
    {
        if (buttons == null)
            return;

        m_cachedListeners = new UnityAction[buttons.Length];

        for (int i = 0; i < buttons.Length; i++)
        {
            WallInteractButton button = buttons[i];
            if (button == null)
                continue;

            UnityAction action = () => OnButtonPressed(i);
            m_cachedListeners[i] = action;
            button.OnInteract.AddListener(action);
        }
    }

    private void UnregisterAllButtons()
    {
        if (buttons == null)
            return;

        for (int i = 0; i < buttons.Length; i++)
        {
            WallInteractButton button = buttons[i];
            if (button == null)
                continue;

            if (m_cachedListeners != null && i < m_cachedListeners.Length && m_cachedListeners[i] != null)
                button.OnInteract.RemoveListener(m_cachedListeners[i]);
        }

        m_cachedListeners = null;
        m_progress = 0;
    }

    private void OnButtonPressed(int buttonIndex)
    {
        Log($"Button pressed: index {buttonIndex}");

        if (m_isSolved && lockAfterSolved)
        {
            Log("Puzzle already solved and locked.");
            return;
        }

        if (!IsSequenceValid())
        {
            Log("Invalid sequence configuration.");
            return;
        }

        int expectedIndex = requiredSequence[m_progress];
        Log($"Expected button index: {expectedIndex} (step {m_progress + 1}/{requiredSequence.Length})");

        if (buttonIndex == expectedIndex)
        {
            m_progress++;
            Log($"Correct input. Progress: {m_progress}/{requiredSequence.Length}");

            if (m_progress >= requiredSequence.Length)
            {
                SolvePuzzle();
            }

            return;
        }

        if (resetOnWrongPress)
        {
            Log("Wrong input. Resetting sequence and turning puzzle blocks OFF.");
            m_progress = 0;
            SetAllBlocksOff();
            return;
        }

        Log("Wrong input, but resetOnWrongPress is disabled.");
    }

    private bool IsSequenceValid()
    {
        if (requiredSequence == null || requiredSequence.Length == 0)
            return false;

        if (buttons == null || buttons.Length == 0)
            return false;

        for (int i = 0; i < requiredSequence.Length; i++)
        {
            int index = requiredSequence[i];
            if (index < 0 || index >= buttons.Length)
                return false;
        }

        return true;
    }

    private void SolvePuzzle()
    {
        m_isSolved = true;
        m_progress = 0;
        Log("Sequence completed. Opening door.");

        if (targetDoor != null)
            targetDoor.Open();
    }

    private void SetAllBlocksOff()
    {
        if (puzzleBlocks == null)
            return;

        for (int i = 0; i < puzzleBlocks.Length; i++)
        {
            if (puzzleBlocks[i] == null)
                continue;

            puzzleBlocks[i].SetOff();
        }
    }

    private void Log(string message)
    {
        if (!enableDebugLogs)
            return;

        Debug.Log($"[{nameof(ButtonSequenceDoorPuzzle)}] {message}", this);
    }

#if UNITY_EDITOR
    private void OnValidate()
    {
        if (requiredSequence == null)
            return;

        for (int i = 0; i < requiredSequence.Length; i++)
        {
            requiredSequence[i] = Math.Max(0, requiredSequence[i]);
        }
    }
#endif
}
