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

/// <summary>
/// GAME 1303 Tier 6 — Works out which ending the player earned and goes there.
/// Commission Witch ("different endings based on how many ingredients you collect"),
/// Anabasis, Detective Liz.
///
/// SETUP
///  1. Empty GameObject + this script, in the scene where the game can end.
///  2. Add an Ending entry per outcome. Each one can require:
///       Require Flags   – "saved_the_cat, !broke_the_mirror"
///       Item / Min Count – at least N of an ItemType from the CollectionTracker
///       Min Counter      – a ChoiceFlagManager counter is at least N
///     An ending with NO conditions is a valid fallback.
///  3. ORDER MATTERS: the FIRST ending whose conditions all pass is chosen. Put the
///     hardest, most specific ending at the top and the "you just finished" one last.
///  4. Each ending can load a scene, set a flag, and fire an event (show a panel,
///     play music, roll credits).
///  5. Trigger it: wire LevelExit.OnCompleted or a boss's OnBossDefeated to
///     EndingSelector.ChooseEnding.
///
/// Endings List: EndingSelector records each ending the player has seen under
/// "ending_seen_<id>" in the flag manager, so an ending gallery is just a set of
/// flag checks (Andraya's mood board has an ENDING LIST in the menu — this is that).
/// </summary>
public class EndingSelector : MonoBehaviour
{
    [System.Serializable]
    public class Ending
    {
        public string endingId = "good";
        public string displayName = "The Good Ending";
        [TextArea(2, 4)] public string description = "";

        [Header("Conditions (all must pass; empty = always passes)")]
        public string requireFlags = "";
        public ItemType requiredItem;
        public int minItemCount = 0;
        public string counterName = "";
        public int minCounterValue = 0;

        [Header("What happens")]
        public string loadScene = "";
        public string setFlag = "";
        public DialogueData epilogue;
        public UnityEvent onChosen;
    }

    [Tooltip("Checked top to bottom — first match wins. Put the fallback LAST.")]
    public List<Ending> endings = new List<Ending>();
    public float delayBeforeScene = 0.5f;
    [Tooltip("Play the ending's epilogue dialogue before loading its scene.")]
    public bool waitForEpilogue = true;
    public DialogueRunner dialogueRunner;

    [Header("Events")]
    public UnityEvent<string> OnEndingChosen;   // ending id
    public UnityEvent OnNoEndingMatched;

    public Ending ChosenEnding { get; private set; }

    /// <summary>Wire LevelExit.OnCompleted / boss defeat here.</summary>
    public void ChooseEnding()
    {
        foreach (var e in endings)
        {
            if (!Matches(e)) continue;
            Apply(e);
            return;
        }
        Debug.LogWarning("EndingSelector: no ending matched. Add a fallback with no conditions.");
        OnNoEndingMatched?.Invoke();
    }

    bool Matches(Ending e)
    {
        if (!string.IsNullOrWhiteSpace(e.requireFlags))
        {
            if (ChoiceFlagManager.Instance != null && !ChoiceFlagManager.Instance.HasAll(e.requireFlags))
                return false;
        }
        if (e.requiredItem != null && e.minItemCount > 0)
        {
            int have = CollectionTracker.Instance != null ? CollectionTracker.Instance.GetCount(e.requiredItem) : 0;
            if (have < e.minItemCount) return false;
        }
        if (!string.IsNullOrEmpty(e.counterName) && e.minCounterValue > 0)
        {
            int c = ChoiceFlagManager.Instance != null ? ChoiceFlagManager.Instance.GetCount(e.counterName) : 0;
            if (c < e.minCounterValue) return false;
        }
        return true;
    }

    void Apply(Ending e)
    {
        ChosenEnding = e;

        if (!string.IsNullOrEmpty(e.setFlag)) ChoiceFlagManager.Instance?.SetFlag(e.setFlag);
        ChoiceFlagManager.Instance?.SetFlag("ending_seen_" + e.endingId);

        e.onChosen?.Invoke();
        OnEndingChosen?.Invoke(e.endingId);

        if (e.epilogue != null && dialogueRunner != null)
        {
            dialogueRunner.StartDialogue(e.epilogue);
            if (waitForEpilogue)
            {
                dialogueRunner.OnDialogueEnded.AddListener(LoadChosenScene);
                return;
            }
        }
        Invoke(nameof(LoadChosenScene), delayBeforeScene);
    }

    void LoadChosenScene()
    {
        if (ChosenEnding == null || string.IsNullOrEmpty(ChosenEnding.loadScene)) return;
        SceneLoader.Instance?.LoadScene(ChosenEnding.loadScene);
    }

    /// <summary>For an ending gallery: has the player seen this one?</summary>
    public static bool HasSeen(string endingId) =>
        ChoiceFlagManager.Instance != null && ChoiceFlagManager.Instance.HasFlag("ending_seen_" + endingId);
}