# retoor <retoor@molodetz.nl>

from devplacepy.services.game import economy


def test_level_thresholds():
    assert economy.level_for_xp(0) == 1
    assert economy.level_for_xp(economy.xp_threshold(2)) == 2
    assert economy.level_for_xp(economy.xp_threshold(5)) == 5
    assert economy.level_for_xp(economy.xp_threshold(economy.MAX_LEVEL) + 9999) == economy.MAX_LEVEL


def test_level_progress_span():
    progress = economy.level_progress(economy.xp_threshold(3))
    assert progress["level"] == 3
    assert progress["into_level"] == 0
    assert progress["is_max"] is False


def test_plot_cost_doubles():
    assert economy.plot_cost(economy.STARTING_PLOTS) == economy.PLOT_BASE_COST
    assert economy.plot_cost(economy.STARTING_PLOTS + 1) == economy.PLOT_BASE_COST * 2
    assert economy.plot_cost(economy.STARTING_PLOTS + 2) == economy.PLOT_BASE_COST * 4


def test_perk_cost_grows():
    perk = economy.perk_for("yield")
    assert economy.perk_cost(perk, 0) == perk.base_cost
    assert economy.perk_cost(perk, 1) == round(perk.base_cost * perk.cost_growth)
    assert economy.perk_cost(perk, 2) > economy.perk_cost(perk, 1)


def test_daily_reward_streak_and_cap():
    assert economy.daily_reward(1) == economy.DAILY_BASE
    assert economy.daily_reward(2) == economy.DAILY_BASE + economy.DAILY_STREAK_STEP
    assert economy.daily_reward(99) == economy.daily_reward(economy.DAILY_STREAK_CAP)


def test_effective_plant_cost_discount():
    crop = economy.crop_for("python")
    assert economy.effective_plant_cost(crop, 0) == crop.cost
    assert economy.effective_plant_cost(crop, 3) < crop.cost
    assert economy.effective_plant_cost(crop, 3) >= 1


def test_effective_reward_coins_yield_and_prestige():
    crop = economy.crop_for("shell")
    assert economy.effective_reward_coins(crop, 0, 0) == crop.reward_coins
    assert economy.effective_reward_coins(crop, 4, 0) > crop.reward_coins
    assert economy.effective_reward_coins(crop, 0, 2) > crop.reward_coins


def test_effective_reward_xp():
    crop = economy.crop_for("shell")
    assert economy.effective_reward_xp(crop, 0) == crop.reward_xp
    assert economy.effective_reward_xp(crop, 10) > crop.reward_xp


def test_growth_perk_speeds_build():
    crop = economy.crop_for("python")
    assert economy.grow_seconds_for(crop, 1, 5) < economy.grow_seconds_for(crop, 1, 0)


def test_ci_tier_speeds_build():
    crop = economy.crop_for("python")
    assert economy.grow_seconds_for(crop, 2, 0) < economy.grow_seconds_for(crop, 1, 0)


def test_prestige_multiplier():
    assert economy.prestige_multiplier(0) == 1.0
    assert economy.prestige_multiplier(2) == 1 + 2 * economy.PRESTIGE_BONUS


def test_fertilize_cost_has_floor():
    assert economy.fertilize_click_cost(1, 1, 1_000_000) == 1
    assert economy.fertilize_click_cost(10_000, 50, 100) > 1


def test_crop_payload_locked_flag():
    rust = economy.crop_for("rust")
    assert economy.crop_payload(rust, 1, 1)["locked"] is True
    assert economy.crop_payload(rust, 1, rust.min_level)["locked"] is False


def test_crop_payload_reflects_perks():
    crop = economy.crop_for("python")
    base = economy.crop_payload(crop, 1, 5)
    boosted = economy.crop_payload(crop, 1, 5, growth_level=5, discount_level=3, yield_level=4, prestige=1)
    assert boosted["cost"] < base["cost"]
    assert boosted["grow_seconds"] < base["grow_seconds"]
    assert boosted["reward_coins"] > base["reward_coins"]


