#pragma once
#include "core/result/Result.h"

#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QString>
#include <QVector>

#include <functional>

namespace fincept {

/// A single versioned migration.
struct Migration {
    int version;
    QString name;
    std::function<Result<void>(QSqlDatabase&)> apply;
};

/// Runs versioned migrations tracked in a schema_version table.
/// Migration files auto-register via static initialization.
class MigrationRunner {
  public:
    explicit MigrationRunner(QSqlDatabase& db);

    /// Apply all pending migrations in order.
    Result<void> run();

    /// Current applied schema version (0 if none).
    int current_version() const;

    /// Register a migration (called at static-init time by each v00N file).
    static void register_migration(Migration m);

    /// All registered migrations, sorted by version.
    static const QVector<Migration>& all_migrations();

  private:
    Result<void> ensure_schema_version_table();
    Result<void> apply_migration(const Migration& m);
    Result<void> record_version(int version, const QString& name);
    int read_current_version();

    QSqlDatabase& db_;
};

// Explicit registration functions — call these before Database::open()
// to ensure MSVC linker doesn't strip the migration translation units.
void register_migration_v001();
void register_migration_v002();
void register_migration_v003();
void register_migration_v004();
void register_migration_v005();
void register_migration_v006();
void register_migration_v007();
void register_migration_v008();
void register_migration_v009();
void register_migration_v010();
void register_migration_v011();
void register_migration_v012();
void register_migration_v013();
void register_migration_v014();
void register_migration_v015();
void register_migration_v016();
void register_migration_v017();
void register_migration_v018();
void register_migration_v019();
void register_migration_v020();
void register_migration_v021();
void register_migration_v022();
void register_migration_v023();
void register_migration_v024();
void register_migration_v025();
void register_migration_v026();
void register_migration_v027();
void register_migration_v028();
void register_migration_v029();
void register_migration_v030();
void register_migration_v031();
void register_migration_v032();
void register_migration_v033();
void register_migration_v034();
void register_migration_v035();
void register_migration_v036();
void register_migration_v037();
void register_migration_v038();
void register_migration_v039();
void register_migration_v040();
void register_migration_v041();
void register_migration_v042();
void register_migration_v043();
void register_migration_v044();
void register_migration_v045();
void register_migration_v046();
void register_migration_v047();
void register_migration_v048();
void register_migration_v049();
void register_migration_v050();

} // namespace fincept
