using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace ModpackLauncher.Models;

public sealed class Manifest
{
    [JsonPropertyName("name")]
    public string? Name { get; set; }

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

    [JsonPropertyName("minecraft")]
    public MinecraftSpec Minecraft { get; set; } = new();

    [JsonPropertyName("loader")]
    public LoaderSpec? Loader { get; set; }

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

    /// <summary>
    /// Optional. The launcher version that the modpack publisher expects clients
    /// to be running. If a client's assembly version is lower than this, the launcher
    /// surfaces a "newer version available" banner pointing at <see cref="LauncherUrl"/>.
    /// </summary>
    [JsonPropertyName("launcherVersion")]
    public string? LauncherVersion { get; set; }

    /// <summary>Public download URL for the latest launcher (shown in the banner).</summary>
    [JsonPropertyName("launcherUrl")]
    public string? LauncherUrl { get; set; }

    /// <summary>
    /// Optional. If present, the launcher writes this entry into the player's
    /// <c>servers.dat</c> on first install so the modpack's server appears in
    /// the multiplayer list automatically -- no copy-paste needed.
    /// </summary>
    [JsonPropertyName("defaultServer")]
    public DefaultServer? DefaultServer { get; set; }

    /// <summary>
    /// Optional. Filename (in shaderpacks/) of a shader pack to enable by default
    /// for fresh installs. Existing installs with a different shader chosen are
    /// left alone -- this is a default, not a forced override.
    /// </summary>
    [JsonPropertyName("defaultShader")]
    public string? DefaultShader { get; set; }

    /// <summary>
    /// Optional. Public base URL of the brass-sigil-server admin panel (e.g.
    /// https://bns-admin.sijbers.uk). The launcher uses this to send whitelist
    /// requests on the player's behalf -- nothing else.
    /// </summary>
    [JsonPropertyName("panelUrl")]
    public string? PanelUrl { get; set; }
}

public sealed class DefaultServer
{
    [JsonPropertyName("name")]
    public string Name { get; set; } = "";

    [JsonPropertyName("ip")]
    public string Ip { get; set; } = "";
}

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

public sealed class LoaderSpec
{
    /// <summary>"forge" | "fabric" | "neoforge" | "vanilla" (or null)</summary>
    [JsonPropertyName("type")]
    public string Type { get; set; } = "vanilla";

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

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

    [JsonPropertyName("url")]
    public string Url { get; set; } = "";

    [JsonPropertyName("sha1")]
    public string? Sha1 { get; set; }

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

    /// <summary>
    /// "both" (default), "client", or "server". The launcher skips files
    /// marked "server"; the server-tool skips files marked "client".
    /// Null/missing/unknown = treated as "both" so manifests pre-dating
    /// this field stay fully compatible.
    /// </summary>
    [JsonPropertyName("side")]
    public string? Side { get; set; }
}

public sealed class PackVersionRecord
{
    [JsonPropertyName("name")]
    public string? Name { get; set; }

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

    [JsonPropertyName("syncedAt")]
    public string? SyncedAt { get; set; }
}
