import type { OneboxDatabase } from '../ts/database/index.js';
import { runValkeyPlatformRenameMigration } from './valkey-platform-rename.js';
import { runCoreTrafficPlatformRenameMigration } from './coretraffic-platform-rename.js';
import { runServiceTargetPortsMigration } from './service-target-ports.js';
import { runServiceRuntimeOptionalsMigration } from './service-runtime-optionals.js';
import { runRuntimeSecretExtractionMigration } from './runtime-secret-extraction.js';
import { runPasskeyOnlyAuthMigration } from './passkey-only-auth.js';

interface IStartupMigration {
  id: string;
  metadataKey: string;
  run(databaseArg: OneboxDatabase): Promise<void>;
}

const getMetadata = async (databaseArg: OneboxDatabase, keyArg: string): Promise<string | null> => {
  const doc = await databaseArg.CMetadata.getInstance({ key: keyArg });
  return doc?.value ?? null;
};

const setMetadata = async (
  databaseArg: OneboxDatabase,
  keyArg: string,
  valueArg: string,
): Promise<void> => {
  const now = Date.now();
  let doc = await databaseArg.CMetadata.getInstance({ key: keyArg });
  if (!doc) {
    doc = new databaseArg.CMetadata();
    doc.key = keyArg;
  }
  doc.value = valueArg;
  doc.updatedAt = now;
  await doc.save();
};

export const runStartupMigrations = async (
  databaseArg: OneboxDatabase,
): Promise<void> => {
  const migrations: IStartupMigration[] = [
    {
      id: 'valkey-platform-rename',
      metadataKey: 'valkeyPlatformRenameComplete',
      run: runValkeyPlatformRenameMigration,
    },
    {
      id: 'coretraffic-platform-rename',
      metadataKey: 'coreTrafficPlatformRenameComplete',
      run: runCoreTrafficPlatformRenameMigration,
    },
    {
      id: 'service-target-ports',
      metadataKey: 'serviceTargetPortsMigrationComplete',
      run: runServiceTargetPortsMigration,
    },
    {
      id: 'runtime-secret-extraction',
      metadataKey: 'runtimeSecretExtractionComplete',
      run: runRuntimeSecretExtractionMigration,
    },
    {
      id: 'service-runtime-optionals',
      metadataKey: 'serviceRuntimeOptionalsMigrationComplete',
      run: runServiceRuntimeOptionalsMigration,
    },
    {
      id: 'passkey-only-auth',
      metadataKey: 'passkeyOnlyAuthMigrationComplete',
      run: runPasskeyOnlyAuthMigration,
    },
  ];

  for (const migration of migrations) {
    if ((await getMetadata(databaseArg, migration.metadataKey)) === 'true') {
      continue;
    }
    await migration.run(databaseArg);
    await setMetadata(databaseArg, migration.metadataKey, 'true');
  }
};
