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

/// <summary>
/// GAME 1303 Tier 6 — Shows "Press E to Examine" over the nearest Interactable and
/// handles the button press. ONE of these on the player covers the whole game.
///
/// SETUP
///  1. Add to the player object.
///  2. Input: add an "Interact" Button action to the Player map (E key, gamepad South/A).
///     This listens for OnInteract.
///  3. Prompt UI: make a small world-space Canvas prefab with a TMP text (and optionally
///     a key icon), drag it into Prompt Prefab. It's spawned once and moved around.
///     If you'd rather use a screen-space UI, drag an existing object into Prompt Instance
///     and tick Screen Space — it will just show/hide and set the text.
///  4. When several interactables overlap, the closest one wins.
///  5. Block While Dialogue Open is on by default so pressing E to advance dialogue
///     doesn't also re-trigger the thing you're talking to.
/// </summary>
public class InteractionPrompt : MonoBehaviour
{
    [Header("Prompt UI")]
    public GameObject promptPrefab;
    public GameObject promptInstance;
    public bool screenSpace = false;
    public string format = "[E] {0}";

    [Header("Rules")]
    public bool blockWhileDialogueOpen = true;

    private static readonly List<Interactable> inRange = new List<Interactable>();
    private TMP_Text promptLabel;
    private Interactable current;

    public static void Register(Interactable i)   { if (!inRange.Contains(i)) inRange.Add(i); }
    public static void Unregister(Interactable i) { inRange.Remove(i); }

    void Awake()
    {
        if (promptInstance == null && promptPrefab != null)
            promptInstance = Instantiate(promptPrefab);
        if (promptInstance != null)
        {
            promptLabel = promptInstance.GetComponentInChildren<TMP_Text>();
            promptInstance.SetActive(false);
        }
    }

    void OnDestroy() => inRange.Clear();

    void Update()
    {
        inRange.RemoveAll(i => i == null);
        current = Closest();

        bool show = current != null && !DialogueBlocked();
        if (promptInstance != null)
        {
            if (promptInstance.activeSelf != show) promptInstance.SetActive(show);
            if (show)
            {
                if (promptLabel != null) promptLabel.text = string.Format(format, current.promptText);
                if (!screenSpace) promptInstance.transform.position = current.PromptPosition;
            }
        }
    }

    Interactable Closest()
    {
        Interactable best = null;
        float bestDist = float.MaxValue;
        foreach (var i in inRange)
        {
            if (i == null || !i.IsAvailable) continue;
            float d = Vector2.Distance(transform.position, i.transform.position);
            if (d < bestDist) { bestDist = d; best = i; }
        }
        return best;
    }

    bool DialogueBlocked() => blockWhileDialogueOpen && DialogueRunner.IsAnyOpen;

    void OnInteract(InputValue value)
    {
        if (!value.isPressed) return;

        // Dialogue takes priority: the same key advances the conversation
        if (DialogueRunner.IsAnyOpen) { DialogueRunner.Active?.Advance(); return; }

        if (current != null) current.Interact();
    }
}