using System.Text.Json.Serialization;

namespace Theriapolis.Core.Persistence;

/// <summary>
/// JSON-serializable metadata stored at the front of a save file. Designed so
/// the slot picker can deserialize just the header (with a 4-byte length
/// prefix preceding it) without touching the binary body.
/// </summary>
public sealed class SaveHeader
{
    /// <summary>Schema version. Bump on breaking changes — see SaveMigrations.</summary>
    [JsonPropertyName("version")]
    public int Version { get; set; } = C.SAVE_SCHEMA_VERSION;

    [JsonPropertyName("worldSeed")]
    public string WorldSeedHex { get; set; } = "0x0";

    [JsonPropertyName("stageHashes")]
    public Dictionary<string, string> StageHashes { get; set; } = new();

    [JsonPropertyName("playerName")]
    public string PlayerName { get; set; } = "Wanderer";

    [JsonPropertyName("playerTier")]
    public int PlayerTier { get; set; }

    [JsonPropertyName("inGameSeconds")]
    public long InGameSeconds { get; set; }

    [JsonPropertyName("savedAt")]
    public string SavedAtUtc { get; set; } = "";

    [JsonPropertyName("appVersion")]
    public string AppVersion { get; set; } = "0.4.0";

    /// <summary>Convenience: a one-line label for the slot picker.</summary>
    public string SlotLabel()
    {
        // "Wanderer — Y0 Spring D5  (Tier 1)" style
        long sec = InGameSeconds;
        long days = sec / Time.WorldClock.SecondsPerDay;
        int  year = (int)(days / Time.WorldClock.DaysPerYear);
        var season = (Time.Season)((days / Time.WorldClock.DaysPerSeason) % 4);
        long dayOfSeason = days % Time.WorldClock.DaysPerSeason;
        return $"{PlayerName} — Y{year} {season} D{dayOfSeason}  (Tier {PlayerTier})";
    }

    public ulong ParseSeed()
    {
        string s = WorldSeedHex.Trim();
        if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
            return Convert.ToUInt64(s[2..], 16);
        return ulong.Parse(s);
    }
}
