import { DataSource, DataSourceOptions } from "typeorm";

/** Schemas required before TypeORM migrations and entity access. */
export const APPLICATION_SCHEMAS = [
  "public",
  "iam",
  "freight",
  "audit",
] as const;

export const APPLICATION_SEARCH_PATH = APPLICATION_SCHEMAS.join(",");

/**
 * TypeORM creates the migrations table before any migration runs. If `public` was
 * dropped, current_schema() is null and CREATE TABLE migrations fails.
 * IAM/freight migrations assume their schemas already exist.
 */
export async function ensurePostgresSchemas(
  options: DataSourceOptions,
): Promise<void> {
  const bootstrap = new DataSource({
    ...options,
    entities: [],
    migrations: [],
    migrationsRun: false,
    synchronize: false,
  });

  await bootstrap.initialize();

  for (const schema of APPLICATION_SCHEMAS) {
    if (schema === "public") {
      await bootstrap.query(`CREATE SCHEMA IF NOT EXISTS public`);
      await bootstrap.query(`GRANT ALL ON SCHEMA public TO public`);
      await bootstrap.query(`GRANT CREATE ON SCHEMA public TO public`);
    } else {
      await bootstrap.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`);
      await bootstrap.query(`GRANT USAGE ON SCHEMA "${schema}" TO public`);
      await bootstrap.query(
        `GRANT CREATE ON SCHEMA "${schema}" TO public`,
      );
    }
  }

  await bootstrap.query(
    `SET search_path TO ${APPLICATION_SEARCH_PATH}`,
  );

  await bootstrap.destroy();
}
