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

/// <summary>
/// GAME 1303 Tier 7 — "Changing the nature of the pet." Watches how the player has cared
/// for it over time and settles on a personality. Cozy Critters.
///
/// HOW IT WORKS
///  Every CareAction adds 1 to a counter named after its Personality Trait
///  ("well_fed", "playful", "cuddled", "groomed"). This script periodically compares the
///  counters and picks whichever Personality's trait has the highest share — but only once
///  there's enough evidence (Minimum Actions) and only if it clearly leads (Dominance
///  Threshold), so the pet doesn't flip personality every few minutes.
///
/// SETUP
///  1. Add to the pet. Needs Tier 4's ChoiceFlagManager in the scene (it stores the counters).
///  2. Add a Personality per outcome: an id, a display name, the trait it grows from, and
///     optionally a sprite/animator to swap in and a tint.
///  3. Leave one personality with an empty trait as the default ("ordinary").
///  4. OnPersonalityChanged fires when it settles somewhere new — good for a little
///     "your critter seems more playful lately" message.
///  5. Happiness Stat (optional): a pet whose happiness has been low for a long time can
///     drift toward a Sad Personality id instead. Set Sad Personality Id and the threshold.
///
/// The point is that this is descriptive, not a score. There's no wrong personality —
/// which is what keeps it cozy.
/// </summary>
public class PersonalityTracker : MonoBehaviour
{
    [System.Serializable]
    public class Personality
    {
        public string id = "playful";
        public string displayName = "Playful";
        [TextArea(1, 3)] public string description = "";
        [Tooltip("Counter name grown by CareActions (leave empty for the default personality).")]
        public string trait = "playful";

        [Header("Look (optional)")]
        public RuntimeAnimatorController animatorController;
        public Sprite portrait;
        public Color tint = Color.white;
    }

    public List<Personality> personalities = new List<Personality>();
    [Tooltip("How often to re-evaluate, in seconds.")]
    public float evaluateEvery = 15f;
    [Tooltip("Total care actions needed before a personality can form.")]
    public int minimumActions = 10;
    [Tooltip("A trait must hold at least this share of all actions to win (0.4 = 40%).")]
    [Range(0.2f, 1f)] public float dominanceThreshold = 0.4f;

    [Header("Sad drift (optional)")]
    public NeedStat happiness;
    public string sadPersonalityId = "";
    [Range(0f, 1f)] public float sadBelow = 0.25f;
    public float sadMinutesRequired = 5f;

    [Header("Events")]
    public UnityEvent<string> OnPersonalityChanged;   // id

    public Personality Current { get; private set; }

    private Animator anim;
    private SpriteRenderer sr;
    private float timer;
    private float sadMinutes;

    void Awake()
    {
        anim = GetComponent<Animator>();
        sr = GetComponentInChildren<SpriteRenderer>();
    }

    void Start()
    {
        Evaluate();
    }

    void Update()
    {
        if (happiness != null && happiness.Normalized < sadBelow)
            sadMinutes += Time.deltaTime / 60f;
        else
            sadMinutes = Mathf.Max(0f, sadMinutes - Time.deltaTime / 60f);

        timer -= Time.deltaTime;
        if (timer <= 0f) { timer = evaluateEvery; Evaluate(); }
    }

    public void Evaluate()
    {
        if (personalities.Count == 0) return;
        var flags = ChoiceFlagManager.Instance;

        // Sad drift wins if it's been going on long enough
        if (!string.IsNullOrEmpty(sadPersonalityId) && sadMinutes >= sadMinutesRequired)
        {
            var sad = personalities.Find(p => p.id == sadPersonalityId);
            if (sad != null) { Apply(sad); return; }
        }

        int total = 0;
        Personality best = null;
        int bestCount = 0;

        foreach (var p in personalities)
        {
            if (string.IsNullOrEmpty(p.trait)) continue;
            int c = flags != null ? flags.GetCount(p.trait) : 0;
            total += c;
            if (c > bestCount) { bestCount = c; best = p; }
        }

        Personality result = Default();
        if (total >= minimumActions && best != null && (float)bestCount / total >= dominanceThreshold)
            result = best;

        Apply(result);
    }

    Personality Default()
    {
        var d = personalities.Find(p => string.IsNullOrEmpty(p.trait));
        return d ?? personalities[0];
    }

    void Apply(Personality p)
    {
        if (p == null || p == Current) return;
        Current = p;

        if (anim != null && p.animatorController != null) anim.runtimeAnimatorController = p.animatorController;
        if (sr != null) sr.color = p.tint;

        ChoiceFlagManager.Instance?.SetFlag("personality_" + p.id);
        OnPersonalityChanged?.Invoke(p.id);
    }
}