def test_daily_quests_deterministic_count_and_kinds():
    first = economy.daily_quests("user-xyz", "2026-06-22")
    second = economy.daily_quests("user-xyz", "2026-06-22")
    assert first == second
    assert len(first) == economy.DAILY_QUEST_COUNT
    assert all(quest["kind"] in economy.QUEST_DEFS for quest in first)
    assert all(quest["goal"] > 0 for quest in first)


def test_farm_score_empty_is_zero():
    assert economy.farm_score({}) == 0


def test_farm_score_counts_every_factor():
    score = economy.farm_score(
        {
            "xp": 100,
            "prestige": 2,
            "total_harvests": 3,
            "coins": 200,
            "ci_tier": 3,
            "plot_count": economy.STARTING_PLOTS + 2,
            "perk_yield": 1,
            "perk_growth": 1,
            "perk_discount": 1,
            "perk_xp": 1,
            "streak": 4,
        }
    )
    expected = (
        100
        + 2 * economy.SCORE_PRESTIGE
        + 3 * economy.SCORE_HARVEST
        + 200 // economy.SCORE_COIN_DIVISOR
        + (3 - 1) * economy.SCORE_CI
        + 2 * economy.SCORE_PLOT
        + 4 * economy.SCORE_PERK
        + 4 * economy.SCORE_STREAK
    )
    assert score == expected


def test_farm_score_prestige_is_additive_and_substantial():
    base = {"xp": 800, "total_harvests": 5}
    with_prestige = {**base, "prestige": 1}
    gain = economy.farm_score(with_prestige) - economy.farm_score(base)
    assert gain == economy.SCORE_PRESTIGE
    assert gain >= economy.xp_threshold(economy.PRESTIGE_MIN_LEVEL)


def test_farm_score_prestige_lifts_above_lower_level_player():
    refactorer = {"xp": 200, "prestige": 1}
    higher_level_no_prestige = {"xp": economy.xp_threshold(5)}
    assert economy.farm_score(refactorer) > economy.farm_score(higher_level_no_prestige)


def test_farm_score_streak_is_capped():
    capped = economy.farm_score({"streak": economy.SCORE_STREAK_CAP})
    over = economy.farm_score({"streak": economy.SCORE_STREAK_CAP + 50})
    assert capped == over


def test_farm_score_handles_legacy_null_columns():
    assert economy.farm_score(
        {"xp": 50, "prestige": None, "perk_yield": None, "streak": None}
    ) == 50


# --- legacy upgrades ---------------------------------------------------------


def test_legacy_for_known_and_unknown():
    assert economy.legacy_for("multiplier") is not None
    assert economy.legacy_for("does_not_exist") is None


def test_legacy_cost_grows_with_level():
    up = economy.legacy_for("multiplier")
    assert economy.legacy_cost(up, 0) == up.base_cost
    assert economy.legacy_cost(up, 2) > economy.legacy_cost(up, 1)


def test_legacy_multiplier_steps():
    assert economy.legacy_multiplier(0) == 1.0
    assert economy.legacy_multiplier(3) == 1 + economy.LEGACY_MULT_STEP * 3


def test_stars_for_refactor_scales_with_level_and_prestige():
    assert economy.stars_for_refactor(0, 0) == economy.STAR_BASE
    assert economy.stars_for_refactor(10, 0) == economy.STAR_BASE + 2
    assert economy.stars_for_refactor(0, 2) == economy.STAR_BASE + 2


def test_prestige_base_plots_adds_legacy_plots():
    assert economy.prestige_base_plots(0) == economy.STARTING_PLOTS
    assert economy.prestige_base_plots(3) == economy.STARTING_PLOTS + 3


# --- steal economy -----------------------------------------------------------


