namespace BlueLaminate.EFCore.Entities;
///
/// One sell-order observed on cs.money via its internal
/// GET /2.0/market/sell-orders endpoint (scraped through the Python worker,
/// since cs.money has no public API and sits behind Cloudflare).
///
/// Kept in its own table rather than shared with the CSFloat :
/// cs.money exposes a different shape (its own sell-order id, a pricing breakdown,
/// quality/phase, and no def/paint index). It still links to the
/// market-agnostic by fingerprint, so the same physical
/// item seen on both markets rolls up to one instance for cross-market analysis.
///
/// Soft-tracked across sweeps exactly like :
/// / bound the observation window
/// and flips to when a
/// once-seen order stops appearing (sold/delisted).
///
public class CsMoneyListing
{
public int Id { get; set; }
/// cs.money's sell-order id (item.id). Natural key for dedup.
public long SellOrderId { get; set; }
///
/// cs.money's asset id for the listed copy. Not a stable identity, but the
/// discriminator that distinguishes duped copies sharing one fingerprint.
///
public string? AssetId { get; set; }
// Catalogue links. Unlike the CSFloat global sweep these are NOT best-effort:
// each scrape job targets one skin+wear, so the worker reports which Skin/
// Condition the results belong to and we set them directly.
public int SkinId { get; set; }
public Skin Skin { get; set; } = null!;
public int? ConditionId { get; set; }
public SkinCondition? Condition { get; set; }
/// The physical item (by fingerprint), shared with CSFloat listings.
public int? SkinInstanceId { get; set; }
public SkinInstance? SkinInstance { get; set; }
// Item identity, from the listing's asset block.
public string MarketHashName { get; set; } = null!;
public string? Quality { get; set; } // cs.money wear short code: fn/mw/ft/ww/bs
public decimal? FloatValue { get; set; } // null for non-skin items
public int? PaintSeed { get; set; } // asset.pattern
public string? Phase { get; set; } // doppler phase (sapphire/ruby/…)
public bool IsStatTrak { get; set; }
public bool IsSouvenir { get; set; }
public int StickerCount { get; set; }
// Pricing. cs.money returns a breakdown; Price is the actual asking price.
public decimal Price { get; set; } // pricing.default
public decimal? PriceBeforeDiscount { get; set; }
public decimal? ComputedPrice { get; set; } // pricing.computed (reference price)
public string Currency { get; set; } = "USD"; // cs.money returns no currency field
public string? InspectLink { get; set; }
// Soft-tracking across sweeps.
public DateTimeOffset FirstSeenAt { get; set; }
public DateTimeOffset LastSeenAt { get; set; }
public ListingStatus Status { get; set; }
public DateTimeOffset? RemovedAt { get; set; }
}