using Metin2Launcher.Logging;
using Metin2Launcher.Manifest;
using Metin2Launcher.Runtime;

namespace Metin2Launcher.Formats;

/// <summary>
/// m2pack release format.
///
/// The manifest still has a flat <c>files</c> list, but the entries are now
/// content-addressed <c>.m2p</c> archives plus a <c>runtime-key.json</c>
/// sidecar. Signing continues to happen on the top-level <c>manifest.json</c>
/// — the <c>.m2p</c> files are each a single sha256 entry, and the launcher
/// NEVER opens them. Decryption, decompression and integrity of the contents
/// is the game client's problem, gated on the runtime key this class loads.
///
/// The runtime-key.json sidecar is listed in the manifest like any other file
/// and goes through the same sha256 round trip, so tamper resistance of the
/// key itself comes from the Ed25519 signature over the enclosing manifest.
/// </summary>
public sealed class M2PackFormat : IReleaseFormat
{
    public const string FormatName = "m2pack";

    /// <summary>Conventional filename of the runtime key sidecar inside the client root.</summary>
    public const string RuntimeKeyFileName = "runtime-key.json";

    public string Name => FormatName;

    public IReadOnlyList<ManifestFile> FilterApplicable(Manifest.Manifest manifest, string platform)
    {
        // Same platform filter as legacy; runtime-key.json is platform=all by convention.
        return manifest.Files.Where(f => f.AppliesTo(platform)).ToList();
    }

    public void OnApplied(string clientRoot, LoadedManifest manifest, ReleaseOutcome outcome)
    {
        var keyPath = Path.Combine(clientRoot, RuntimeKeyFileName);
        if (!File.Exists(keyPath))
        {
            // An m2pack manifest without a runtime-key.json is a release-tool bug,
            // but we don't hard-fail here: the game will refuse to start without the
            // env vars and surface the real error to the user with better context.
            Log.Warn($"m2pack: runtime key file not found at {keyPath}");
            return;
        }

        try
        {
            outcome.RuntimeKey = RuntimeKey.Load(keyPath);
            Log.Info($"m2pack: loaded runtime key {outcome.RuntimeKey.KeyId}");
        }
        catch (Exception ex)
        {
            Log.Error($"m2pack: failed to parse runtime key {keyPath}", ex);
            throw;
        }
    }
}