def test_effective_steal_grace_extends_with_defense():
    assert economy.effective_steal_grace(0) == economy.STEAL_GRACE_SECONDS
    assert economy.effective_steal_grace(2) == (
        economy.STEAL_GRACE_SECONDS + economy.LEGACY_DEFENSE_GRACE * 2
    )


def test_effective_steal_fraction_drops_with_defense_and_has_floor():
    assert economy.effective_steal_fraction(0) == economy.STEAL_FRACTION
    assert economy.effective_steal_fraction(2) < economy.STEAL_FRACTION
    assert economy.effective_steal_fraction(99) >= 0.1


def test_steal_reward_coins_is_a_fraction_of_harvest():
    crop = economy.crop_for("shell")
    full = economy.effective_reward_coins(crop)
    stolen = economy.steal_reward_coins(crop)
    assert 0 < stolen <= full


# --- golden crops ------------------------------------------------------------


def test_is_golden_deterministic_and_bounded():
    first = economy.is_golden("plot-7", "2026-06-20T00:00:00+00:00")
    second = economy.is_golden("plot-7", "2026-06-20T00:00:00+00:00")
    assert first == second
    assert isinstance(first, bool)


def test_is_golden_requires_both_args():
    assert economy.is_golden("", "2026-06-20T00:00:00+00:00") is False
    assert economy.is_golden("plot-7", "") is False


# --- market saturation --------------------------------------------------------


def test_market_saturation_factor_is_full_when_fresh():
    assert economy.market_saturation_factor(0.0) == 1.0


def test_market_saturation_factor_steps_down():
    assert economy.market_saturation_factor(8.0) < 1.0
    assert economy.market_saturation_factor(96.0) == 0.40
    assert economy.market_saturation_factor(8.0) > economy.market_saturation_factor(96.0)


def test_market_saturation_factor_is_monotone_non_increasing():
    previous = 1.0
    step = 0
    while step <= 400:
        supply = step * 0.5
        factor = economy.market_saturation_factor(supply)
        assert factor <= previous
        previous = factor
        step += 1


def test_supply_days_normalizes_by_grow_time():
    shell = economy.crop_for("shell")
    kernel = economy.crop_for("kernel")
    assert economy.supply_days(shell, 0) == 0.0
    assert economy.supply_days(shell, 5760) == economy.supply_days(kernel, 24)
    assert economy.supply_days(shell, 2880) == 1.0
    assert economy.supply_days(kernel, 12) == 1.0


def test_market_buff_factor_only_applies_to_starter_crops():
    assert economy.market_buff_factor("kernel", 0.60) == 1.0
    assert economy.market_buff_factor("shell", 0.0) == 1.0
    assert economy.market_buff_factor("shell", 0.15) == 1.0375
    assert economy.market_buff_factor("shell", 0.60) == economy.MARKET_BUFF_CAP
    assert economy.market_buff_factor("shell", 0.90) == economy.MARKET_BUFF_CAP


def test_market_factor_bounds_across_domain():
    floor = economy.MARKET_SATURATION_TIERS[-1][1]
    for key in economy.MARKET_BUFFED_CROPS + economy.MARKET_PRESSURE_CROPS:
        crop = economy.crop_for(key)
        for harvests in range(0, 300000, 977):
            saturation = economy.market_saturation_factor(economy.supply_days(crop, harvests))
            for pressure in (0.0, 0.15, 0.30, 0.45, 0.60):
                factor = saturation if saturation < 1.0 else economy.market_buff_factor(key, pressure)
                assert floor <= factor <= economy.MARKET_BUFF_CAP
                if saturation < 1.0:
                    assert factor == saturation
                else:
                    assert factor >= 1.0


def test_effective_reward_coins_applies_market_factor():
    crop = economy.crop_for("shell")
    full = economy.effective_reward_coins(crop, 0, 0, 0, 1.0)
    saturated = economy.effective_reward_coins(crop, 0, 0, 0, 0.5)
    assert saturated < full
    assert saturated == round(crop.reward_coins * 0.5)


