using MessagePack;
using SVSim.Database.Enums;
using System.Text.Json.Serialization;
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses;
///
/// /mypage/index ("home screen refresh") response payload.
///
/// Required fields per the minimum-viable section of
/// docs/api-spec/endpoints/post-login/mypage-index.md and corroborated by
/// MyPageTask.cs direct-index accesses (jsonData["…"] without TryGetValue).
/// Optional fields are nullable and omitted by the global WhenWritingNull
/// policy — the client uses TryGetValue / GetValueOrDefault for those.
///
[MessagePackObject]
public class MyPageIndexResponse
{
// ── User identity / counts ─────────────────────────────────────────────
///
/// Full UserInfo block. Client only reads .name here (MyPageTask.cs:39) but
/// prod emits the full structure, so we do too.
///
[JsonPropertyName("user_info")]
[Key("user_info")]
public UserInfo UserInfo { get; set; } = new();
[JsonPropertyName("unreceived_mission_reward_count")]
[Key("unreceived_mission_reward_count")]
public int UnreceivedMissionRewardCount { get; set; }
[JsonPropertyName("receive_friend_apply_count")]
[Key("receive_friend_apply_count")]
public int ReceiveFriendApplyCount { get; set; }
[JsonPropertyName("unread_present_count")]
[Key("unread_present_count")]
public int UnreadPresentCount { get; set; }
[JsonPropertyName("friend_battle_invite_count")]
[Key("friend_battle_invite_count")]
public int FriendBattleInviteCount { get; set; }
// ── Guild ──────────────────────────────────────────────────────────────
[JsonPropertyName("guild_notification")]
[Key("guild_notification")]
public GuildNotification GuildNotification { get; set; } = new();
// ── Announcements ──────────────────────────────────────────────────────
[JsonPropertyName("last_announce_id")]
[Key("last_announce_id")]
public int LastAnnounceId { get; set; }
/// ISO datetime. Parse is wrapped in try/catch on the client.
[JsonPropertyName("last_announce_update_time")]
[Key("last_announce_update_time")]
public string LastAnnounceUpdateTime { get; set; } = string.Empty;
// ── Maintenance ────────────────────────────────────────────────────────
/// Same shape as /load/index. Empty list in the 2026-05-23 capture.
[JsonPropertyName("feature_maintenance_list")]
[Key("feature_maintenance_list")]
public List FeatureMaintenanceList { get; set; } = new();
// ── Arena / Colosseum ──────────────────────────────────────────────────
///
/// Client unconditionally constructs ArenaData(arena_info) which reads [0],
/// so this MUST be a non-empty list. See LoadController BuildArenaInfosAsync
/// — we mirror that, returning null (omitted on wire) when no Take Two
/// season is seeded, in which case the client's Keys.Contains guard at
/// LoadDetail.cs:261 handles it. For mypage there is no equivalent guard;
/// the client always reads it. Until that's reconciled we send a minimal
/// stub on the controller side.
///
[JsonPropertyName("arena_info")]
[Key("arena_info")]
public List ArenaInfo { get; set; } = new();
[JsonPropertyName("is_arena_challenge_period")]
[Key("is_arena_challenge_period")]
public bool IsArenaChallengePeriod { get; set; }
[JsonPropertyName("is_available_colosseum_free_entry")]
[Key("is_available_colosseum_free_entry")]
public bool IsAvailableColosseumFreeEntry { get; set; }
// ── Sealed Arena season ────────────────────────────────────────────────
///
/// sealed_info is consumed by ArenaData.SetSealedMyPageResponseData (Keys.Contains-guarded),
/// but post-parse-consumer policy says we emit anyway. Defaults to a zeroed-out SealedInfo
/// when no current season is seeded — Enable=0 means the UI treats Sealed as inactive.
///
[JsonPropertyName("sealed_info")]
[Key("sealed_info")]
public SealedInfo SealedInfo { get; set; } = new();
// ── Mypage banner carousel ─────────────────────────────────────────────
///
/// banner is consumed by per-entry parsing inside a TryGetValue guard
/// (Wizard/MyPageBannerBase.BannerInfo.Parse iterates the array if present). We always emit
/// the list — empty when no rows have been imported. See SVSim.Bootstrap.MyPageGlobalsImporter.ImportBannersAsync.
///
[JsonPropertyName("banner")]
[Key("banner")]
public List Banner { get; set; } = new();
/// Prod sends explicit null. Override WhenWritingNull so the key survives serialization.
[JsonPropertyName("sub_banner")]
[Key("sub_banner")]
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public object? SubBanner { get; set; }
[JsonPropertyName("sub_banner_list")]
[Key("sub_banner_list")]
public List