using System.Text.Json.Serialization;

namespace Metin2Launcher.Manifest;

/// <summary>
/// DTOs matching docs/update-manifest.md.
/// Field order in the serialized JSON is governed by the canonical ordering rules;
/// we only parse here (and optionally round-trip for tests), we do not sign.
/// Unknown fields are ignored by <see cref="System.Text.Json.JsonSerializerOptions.UnmappedMemberHandling"/> default (Skip).
/// </summary>
public sealed class Manifest
{
    [JsonPropertyName("format")]
    public string? Format { get; set; }

    /// <summary>
    /// Effective release format. Defaults to <c>legacy-json-blob</c> when the
    /// field is absent, which preserves backward compatibility with manifests
    /// produced before the m2pack migration.
    /// </summary>
    public string EffectiveFormat =>
        string.IsNullOrWhiteSpace(Format) ? "legacy-json-blob" : Format;

    [JsonPropertyName("version")]
    public string Version { get; set; } = "";

    [JsonPropertyName("created_at")]
    public string CreatedAt { get; set; } = "";

    [JsonPropertyName("previous")]
    public string? Previous { get; set; }

    [JsonPropertyName("notes")]
    public string? Notes { get; set; }

    [JsonPropertyName("min_launcher_version")]
    public string? MinLauncherVersion { get; set; }

    [JsonPropertyName("launcher")]
    public ManifestLauncherEntry Launcher { get; set; } = new();

    [JsonPropertyName("files")]
    public List<ManifestFile> Files { get; set; } = new();
}

public sealed class ManifestLauncherEntry
{
    [JsonPropertyName("path")]
    public string Path { get; set; } = "";

    [JsonPropertyName("sha256")]
    public string Sha256 { get; set; } = "";

    [JsonPropertyName("size")]
    public long Size { get; set; }

    [JsonPropertyName("platform")]
    public string? Platform { get; set; }
}

public sealed class ManifestFile
{
    [JsonPropertyName("path")]
    public string Path { get; set; } = "";

    [JsonPropertyName("sha256")]
    public string Sha256 { get; set; } = "";

    [JsonPropertyName("size")]
    public long Size { get; set; }

    [JsonPropertyName("platform")]
    public string? Platform { get; set; }

    [JsonPropertyName("required")]
    public bool? Required { get; set; }

    [JsonPropertyName("executable")]
    public bool? Executable { get; set; }

    /// <summary>Manifest spec default: platform == "all" if unset.</summary>
    public string EffectivePlatform => Platform ?? "all";

    /// <summary>Manifest spec default: required == true if unset.</summary>
    public bool IsRequired => Required ?? true;

    /// <summary>Returns true if this file applies to the given platform ("windows" or "linux").</summary>
    public bool AppliesTo(string platform)
    {
        var p = EffectivePlatform;
        return p == "all" || p == platform;
    }
}