def test_effective_reward_coins_underdog_multiplier():
    crop = economy.crop_for("shell")
    plain = economy.effective_reward_coins(crop, 0, 0, 0, 1.0, False)
    boosted = economy.effective_reward_coins(crop, 0, 0, 0, 1.0, True)
    assert boosted == round(crop.reward_coins * economy.UNDERDOG_MULTIPLIER)
    assert boosted > plain


# --- infrastructure and defense ------------------------------------------------


def test_infra_for_known_and_unknown():
    assert economy.infra_for("registry") is not None
    assert economy.infra_for("does_not_exist") is None


def test_registry_boost_speeds_only_named_crops():
    kernel = economy.crop_for("kernel")
    shell = economy.crop_for("shell")
    assert economy.grow_seconds_for(kernel, 1, 0, 0, True) < economy.grow_seconds_for(
        kernel, 1, 0, 0, False
    )
    assert economy.grow_seconds_for(shell, 1, 0, 0, True) == economy.grow_seconds_for(
        shell, 1, 0, 0, False
    )


def test_defense_tier_lookup_and_progression():
    assert economy.defense_tier(0).name == "Undefended"
    assert economy.defense_tier(0).upkeep_daily == 0
    top = economy.defense_tier(economy.MAX_DEFENSE_LEVEL)
    assert economy.next_defense_tier(economy.MAX_DEFENSE_LEVEL) is None
    assert economy.next_defense_tier(0) is not None
    assert top.steal_fraction_floor < economy.defense_tier(0).steal_fraction_floor


def test_daily_upkeep_scales_with_wealth():
    tier = economy.defense_tier(1)
    assert economy.daily_upkeep(tier, 0) == tier.upkeep_daily
    rich = economy.daily_upkeep(tier, 10_000_000)
    assert rich > tier.upkeep_daily
    assert rich == round(10_000_000 * economy.UPKEEP_WEALTH_PCT)


def test_effective_steal_fraction_floor_overridden_by_building():
    assert economy.effective_steal_fraction(99, floor=0.30) == 0.30
    assert economy.effective_steal_fraction(0, floor=0.30) == economy.STEAL_FRACTION


def test_effective_steal_grace_extra_seconds_from_building():
    base = economy.effective_steal_grace(0, 0)
    with_building = economy.effective_steal_grace(0, 30)
    assert with_building == base + 30


# --- cosmetics ------------------------------------------------------------------


def test_cosmetic_for_known_and_unknown():
    assert economy.cosmetic_for("title_architect") is not None
    assert economy.cosmetic_for("does_not_exist") is None


def test_cosmetic_title_name_only_resolves_titles():
    assert economy.cosmetic_title_name("title_architect") == "The Architect"
    assert economy.cosmetic_title_name("skin_neon") == ""
    assert economy.cosmetic_title_name("") == ""
    assert economy.cosmetic_title_name("does_not_exist") == ""


# --- mastery --------------------------------------------------------------------


def test_mastery_points_awarded_first_point_at_unlock():
    step = economy.MASTERY_PRESTIGE_STEP
    unlock = economy.MASTERY_UNLOCK_PRESTIGE
    assert economy.mastery_points_awarded(unlock - 1, unlock) == 1
    assert economy.mastery_points_awarded(0, unlock - 1) == 0
    assert economy.mastery_points_awarded(unlock, unlock + step - 1) == 0
    assert economy.mastery_points_awarded(unlock + step - 1, unlock + step) == 1
    assert economy.mastery_points_awarded(unlock, unlock + step * 2) == 2


def test_mastery_for_known_and_unknown():
    assert economy.mastery_for("autoreplant") is not None
    assert economy.mastery_for("does_not_exist") is None


def test_mastery_cost_grows_with_level():
    m = economy.mastery_for("contracts")
    assert economy.mastery_cost(m, 0) == m.base_cost


