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

/// <summary>
/// GAME 1303 Tier 6 — A list of what the player has found out. Detective Liz's case notes,
/// Anabasis's recovered memories.
///
/// SETUP
///  1. Empty GameObject + this script (tick Persist Across Scenes if the case spans scenes).
///  2. Make a Clue entry per discoverable fact: an id, a title, and the text.
///  3. Discover one from any Interactable: OnInteract -> ClueJournal.Discover, then type
///     the clue id in the string field.
///  4. Optional UI: drag in a panel, a TMP text, and a Clue Entry Prefab (a TMP text) and
///     it will list everything found. Toggle the panel with a UI button or the "Journal"
///     input action.
///  5. Each discovered clue also sets the flag "clue_<id>", so dialogue lines and endings
///     can react with Require Flags — that's how "ask the ghost about the locked room"
///     appears only after you found the room.
///
/// The count is what makes an investigation feel like progress: OnClueCountChanged
/// drives a "4 / 9 clues" HUD readout.
/// </summary>
public class ClueJournal : MonoBehaviour
{
    public static ClueJournal Instance { get; private set; }

    [System.Serializable]
    public class Clue
    {
        public string id = "clue_1";
        public string title = "A torn photograph";
        [TextArea(2, 5)] public string text = "";
        public Sprite icon;
        [Tooltip("Which floor / chapter this belongs to, for grouping. Optional.")]
        public string category = "";
    }

    public bool persistAcrossScenes = true;
    public List<Clue> allClues = new List<Clue>();

    [Header("UI (optional)")]
    public GameObject panel;
    public Transform entryContainer;
    public TMP_Text entryPrefab;
    public TMP_Text counterText;
    public string counterFormat = "{0} / {1} clues";

    [Header("Feedback")]
    public string discoverSfx = "clue_found";

    [Header("Events")]
    public UnityEvent<string> OnClueDiscovered;    // clue id
    public UnityEvent<int, int> OnClueCountChanged; // (found, total)
    public UnityEvent OnAllCluesFound;

    private readonly HashSet<string> found = new HashSet<string>();

    public int FoundCount => found.Count;
    public int TotalCount => allClues.Count;

    void Awake()
    {
        if (Instance != null && Instance != this) { Destroy(gameObject); return; }
        Instance = this;
        if (persistAcrossScenes) DontDestroyOnLoad(gameObject);
        if (panel != null) panel.SetActive(false);
    }

    void Start() => OnClueCountChanged?.Invoke(FoundCount, TotalCount);

    /// <summary>Wire an Interactable's OnInteract here and type the clue id.</summary>
    public void Discover(string clueId)
    {
        if (string.IsNullOrEmpty(clueId) || !found.Add(clueId)) return;

        ChoiceFlagManager.Instance?.SetFlag("clue_" + clueId);
        if (!string.IsNullOrEmpty(discoverSfx)) AudioManager.Instance?.PlaySFX(discoverSfx);

        OnClueDiscovered?.Invoke(clueId);
        OnClueCountChanged?.Invoke(FoundCount, TotalCount);
        if (FoundCount >= TotalCount && TotalCount > 0) OnAllCluesFound?.Invoke();

        if (panel != null && panel.activeSelf) Rebuild();
    }

    public bool HasFound(string clueId) => found.Contains(clueId);

    public Clue GetClue(string clueId) => allClues.Find(c => c.id == clueId);

    public void TogglePanel()
    {
        if (panel == null) return;
        bool show = !panel.activeSelf;
        panel.SetActive(show);
        if (show) Rebuild();
    }

    void Rebuild()
    {
        if (entryContainer == null || entryPrefab == null) return;

        foreach (Transform child in entryContainer) Destroy(child.gameObject);

        foreach (var clue in allClues)
        {
            if (!found.Contains(clue.id)) continue;
            var entry = Instantiate(entryPrefab, entryContainer);
            entry.text = $"<b>{clue.title}</b>\n{clue.text}";
        }

        if (counterText != null) counterText.text = string.Format(counterFormat, FoundCount, TotalCount);
    }

    /// <summary>New game / testing.</summary>
    public void ResetJournal()
    {
        found.Clear();
        OnClueCountChanged?.Invoke(0, TotalCount);
        if (panel != null && panel.activeSelf) Rebuild();
    }
}