using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// GAME 1303 Tier 6 — "Press E." A thing in the world the player can examine, talk to,
/// pick up, or operate. Anabasis, Detective Liz (clues), Commission Witch (order board),
/// Cozy Critters, Store Simulator.
///
/// SETUP
///  1. Object + Collider2D (Is Trigger) sized to how close the player must stand + this script.
///  2. Prompt Text: what the little floating label says ("Examine", "Talk", "Pick up").
///  3. Wire OnInteract to whatever should happen: DialogueRunner.StartDialogue,
///     Door.Open, ChoiceFlagManager.SetFlag, an animation, a sound.
///  4. One Shot: can only be used once (a note you read, an item you take).
///  5. Require Flag / Blocked By Flag: gate an interaction on story state, e.g. a locked
///     desk that only works once you have "found_key".
///  6. The player needs an InteractionPrompt component (see the other script) — one on the
///     player object handles every interactable in the game.
///
/// This is the single most reusable script in the narrative tier: almost every "something
/// happens when the player does a thing here" moment is an Interactable plus a UnityEvent.
/// </summary>
[RequireComponent(typeof(Collider2D))]
public class Interactable : MonoBehaviour
{
    [Header("Prompt")]
    public string promptText = "Examine";
    [Tooltip("Where the floating prompt appears. Leave empty for just above this object.")]
    public Transform promptAnchor;
    public Vector2 promptOffset = new Vector2(0f, 1f);

    [Header("Rules")]
    public bool oneShot = false;
    [Tooltip("Flags required (comma separated; prefix ! to require NOT set).")]
    public string requireFlags = "";
    [Tooltip("Set this flag when interacted with. Leave blank for none.")]
    public string setFlagOnInteract = "";
    public bool startEnabled = true;

    [Header("Feedback")]
    public string sfxName = "";
    public Sprite usedSprite;

    [Header("Events")]
    public UnityEvent OnInteract;
    public UnityEvent OnBecameAvailable;
    public UnityEvent OnPlayerEntered;
    public UnityEvent OnPlayerExited;

    public bool Used { get; private set; }
    public bool IsAvailable => startEnabled && enabled && !(oneShot && Used) && FlagsOk();

    public Vector3 PromptPosition =>
        (promptAnchor != null ? promptAnchor.position : transform.position) + (Vector3)promptOffset;

    void Reset() { GetComponent<Collider2D>().isTrigger = true; }

    bool FlagsOk()
    {
        if (string.IsNullOrWhiteSpace(requireFlags)) return true;
        return ChoiceFlagManager.Instance == null || ChoiceFlagManager.Instance.HasAll(requireFlags);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (!other.CompareTag("Player")) return;
        InteractionPrompt.Register(this);
        OnPlayerEntered?.Invoke();
    }

    void OnTriggerExit2D(Collider2D other)
    {
        if (!other.CompareTag("Player")) return;
        InteractionPrompt.Unregister(this);
        OnPlayerExited?.Invoke();
    }

    void OnDisable() => InteractionPrompt.Unregister(this);

    /// <summary>Called by InteractionPrompt when the player presses the interact button.</summary>
    public void Interact()
    {
        if (!IsAvailable) return;
        Used = true;

        if (!string.IsNullOrEmpty(sfxName)) AudioManager.Instance?.PlaySFX(sfxName);
        if (!string.IsNullOrEmpty(setFlagOnInteract)) ChoiceFlagManager.Instance?.SetFlag(setFlagOnInteract);

        if (usedSprite != null)
        {
            var sr = GetComponentInChildren<SpriteRenderer>();
            if (sr != null) sr.sprite = usedSprite;
        }

        OnInteract?.Invoke();

        if (oneShot) InteractionPrompt.Unregister(this);
    }

    /// <summary>Turn an interactable on later in the story.</summary>
    public void SetAvailable(bool available)
    {
        startEnabled = available;
        if (available) OnBecameAvailable?.Invoke();
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(PromptPosition, 0.15f);
    }
}