def test_unlocked_crops_gates_on_mastery_and_level():
    base = economy.unlocked_crops(economy.MAX_LEVEL, mastery_earned=0)
    with_mastery = economy.unlocked_crops(economy.MAX_LEVEL, mastery_earned=1)
    assert "distsys" not in {c.key for c in base}
    assert "distsys" in {c.key for c in with_mastery}


def test_crop_payload_locked_by_mastery():
    distsys = economy.crop_for("distsys")
    locked = economy.crop_payload(distsys, 1, economy.MAX_LEVEL, mastery_earned=0)
    assert locked["locked"] is True
    assert locked["locked_reason"] == "mastery"
    assert "Mastery" in locked["locked_text"]
    unlocked = economy.crop_payload(distsys, 1, economy.MAX_LEVEL, mastery_earned=1)
    assert unlocked["locked"] is False
    assert unlocked["locked_reason"] == ""


def test_crop_payload_locked_by_level_reason():
    rust = economy.crop_for("rust")
    locked = economy.crop_payload(rust, 1, 1)
    assert locked["locked_reason"] == "level"
    assert str(rust.min_level) in locked["locked_text"]


def test_crop_lock_reason_matches_plant_enforcement():
    distsys = economy.crop_for("distsys")
    assert economy.crop_lock_reason(distsys, economy.MAX_LEVEL, 0) == ("mastery", "unlocks after reaching Mastery (Refactor to prestige 50)")
    assert economy.crop_lock_reason(distsys, economy.MAX_LEVEL, 1) is None
    assert economy.crop_lock_reason(distsys, 1, 1)[0] == "level"


def test_secfort_crop_is_steal_immune():
    secfort = economy.crop_for("secfort")
    assert secfort.steal_immune is True
    assert economy.crop_for("shell").steal_immune is False


# --- secondary leaderboard scoring -----------------------------------------------


def test_fair_play_score_rewards_activity_and_penalizes_hoarding():
    active = economy.fair_play_score(harvests_week=20, coins=0)
    hoarder = economy.fair_play_score(harvests_week=0, coins=10_000_000)
    assert active > hoarder


# --- era --------------------------------------------------------------------------


def test_era_score_gives_prestige_partial_weight():
    veteran = economy.era_score(era_coins=0, era_harvests=0, prestige=10)
    rookie = economy.era_score(era_coins=0, era_harvests=0, prestige=0)
    assert veteran > rookie
    assert veteran == round(10 * economy.SCORE_PRESTIGE * economy.ERA_PRESTIGE_CARRYOVER_PCT)


def test_era_reward_stars_by_rank():
    assert economy.era_reward_stars(1) == economy.ERA_REWARD_STARS_BY_RANK[0]
    assert economy.era_reward_stars(len(economy.ERA_REWARD_STARS_BY_RANK) + 1) == 0
    assert economy.era_reward_stars(0) == 0


# --- weekly contracts ---------------------------------------------------------------


def test_weekly_contract_deterministic():
    first = economy.weekly_contract("user-xyz", "2026-W10")
    second = economy.weekly_contract("user-xyz", "2026-W10")
    assert first == second
    assert first["kind"] in economy.QUEST_DEFS
    assert first["reward_stars"] > 0


# --- refactor fee, carry-over, and grants -------------------------------------------


def test_refactor_cost_monotonic_in_prestige():
    previous = 0
    for prestige in range(0, 200):
        cost = economy.refactor_cost(prestige, 0)
        assert cost > previous
        previous = cost


def test_refactor_cost_monotonic_in_wealth():
    previous = -1
    for coins in range(0, 2_000_000, 10_000):
        cost = economy.refactor_cost(0, coins)
        assert cost >= previous
        previous = cost


def test_refactor_cost_floor_is_base():
    assert economy.refactor_cost(0, 0) == economy.REFACTOR_BASE_COST
    assert economy.refactor_cost(-5, -100) == economy.REFACTOR_BASE_COST


def test_refactor_cost_includes_wealth_tax():
    coins = 100_000
    expected = round(
        economy.REFACTOR_BASE_COST + economy.REFACTOR_WEALTH_PCT * coins
    )
    assert economy.refactor_cost(0, coins) == expected


