namespace Theriapolis.Core.Persistence.SaveMigrations;

/// <summary>
/// Registry + chain runner for SaveBody migrations. Phase 4 is the v4 baseline;
/// older versions are not supported because nothing earlier shipped. As we
/// bump the schema in Phase 5+, register migrations here.
///
/// The registry seeds itself with every built-in migration on first use, so
/// callers don't need to remember to <see cref="Register"/> them at startup.
/// </summary>
public static class Migrations
{
    private static readonly List<ISaveMigration> _registry = new();
    private static bool _seeded;

    public static void Register(ISaveMigration m)
    {
        EnsureSeeded();
        _registry.Add(m);
    }

    private static void EnsureSeeded()
    {
        if (_seeded) return;
        _seeded = true;
        // Built-in migrations registered in version order:
        _registry.Add(new V5ToV6Migration());
        _registry.Add(new V6ToV7Migration());
        _registry.Add(new V7ToV8Migration());
    }

    /// <summary>
    /// Walk migrations from header.Version up to C.SAVE_SCHEMA_VERSION. Returns
    /// false if no chain exists; the caller decides whether to hard-block or
    /// best-effort the load (see SaveCodec docs).
    /// </summary>
    public static bool MigrateUp(SaveHeader header, SaveBody body)
    {
        EnsureSeeded();
        while (header.Version < C.SAVE_SCHEMA_VERSION)
        {
            var step = _registry.FirstOrDefault(m => m.FromVersion == header.Version);
            if (step is null) return false;
            step.Apply(header, body);
            header.Version = step.ToVersion;
        }
        return header.Version == C.SAVE_SCHEMA_VERSION;
    }
}
