namespace BlueLaminate.Core.Tradeups;
/// One possible result of a contract and what it would net if it lands.
/// Chance this specific output is produced (single-collection: 1/k).
///
/// Realisable sale value after undercut + sell fee, or null when nothing comparable is
/// listed (treated as unsellable for the worst-case test).
///
/// Active listings backing the price, in the same wear band.
/// Where the price came from: "market" (our stored listings) or
/// "csfloat-live" (re-priced from the CSFloat API because the stored liquidity was thin).
public sealed record TradeupOutcome(
int SkinId,
string Name,
decimal OutputFloat,
WearBand Band,
decimal Probability,
decimal? NetSellPrice,
int Liquidity,
string PriceSource = "market");
///
/// One collection's share of a (possibly multi-collection) contract: how many of the ten
/// inputs came from it, and which output tier those inputs roll into. Single-collection
/// contracts have exactly one of these.
///
public sealed record TradeupContribution(
int CollectionId,
string CollectionName,
WeaponRarity OutputRarity,
int InputCount);
///
/// A concrete, actionable tradeup: which ten copies to buy, what they cost, the output
/// distribution, and the resulting economics. The finder returns these ranked; a frontend
/// only formats them.
///
/// A contract may mix several collections (all inputs share the input rarity, but each
/// collection rolls into its own next tier). records the per-
/// collection split; is its length.
/// is the tier of the largest contributor (a display convenience for the common case).
///
///
public sealed record TradeupCandidate(
int CollectionId,
string CollectionName,
WeaponRarity InputRarity,
WeaponRarity OutputRarity,
bool StatTrak,
decimal AverageFraction,
decimal InputCost,
decimal ExpectedNet,
decimal WorstCaseNet,
bool Guaranteed,
IReadOnlyList Inputs,
IReadOnlyList Outcomes,
IReadOnlyList Composition)
{
/// Number of distinct collections the inputs are drawn from (1 = single-collection).
public int CollectionCount => Composition.Count;
/// Expected profit across the output distribution, net of cost.
public decimal ExpectedProfit => ExpectedNet - InputCost;
/// Profit if the worst (lowest-value) output lands — negative unless guaranteed.
public decimal WorstCaseProfit => WorstCaseNet - InputCost;
}