def test_refactor_carryover_fraction_bounds():
    for level in range(0, 50):
        fraction = economy.refactor_carryover_fraction(level)
        assert economy.REFACTOR_CARRYOVER_BASE <= fraction <= economy.REFACTOR_CARRYOVER_MAX


def test_refactor_carryover_never_exceeds_remainder():
    for coins in range(0, 500_000, 7_777):
        for level in (0, 3, 5):
            fee = economy.refactor_cost(0, coins)
            carried = economy.refactor_carryover(coins, fee, level)
            assert 0 <= carried <= max(0, coins - fee)


def test_refactor_carryover_zero_when_unaffordable():
    assert economy.refactor_carryover(100, 20_000, 5) == 0


def test_grant_amount_capped_and_bounded():
    assert economy.grant_amount(0) == 0
    assert economy.grant_amount(-10) == 0
    assert economy.grant_amount(100) == 0
    assert economy.grant_amount(economy.GRANT_MIN_AMOUNT) == economy.GRANT_MIN_AMOUNT
    assert economy.grant_amount(10**9) == economy.GRANT_CAP


def test_grant_amount_shares_between_eligible_farms():
    assert economy.grant_amount(10_000, 5) == 2_000
    assert economy.grant_amount(10**9, 4) == economy.GRANT_CAP
    assert economy.grant_amount(1_000, 10) == 0
    for eligible in range(1, 50):
        share = economy.grant_amount(10**6, eligible)
        assert 0 <= share <= economy.GRANT_CAP
        assert share * eligible <= 10**6 or share == economy.GRANT_CAP


def test_legacy_carryover_upgrade_registered():
    upgrade = economy.legacy_for("carryover")
    assert upgrade is not None
    assert upgrade.max_level == 10
    assert "carry-over" in economy.legacy_value_text(upgrade, 2)
    assert economy.refactor_carryover_fraction(upgrade.max_level) < 1.0


def test_fertilize_is_never_profitable_across_the_input_domain():
    import itertools

    for crop in economy.CROPS:
        for prestige in range(0, 201, 23):
            for yield_level in (0, 5, 10):
                for legacy in (0, 5, 10):
                    for market in (0.40, 0.70, 1.0, 1.15):
                        for golden, contract, underdog in itertools.product(
                            (False, True), repeat=3
                        ):
                            value = economy.realizable_harvest_coins(
                                crop,
                                yield_level,
                                prestige,
                                legacy,
                                market,
                                golden,
                                contract,
                                underdog,
                            )
                            cost = economy.fertilize_click_cost(
                                value, crop.grow_seconds, crop.grow_seconds
                            )
                            assert cost >= value, (
                                crop.key,
                                prestige,
                                golden,
                                contract,
                                underdog,
                                cost,
                                value,
                            )


def test_fertilize_priced_above_the_expected_canary_payout():
    for crop in economy.CROPS:
        for prestige in (0, 25, 100):
            plain = economy.realizable_harvest_coins(crop, 10, prestige, 10, 1.0)
            priced = economy.realizable_harvest_coins(
                crop, 10, prestige, 10, 1.0, canary=True
            )
            cost = economy.fertilize_click_cost(
                priced, crop.grow_seconds, crop.grow_seconds
            )
            expected = plain * (
                economy.CANARY_DOUBLE_CHANCE * 2
                + (1 - economy.CANARY_DOUBLE_CHANCE - economy.CANARY_FAIL_CHANCE)
            ) + economy.CANARY_FAIL_CHANCE * min(plain, crop.cost)
            assert cost >= expected


