using Theriapolis.Core.Rules.Reputation;

namespace Theriapolis.Core.Rules.Dialogue;

/// <summary>
/// Phase 6 M3 — disposition-driven shop modifiers per the plan §4.6.
///
///   NEMESIS       → service refused
///   HOSTILE       → service refused
///   ANTAGONISTIC..UNFRIENDLY → +25% prices, +10% sell discount
///   NEUTRAL       → base prices
///   FAVORABLE     → -10% buy
///   FRIENDLY      → -20% buy
///   ALLIED        → -30% buy
///   CHAMPION      → -40% buy
///
/// Phase 6 M3 ships buy-side adjustment only; sell-side is mirrored at
/// 50% of the buy modifier so a friendly merchant pays a small premium
/// without dual-tunable knobs.
/// </summary>
public static class ShopPricing
{
    /// <summary>True if the player can shop at all given the disposition score.</summary>
    public static bool ServiceAvailable(int dispositionScore)
    {
        var label = DispositionLabels.For(dispositionScore);
        return label != DispositionLabel.Nemesis && label != DispositionLabel.Hostile;
    }

    /// <summary>
    /// Multiplier applied to a price the player pays. 1.0 = base; &gt;1 =
    /// markup; &lt;1 = discount. Caller multiplies the item's listed cost
    /// and rounds.
    /// </summary>
    public static float BuyMultiplier(int dispositionScore)
    {
        var label = DispositionLabels.For(dispositionScore);
        return label switch
        {
            DispositionLabel.Nemesis      => 99f,   // shouldn't be called; sentinel
            DispositionLabel.Hostile      => 99f,
            DispositionLabel.Antagonistic => 1.25f,
            DispositionLabel.Unfriendly   => 1.25f,
            DispositionLabel.Neutral      => 1.00f,
            DispositionLabel.Favorable    => 0.90f,
            DispositionLabel.Friendly     => 0.80f,
            DispositionLabel.Allied       => 0.70f,
            DispositionLabel.Champion     => 0.60f,
            _                              => 1.00f,
        };
    }

    /// <summary>Multiplier applied to a price the merchant pays the player on sell-back.</summary>
    public static float SellMultiplier(int dispositionScore)
    {
        // Mirror buy modifier toward 1.0 by 50%: friendly buy = 0.80 →
        // friendly sell = 0.60 (you still take a haircut), antagonistic
        // buy = 1.25 → antagonistic sell = 0.30.
        var label = DispositionLabels.For(dispositionScore);
        return label switch
        {
            DispositionLabel.Antagonistic => 0.35f,
            DispositionLabel.Unfriendly   => 0.40f,
            DispositionLabel.Neutral      => 0.50f,
            DispositionLabel.Favorable    => 0.55f,
            DispositionLabel.Friendly     => 0.60f,
            DispositionLabel.Allied       => 0.65f,
            DispositionLabel.Champion     => 0.70f,
            _                              => 0f,    // refused at Hostile / Nemesis
        };
    }

    /// <summary>Buy price for one unit (rounded up). Cost is in the item's "cost_fang" or equivalent unit.</summary>
    public static int BuyPriceFor(int baseCost, int dispositionScore)
        => System.Math.Max(1, (int)System.Math.Ceiling(baseCost * BuyMultiplier(dispositionScore)));

    /// <summary>Sell price for one unit (rounded down).</summary>
    public static int SellPriceFor(int baseCost, int dispositionScore)
        => System.Math.Max(0, (int)System.Math.Floor(baseCost * SellMultiplier(dispositionScore)));
}
