import { getContainer } from './cosmos-init.js';
import { productId } from './config.js';

export interface Migration {
  name: string;
  version: number;
  up: () => Promise<void>;
  down: () => Promise<void>;
}

const MIGRATIONS_CONTAINER = 'migrations';

export async function ensureMigrationsContainer(): Promise<void> {
  try {
    await getContainer(MIGRATIONS_CONTAINER as any);
  } catch {
    await getContainer(MIGRATIONS_CONTAINER).create();
  }
}

export async function getAppliedMigrations(): Promise<string[]> {
  try {
    const { resources } = await getContainer(MIGRATIONS_CONTAINER)
      .items.query({
        query: 'SELECT * FROM c WHERE c.productId = @productId',
        parameters: [{ name: '@productId', value: productId }],
      })
      .fetchAll();

    return resources.map((r: any) => r.name);
  } catch {
    return [];
  }
}

export async function recordMigration(name: string, version: number): Promise<void> {
  await getContainer(MIGRATIONS_CONTAINER).items.create({
    id: `migration-${name}`,
    name,
    version,
    productId,
    appliedAt: new Date().toISOString(),
  });
}

export async function removeMigrationRecord(name: string): Promise<void> {
  try {
    const { resources } = await getContainer(MIGRATIONS_CONTAINER)
      .items.query({
        query: 'SELECT * FROM c WHERE c.name = @name AND c.productId = @productId',
        parameters: [
          { name: '@name', value: name },
          { name: '@productId', value: productId },
        ],
      })
      .fetchAll();

    if (resources.length > 0) {
      await getContainer(MIGRATIONS_CONTAINER).item(resources[0].id).delete();
    }
  } catch {
    // Ignore errors
  }
}

export async function runMigrations(migrations: Migration[]): Promise<void> {
  await ensureMigrationsContainer();

  const applied = await getAppliedMigrations();
  const pending = migrations.filter((m) => !applied.includes(m.name));

  if (pending.length === 0) {
    console.log('No pending migrations');
    return;
  }

  console.log(`Running ${pending.length} migration(s)...`);

  for (const migration of pending) {
    console.log(`Running migration: ${migration.name}`);
    try {
      await migration.up();
      await recordMigration(migration.name, migration.version);
      console.log(`✓ Migration ${migration.name} completed`);
    } catch (error) {
      console.error(`✗ Migration ${migration.name} failed:`, error);
      throw error;
    }
  }
}

export async function rollbackMigration(name: string, migrations: Migration[]): Promise<void> {
  const migration = migrations.find((m) => m.name === name);
  if (!migration) {
    throw new Error(`Migration ${name} not found`);
  }

  console.log(`Rolling back migration: ${name}`);
  try {
    await migration.down();
    await removeMigrationRecord(name);
    console.log(`✓ Migration ${name} rolled back`);
  } catch (error) {
    console.error(`✗ Rollback of ${name} failed:`, error);
    throw error;
  }
}
