import type { TableInfo } from "./getTablesInSchema";
import { isNameInSql } from "./isNameInSql";

/**
 * Validates that the list of primary keys extracted from the dump earlier match
 * the actual list of tables read from pg_catalog. This is mainly for sanity
 * checking the dump parsing logic.
 */
export function validatePrimaryKeysFromDump({
  primaryKeys,
  allTables,
}: {
  primaryKeys: string[];
  allTables: TableInfo[];
}): void {
  const tablesWithoutIdentity = allTables.filter((table) => !table.identity);
  if (tablesWithoutIdentity.length > 0) {
    throw (
      "To be moved, every table in the schema must have a PRIMARY KEY " +
      "constraint (or an unique index marked as REPLICA IDENTITY). " +
      "Please add primary keys or unique indexes to the following tables:\n" +
      tablesWithoutIdentity.map(({ name }) => `- ${name}`).join("\n")
    );
  }

  const tables = allTables as Array<
    TableInfo & { identity: NonNullable<TableInfo["identity"]> }
  >;

  const tablesWithoutDumpEntries = tables.filter(
    (table) =>
      !primaryKeys.some((primaryKeySql) =>
        isNameInSql(table.identity.indexName, primaryKeySql),
      ),
  );
  if (tablesWithoutDumpEntries.length > 0) {
    throw (
      "Some PRIMARY KEY constraints (or unique indexes marked as REPLICA IDENTITY) " +
      "are not found in the parsed post-data section of the dump. Is there a bug " +
      "in dump parsing logic? Missing indexes:\n" +
      tablesWithoutDumpEntries
        .map(({ name, identity }) => `- ${identity.indexName} (table ${name})`)
        .join("\n")
    );
  }

  const dumpEntriesWithoutTables = primaryKeys.filter(
    (primaryKeySql) =>
      !tables.some((table) =>
        isNameInSql(table.identity.indexName, primaryKeySql),
      ),
  );
  if (dumpEntriesWithoutTables.length > 0) {
    throw (
      "After parsing the post-data section of the dump, some entries related to " +
      "PRIMARY KEY constraints (or unique indexes marked as REPLICA IDENTITY) did " +
      "not match the indexes in the schema. Is there a bug in dump parsing logic? " +
      "Entries related to unknown indexes:\n" +
      dumpEntriesWithoutTables
        .map((entry) => `- ${entry.replace(/\s+/g, " ").trim()}`)
        .join("\n")
    );
  }
}
