using UnityEngine;
using System;

/// <summary>
/// GameEvents — Static event bus replacing all FindObjectOfType communication.
/// Zero-allocation pub/sub pattern. All events are static Actions.
/// Subscribe in OnEnable, unsubscribe in OnDisable.
/// </summary>
public static class GameEvents
{
    // ─── Match Flow ───────────────────────────────────────────
    public static event Action OnMatchStart;
    public static event Action<string> OnMatchEnd;               // winning teamTag
    public static event Action<bool> OnMatchResult;              // true = player won
    public static event Action<float> OnTimerUpdated;            // remaining seconds
    public static event Action<string> OnCountdownTick;          // "3", "2", "1", "FIGHT!"
    public static event Action<bool> OnCombatEnabled;            // true = enabled
    public static event Action OnOvertimeStart;

    // ─── Cash Bag Events ──────────────────────────────────────
    public static event Action<CashBag> OnBagSpawned;
    public static event Action<CashBag> OnBagCollected;                    // bag was picked up
    public static event Action<CashBag, CashCarrier> OnBagPickedUp;       // who picked it
    public static event Action<CashBag, Vector3> OnBagDropped;             // bag + drop position
    public static event Action<CashBag> OnBagDespawned;
    public static event Action<int> OnActiveBagCountChanged;               // current active count

    // ─── Scoring Events ──────────────────────────────────────
    public static event Action<string, float, int> OnCashDeposited;        // teamTag, value, comboMultiplier
    public static event Action<string, float> OnVaultUpdated;              // teamTag, newTotal
    public static event Action<string, float> OnScoreChanged;              // teamTag, totalScore

    // ─── Combat Events ───────────────────────────────────────
    public static event Action<GameObject, GameObject> OnKill;             // killer, victim
    public static event Action<GameObject, GameObject, float> OnDamageDealt; // attacker, victim, amount
    public static event Action<CashCarrier> OnCarrierKilled;               // carrier that was killed
    public static event Action<GameObject, int> OnCarrierKillBonus;        // killer, bonus points

    // ─── Vault Events ────────────────────────────────────────
    public static event Action<TeamVault> OnVaultUnderAttack;
    public static event Action<TeamVault> OnVaultDefended;
    public static event Action<TeamVault, float> OnVaultStolen;            // vault, amount stolen

    // ─── Extraction Events ───────────────────────────────────
    public static event Action<ExtractionVault> OnExtractionVaultSpawned;   // vault appeared in world
    public static event Action<ExtractionVault, GameObject> OnVaultOpened;  // vault, opener — $1,000 instant reward
    public static event Action<ExtractionVault, GameObject> OnVaultPickedUp;// vault, carrier — starts encumbrance
    public static event Action<ExtractionVault, Vector3> OnVaultDropped;    // vault, drop position
    public static event Action<CashoutStation, string, float> OnCashoutStarted;  // station, teamTag, instantPayout (30%)
    public static event Action<CashoutStation, float> OnCashoutProgress;         // station, progress 0-1
    public static event Action<CashoutStation, string, float> OnCashoutCompleted;// station, teamTag, totalPayout
    public static event Action<CashoutStation, string> OnCashoutContested;       // station, contestingTeamTag
    public static event Action<CashoutStation, string, float> OnCashoutHacked;   // station, hackingTeamTag, stolenAmount
    public static event Action<string> OnTeamWipe;                               // wiped teamTag — triggers -30% penalty
    public static event Action<GameObject, float> OnKillReward;                  // killer, reward amount ($200)
    public static event Action<GameObject, float> OnRespawnTimerUpdate;          // character, remainingSeconds

    // ─── Character Events ────────────────────────────────────
    public static event Action<GameObject> OnCharacterSpawned;
    public static event Action<GameObject> OnCharacterDied;
    public static event Action<GameObject> OnCharacterRespawned;
    public static event Action<GameObject, GameObject> OnCharacterSwitched; // old, new

    // ─── AI Events ───────────────────────────────────────────
    public static event Action<AIBrain, AIAction> OnAIActionChanged;
    public static event Action<string> OnTeamPing;                         // "Attack!", "Defend!", etc.

    // ─── UI Events ───────────────────────────────────────────
    public static event Action<string, string, string> OnKillFeedEntry;    // killer, action, victim
    public static event Action<string, float> OnPopupMessage;              // message, duration
    public static event Action<int> OnComboMultiplier;                     // multiplier value

    // ─── Fire Methods (static, no allocation) ────────────────

    // Match Flow
    public static void FireMatchStart() => OnMatchStart?.Invoke();
    public static void FireMatchEnd(string winnerTag) => OnMatchEnd?.Invoke(winnerTag);
    public static void FireMatchResult(bool playerWon) => OnMatchResult?.Invoke(playerWon);
    public static void FireTimerUpdated(float remaining) => OnTimerUpdated?.Invoke(remaining);
    public static void FireCountdownTick(string text) => OnCountdownTick?.Invoke(text);
    public static void FireCombatEnabled(bool enabled) => OnCombatEnabled?.Invoke(enabled);
    public static void FireOvertimeStart() => OnOvertimeStart?.Invoke();

    // Cash Bags
    public static void FireBagSpawned(CashBag bag) => OnBagSpawned?.Invoke(bag);
    public static void FireBagCollected(CashBag bag) => OnBagCollected?.Invoke(bag);
    public static void FireBagPickedUp(CashBag bag, CashCarrier carrier) => OnBagPickedUp?.Invoke(bag, carrier);
    public static void FireBagDropped(CashBag bag, Vector3 pos) => OnBagDropped?.Invoke(bag, pos);
    public static void FireBagDespawned(CashBag bag) => OnBagDespawned?.Invoke(bag);
    public static void FireActiveBagCountChanged(int count) => OnActiveBagCountChanged?.Invoke(count);

