using Theriapolis.Core.Rules.Stats;

namespace Theriapolis.Core.Rules.Combat;

/// <summary>
/// Phase 5 M6 player death-save loop. d20 every turn while at 0 HP:
/// - 1            → 2 failures
/// - 2..9         → 1 failure
/// - 10..19       → 1 success
/// - 20           → revive at 1 HP (zero out failures + successes)
///
/// 3 cumulative successes (≥10) → stabilised at 0 HP (cleared on heal).
/// 3 cumulative failures (<10)  → dead. CombatHUDScreen pushes
/// <see cref="Game.Screens.DefeatedScreen"/> when this fires.
///
/// Tracker lives on <see cref="Combatant"/> only for the player; NPC
/// combatants skip death saves and are removed at 0 HP.
/// </summary>
public sealed class DeathSaveTracker
{
    public int Successes { get; private set; }
    public int Failures  { get; private set; }
    public bool Stabilised { get; private set; }
    public bool Dead       { get; private set; }

    /// <summary>Roll a death save and update counters. Returns the outcome.</summary>
    public DeathSaveOutcome Roll(Encounter enc, Combatant target)
    {
        if (Dead || Stabilised) return DeathSaveOutcome.NoOp;

        int d20 = enc.RollD20();
        DeathSaveOutcome outcome;
        if (d20 == 20)
        {
            // Critical success — revive at 1 HP.
            target.CurrentHp = 1;
            target.Conditions.Remove(Condition.Unconscious);
            Successes = 0;
            Failures  = 0;
            outcome   = DeathSaveOutcome.CriticalRevive;
        }
        else if (d20 >= 10)
        {
            Successes++;
            outcome = Successes >= 3 ? DeathSaveOutcome.Stabilised : DeathSaveOutcome.Success;
            if (Successes >= 3) Stabilised = true;
        }
        else
        {
            int failsThisRoll = d20 == 1 ? 2 : 1;
            Failures += failsThisRoll;
            outcome   = Failures >= 3 ? DeathSaveOutcome.Dead : DeathSaveOutcome.Failure;
            if (Failures >= 3) Dead = true;
        }

        enc.AppendLog(CombatLogEntry.Kind.Save,
            $"{target.Name} death save: {d20} → {outcome} ({Successes}S/{Failures}F)");
        return outcome;
    }

    /// <summary>Called when the character is healed above 0 HP — cancels the loop.</summary>
    public void Reset()
    {
        Successes = 0;
        Failures  = 0;
        Stabilised = false;
        // Don't reset Dead — once dead, stays dead.
    }
}

public enum DeathSaveOutcome
{
    NoOp           = 0,
    Success        = 1,
    Failure        = 2,
    Stabilised     = 3,
    Dead           = 4,
    CriticalRevive = 5,
}
