using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// GAME 1303 Tier 4 — Crates, cracked walls, pots. Takes damage like anything else and
/// shatters. The Magnet, Stardust, Spark of Corruption.
///
/// SETUP
///  1. Sprite + Collider2D (solid, so it blocks) + Health (Max 2, Invulnerability 0,
///     Destroy On Death OFF — this script handles it) + this script.
///  2. If the player attacks with Tier 2 Hitboxes: add a child with a trigger collider +
///     Hurtbox (Team = Neutral) so any team can hit it. DamageOnContact from a thrown
///     MetalObject or a Dash-through hitbox also works.
///  3. Min Damage To Break: 0 = anything chips it; 3 = only a strong hit (charged launch,
///     thrown metal) breaks it — weak hits are ignored. Good for "you need the Sorcerer
///     to break this wall" gating in Spark of Corruption.
///  4. Loot: drop a Collectible prefab (or several). Debris: a particle or chunk prefab.
///  5. Cracked Sprite: swaps in when health is below half — visual feedback.
/// </summary>
[RequireComponent(typeof(Health))]
public class Breakable : MonoBehaviour
{
    public int minDamageToBreak = 0;

    [Header("Visuals")]
    public Sprite crackedSprite;
    public GameObject debrisPrefab;
    public string breakSfx = "break";
    public string hitSfx = "thud";

    [Header("Loot")]
    public GameObject[] lootPrefabs;
    public int lootCount = 1;
    public float lootScatter = 3f;

    public UnityEvent OnBroken;

    private Health health;
    private SpriteRenderer sr;
    private int lastHealth;

    void Awake()
    {
        health = GetComponent<Health>();
        health.destroyOnDeath = false;
        health.invulnerabilityTime = 0f;
        sr = GetComponentInChildren<SpriteRenderer>();
        lastHealth = health.maxHealth;
        health.OnHealthChanged.AddListener(OnHealthChanged);
        health.OnDied.AddListener(Break);
    }

    void OnHealthChanged(int current, int max)
    {
        int taken = lastHealth - current;
        lastHealth = current;
        if (taken <= 0 || current <= 0) return;

        // Too weak? Undo the damage.
        if (minDamageToBreak > 0 && taken < minDamageToBreak)
        {
            health.Heal(taken);
            lastHealth = health.CurrentHealth;
            if (!string.IsNullOrEmpty(hitSfx)) AudioManager.Instance?.PlaySFX(hitSfx);
            return;
        }

        if (!string.IsNullOrEmpty(hitSfx)) AudioManager.Instance?.PlaySFX(hitSfx);
        if (crackedSprite != null && sr != null && current <= max / 2) sr.sprite = crackedSprite;
    }

    public void Break()
    {
        if (!string.IsNullOrEmpty(breakSfx)) AudioManager.Instance?.PlaySFX(breakSfx);
        if (debrisPrefab != null) Instantiate(debrisPrefab, transform.position, Quaternion.identity);

        if (lootPrefabs != null && lootPrefabs.Length > 0)
            for (int i = 0; i < lootCount; i++)
            {
                var prefab = lootPrefabs[Random.Range(0, lootPrefabs.Length)];
                if (prefab == null) continue;
                var loot = Instantiate(prefab, transform.position, Quaternion.identity);
                var rb = loot.GetComponent<Rigidbody2D>();
                if (rb != null) rb.AddForce(new Vector2(Random.Range(-1f, 1f), 1f).normalized * lootScatter, ForceMode2D.Impulse);
            }

        OnBroken?.Invoke();
        Destroy(gameObject);
    }
}