def test_staged_fertilize_never_undercuts_the_payout():
    for key in ("shell", "api", "kernel", "secfort"):
        crop = economy.crop_for(key)
        value = economy.realizable_harvest_coins(crop, 10, 50, 10, 1.0, True, True, True)
        remaining, total = crop.grow_seconds, 0
        while True:
            reduce_by = int(remaining * economy.FERTILIZE_FRACTION)
            if reduce_by < 1:
                break
            total += economy.fertilize_click_cost(value, reduce_by, crop.grow_seconds)
            remaining -= reduce_by
        assert total >= value


def test_every_defense_tier_reduces_the_raider_share():
    shares = []
    for tier in economy.DEFENSE_TIERS:
        share = economy.effective_steal_fraction(
            0, tier.steal_fraction_floor, tier.steal_reduction
        )
        shares.append(round(share, 4))
    assert len(set(shares)) == len(economy.DEFENSE_TIERS)
    assert shares == sorted(shares, reverse=True)


def test_more_defense_never_increases_the_raider_share():
    previous = 1.0
    for tier in economy.DEFENSE_TIERS:
        for legacy in range(0, 6):
            share = economy.effective_steal_fraction(
                legacy, tier.steal_fraction_floor, tier.steal_reduction
            )
            assert 0.0 <= share <= 1.0
        top = economy.effective_steal_fraction(
            0, tier.steal_fraction_floor, tier.steal_reduction
        )
        assert top <= previous + 1e-9
        previous = top


def test_observability_only_ever_lowers_the_raider_share():
    for tier in economy.DEFENSE_TIERS:
        for legacy in range(0, 6):
            without = economy.effective_steal_fraction(
                legacy, tier.steal_fraction_floor, tier.steal_reduction
            )
            with_suite = economy.effective_steal_fraction(
                legacy,
                tier.steal_fraction_floor,
                tier.steal_reduction,
                economy.OBSERVABILITY_STEAL_CAP,
            )
            assert with_suite <= without + 1e-9
            assert with_suite <= economy.OBSERVABILITY_STEAL_CAP + 1e-9


def test_raid_share_plus_owner_remainder_never_exceeds_the_build():
    for crop in economy.CROPS:
        for prestige in range(0, 101, 17):
            for golden in (False, True):
                value = economy.realizable_harvest_coins(
                    crop, 10, prestige, 10, 1.0, golden
                )
                for tier in economy.DEFENSE_TIERS:
                    for legacy in range(0, 6):
                        share = economy.effective_steal_fraction(
                            legacy, tier.steal_fraction_floor, tier.steal_reduction
                        )
                        thief = min(max(1, round(value * share)), int(value * (1.0 - 0.0)))
                        owner = int(value * (1.0 - share))
                        assert thief + owner <= value


def test_weekly_contract_stars_are_per_kind_not_per_goal():
    for kind in economy.QUEST_KINDS:
        for scale in (1.0, 13.5, 40.0):
            contract = economy.weekly_contract("user-a", "2026-W30", scale)
            if contract["kind"] != kind:
                continue
            assert contract["reward_stars"] == economy.QUEST_DEFS[kind].contract_stars
            assert contract["reward_stars"] <= 5


def test_social_rewards_scale_with_the_earner_and_never_regress():
    assert economy.water_reward_coins(0, 0) == economy.WATER_REWARD_COINS
    assert economy.daily_reward(1) == economy.DAILY_BASE
    previous = 0
    for prestige in range(0, 101):
        reward = economy.water_reward_coins(prestige, 0)
        assert reward >= previous
        previous = reward


def test_leaderboard_coin_contribution_is_capped():
    base = {"xp": 18050, "prestige": 50, "total_harvests": 5000, "ci_tier": 5}
    poor = economy.farm_score({**base, "coins": 0})
    rich = economy.farm_score({**base, "coins": 10**9})
    assert rich - poor <= economy.SCORE_COIN_CAP


def test_market_saturation_is_per_capita():
    crop = economy.crop_for("kernel")
    assert economy.supply_days(crop, 288, 1) == economy.supply_days(crop, 2880, 10)
    assert economy.supply_days(crop, 288, 4) < economy.supply_days(crop, 288, 1)
