using System.ComponentModel.DataAnnotations;
namespace DorkNet.Server.Data.Entities;
///
/// One purchasable item in the in-game store. The watch's Shop tab
/// renders these, and the purchase flow (initiatepurchase →
/// processpurchase → completepurchase) verifies the player has enough
/// of currency, deducts ,
/// and appends to the buyer's
/// list so the customisation
/// menu can equip it.
///
/// Item slots / categories track the avatar slots the watch's
/// outfit-selector groups items by — Head, Torso, Legs, Feet,
/// Accessory, Face, Hair, plus non-avatar categories (Consumable,
/// RoomTemplate, Emote) that don't go into outfit selections but
/// still show up in the player's inventory.
///
public class StoreItemEntity
{
public long Id { get; set; }
/// Stable string identifier — what we put in
/// InventoryJson and OutfitSelections. Format is a GUID for
/// avatar items (so the watch's avatar resolver matches the
/// baked AvatarItemDefinition catalog), or a kebab-case slug for
/// non-avatar items (consumables / templates). Unique.
// Widened from 64→128 in 2026-05 to accommodate the
// wardrobe-colored-{guid}-{color} slugs the color-variant seeder
// generates — longest in the catalog is ~68 chars (long color
// names like "WhiteHatHacker" + 36-char GUID + prefix).
[MaxLength(128)]
public string Slug { get; set; } = string.Empty;
[MaxLength(128)]
public string DisplayName { get; set; } = string.Empty;
[MaxLength(1024)]
public string Description { get; set; } = string.Empty;
/// Avatar slot or item type. One of: head, torso, legs,
/// feet, accessory, face, hair, consumable, roomtemplate, emote.
///
[MaxLength(32)]
public string Category { get; set; } = "accessory";
/// cdn filename (relative to cdn.rec.net/) for the
/// store-tile thumbnail. Empty = the watch falls back to a
/// silhouette. Same format as RoomEntity.ImageName.
[MaxLength(256)]
public string ImageName { get; set; } = string.Empty;
/// Currency the item is priced in. 2 = standard tokens
/// (the everyday currency earned from level-up + cheers); higher
/// numbers reserved for premium currencies (e.g. 1 = real-money
/// purchases — never enabled on a private server).
public int CurrencyType { get; set; } = 2;
public long Price { get; set; }
/// Listing flag. False = hidden from the store but kept
/// in the catalog so existing inventory references stay
/// resolvable. Admin-only mutation.
public bool IsActive { get; set; } = true;
/// True for limited-time / event items. The watch
/// renders an "ends in" countdown alongside these and pulls them
/// from the catalog when AvailableUntil expires (we keep the row,
/// just flip IsActive=false on expiry).
public bool IsLimitedTime { get; set; }
public DateTime? AvailableUntil { get; set; }
/// Storefront grouping. "main" = the everyday
/// shop; "giftdrop:N" = a specific rotating gift-drop shelf
/// the 2020 client probes via /storefronts/v3/giftdropstore/{N};
/// "rro" = every RRO/Rec Center in-room shelf;
/// "all" = every in-room shelf; "season:N" =
/// season-pass ladders. Default is main.
///
[MaxLength(32)]
public string Storefront { get; set; } = "main";
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}