using System.ComponentModel.DataAnnotations;
namespace DorkNet.Server.Data.Entities;
///
/// A "Group" / club — wire type RecNet.Group
/// (Cpp2IL_CS/.../RecNet/Group.cs) for the legacy
/// api/groups/v1/* surface, and the newer RecNet.Club
/// (Cpp2IL_ISIL/.../PLILLKHMNDA.txt) for the
/// clubs.localhost/club/* surface used by 2020.12. Both wire
/// shapes are projected from this one entity by the respective
/// controllers; field names + types match each client deserializer
/// so the watch round-trips cleanly.
///
/// The 2020.12 Club wire keys (per ISIL deserializer):
/// ClubId, Name, Description, MainImageName, State, CreatorAccountId,
/// Category, Visibility, Joinability, AllowJuniors, MemberCount,
/// IsRRO, ClubhouseRoomId, ClubType.
/// MemberCount is derived live from
/// at projection time so we never have to keep a denormalised counter
/// in sync; the other fields are persisted columns on this row.
///
public class ClubEntity
{
/// Mirrors wire field GroupId / ClubId.
public long Id { get; set; }
[MaxLength(128)]
public string Name { get; set; } = string.Empty;
[MaxLength(2000)]
public string Description { get; set; } = string.Empty;
/// Mirrors wire CreatorId (legacy) / CreatorAccountId
/// (Int32 in the 2020.12 payload). Cast to int in the wire mappers.
public long CreatorPlayerId { get; set; }
/// Legacy ImageName for api/groups/v1/*. The 2020.12
/// Club wire field is MainImageName — same column, two projection
/// names.
[MaxLength(256)]
public string ImageName { get; set; } = string.Empty;
/// GroupBanStatus enum: 0=GoodStanding, 1=InReview,
/// 2=TempLock, 3=Permaban.
public int BanStatus { get; set; } = 0;
/// Club state enum on the 2020.12 wire (State).
/// 0=Active, 1=Disbanded, 2=Suspended. Defaults to Active so legacy
/// rows created via api/groups/v1/* still surface as live.
public int State { get; set; } = 0;
/// Primary category-tag name surfaced in the 2020.12 Club
/// wire Category field. Empty string is valid — the watch
/// renders "uncategorized" when blank.
[MaxLength(64)]
public string Category { get; set; } = string.Empty;
/// Club visibility enum on the wire (Visibility).
/// 0=Public, 1=Unlisted, 2=Private.
public int Visibility { get; set; } = 0;
/// Club joinability enum on the wire (Joinability).
/// 0=Open, 1=RequestToJoin, 2=InviteOnly.
public int Joinability { get; set; } = 0;
/// Drives the wire AllowJuniors bool. True means
/// junior accounts can join + see member-only content.
public bool AllowJuniors { get; set; } = true;
/// Drives the wire IsRRO bool — Rec Room Original
/// stamp on first-party clubs. Default false; admin-toggle only.
public bool IsRRO { get; set; } = false;
/// Drives the wire nullable ClubhouseRoomId. When
/// set, the watch shows a "Go to clubhouse" CTA on the club
/// detail screen that routes to this room's standard goto flow.
public long? ClubhouseRoomId { get; set; }
/// Drives the wire ClubType int. 0=Standard,
/// 1=Featured. The legacy api/groups/v1 surface ignores this; the
/// 2020.12 watch uses it to sort featured clubs to the top of
/// browse.
public int ClubType { get; set; } = 0;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}
/// One row per (club, player). Permissions is the
/// GroupMembershipPermissions flags enum (Member=0, Moderator=24,
/// CoOwner=124, Owner=127, Pending=128 for join-requests on private
/// groups).
public class ClubMembershipEntity
{
public long Id { get; set; }
public long ClubId { get; set; }
public long PlayerId { get; set; }
/// GroupMembershipPermissions flags enum value.
public int Permissions { get; set; } = 0;
public DateTime JoinedAt { get; set; } = DateTime.UtcNow;
}