    // Scoring
    public static void FireCashDeposited(string teamTag, float value, int combo) => OnCashDeposited?.Invoke(teamTag, value, combo);
    public static void FireVaultUpdated(string teamTag, float total) => OnVaultUpdated?.Invoke(teamTag, total);
    public static void FireScoreChanged(string teamTag, float total) => OnScoreChanged?.Invoke(teamTag, total);

    // Combat
    public static void FireKill(GameObject killer, GameObject victim) => OnKill?.Invoke(killer, victim);
    public static void FireDamageDealt(GameObject attacker, GameObject victim, float amount) => OnDamageDealt?.Invoke(attacker, victim, amount);
    public static void FireCarrierKilled(CashCarrier carrier) => OnCarrierKilled?.Invoke(carrier);
    public static void FireCarrierKillBonus(GameObject killer, int bonus) => OnCarrierKillBonus?.Invoke(killer, bonus);

    // Vault
    public static void FireVaultUnderAttack(TeamVault vault) => OnVaultUnderAttack?.Invoke(vault);
    public static void FireVaultDefended(TeamVault vault) => OnVaultDefended?.Invoke(vault);
    public static void FireVaultStolen(TeamVault vault, float amount) => OnVaultStolen?.Invoke(vault, amount);

    // Extraction
    public static void FireExtractionVaultSpawned(ExtractionVault vault) => OnExtractionVaultSpawned?.Invoke(vault);
    public static void FireVaultOpened(ExtractionVault vault, GameObject opener) => OnVaultOpened?.Invoke(vault, opener);
    public static void FireVaultPickedUp(ExtractionVault vault, GameObject carrier) => OnVaultPickedUp?.Invoke(vault, carrier);
    public static void FireVaultDropped(ExtractionVault vault, Vector3 pos) => OnVaultDropped?.Invoke(vault, pos);
    public static void FireCashoutStarted(CashoutStation station, string teamTag, float payout) => OnCashoutStarted?.Invoke(station, teamTag, payout);
    public static void FireCashoutProgress(CashoutStation station, float progress) => OnCashoutProgress?.Invoke(station, progress);
    public static void FireCashoutCompleted(CashoutStation station, string teamTag, float total) => OnCashoutCompleted?.Invoke(station, teamTag, total);
    public static void FireCashoutContested(CashoutStation station, string teamTag) => OnCashoutContested?.Invoke(station, teamTag);
    public static void FireCashoutHacked(CashoutStation station, string teamTag, float amount) => OnCashoutHacked?.Invoke(station, teamTag, amount);
    public static void FireTeamWipe(string teamTag) => OnTeamWipe?.Invoke(teamTag);
    public static void FireKillReward(GameObject killer, float reward) => OnKillReward?.Invoke(killer, reward);
    public static void FireRespawnTimerUpdate(GameObject character, float remaining) => OnRespawnTimerUpdate?.Invoke(character, remaining);

    // Characters
    public static void FireCharacterSpawned(GameObject character) => OnCharacterSpawned?.Invoke(character);
    public static void FireCharacterDied(GameObject character) => OnCharacterDied?.Invoke(character);
    public static void FireCharacterRespawned(GameObject character) => OnCharacterRespawned?.Invoke(character);
    public static void FireCharacterSwitched(GameObject oldChar, GameObject newChar) => OnCharacterSwitched?.Invoke(oldChar, newChar);

    // AI
    public static void FireAIActionChanged(AIBrain brain, AIAction action) => OnAIActionChanged?.Invoke(brain, action);
    public static void FireTeamPing(string message) => OnTeamPing?.Invoke(message);

    // UI
    public static void FireKillFeedEntry(string killer, string action, string victim) => OnKillFeedEntry?.Invoke(killer, action, victim);
    public static void FirePopupMessage(string message, float duration) => OnPopupMessage?.Invoke(message, duration);
    public static void FireComboMultiplier(int multiplier) => OnComboMultiplier?.Invoke(multiplier);

    /// <summary>
    /// Call on scene unload to prevent stale references.
    /// </summary>
    public static void ClearAll()
    {
        OnMatchStart = null;
        OnMatchEnd = null;
        OnMatchResult = null;
        OnTimerUpdated = null;
        OnCountdownTick = null;
        OnCombatEnabled = null;
        OnOvertimeStart = null;

        OnBagSpawned = null;
        OnBagCollected = null;
        OnBagPickedUp = null;
        OnBagDropped = null;
        OnBagDespawned = null;
        OnActiveBagCountChanged = null;

        OnCashDeposited = null;
        OnVaultUpdated = null;
        OnScoreChanged = null;

        OnKill = null;
        OnDamageDealt = null;
        OnCarrierKilled = null;
        OnCarrierKillBonus = null;

        OnVaultUnderAttack = null;
        OnVaultDefended = null;
        OnVaultStolen = null;

        OnExtractionVaultSpawned = null;
        OnVaultOpened = null;
        OnVaultPickedUp = null;
        OnVaultDropped = null;
        OnCashoutStarted = null;
        OnCashoutProgress = null;
        OnCashoutCompleted = null;
        OnCashoutContested = null;
        OnCashoutHacked = null;
        OnTeamWipe = null;
        OnKillReward = null;
        OnRespawnTimerUpdate = null;

        OnCharacterSpawned = null;
        OnCharacterDied = null;
        OnCharacterRespawned = null;
        OnCharacterSwitched = null;

        OnAIActionChanged = null;
        OnTeamPing = null;

        OnKillFeedEntry = null;
        OnPopupMessage = null;
        OnComboMultiplier = null;
    }
}
