import pg from "pg";

const { Client } = pg;

if (!process.env.DATABASE_URL) {
  throw new Error(
    "DATABASE_URL must be set. Did you forget to provision a database?",
  );
}

async function tableExists(client: pg.Client, table: string): Promise<boolean> {
  const result = await client.query(
    `SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = $1`,
    [table],
  );
  return (result.rowCount ?? 0) > 0;
}

async function main(): Promise<void> {
  const client = new Client({ connectionString: process.env.DATABASE_URL });
  await client.connect();
  try {
    await client.query("BEGIN");

    if (await tableExists(client, "app_permissions")) {
      const dupes = await client.query(
        `SELECT
           count(*)::int AS dup_groups,
           coalesce(sum(c - 1), 0)::int AS extra_rows
         FROM (
           SELECT app_id, permission_id, count(*) AS c
             FROM app_permissions
            GROUP BY app_id, permission_id
           HAVING count(*) > 1
         ) d`,
      );
      const dupGroups = (dupes.rows[0]?.dup_groups ?? 0) as number;
      const extraRows = (dupes.rows[0]?.extra_rows ?? 0) as number;
      if (dupGroups > 0) {
        await client.query(
          `CREATE TEMP TABLE app_permissions_dedup ON COMMIT DROP AS
             SELECT DISTINCT app_id, permission_id FROM app_permissions`,
        );
        await client.query(`DELETE FROM app_permissions`);
        await client.query(
          `INSERT INTO app_permissions (app_id, permission_id)
             SELECT app_id, permission_id FROM app_permissions_dedup`,
        );
        console.log(
          `[pre-push] Removed ${extraRows} duplicate app_permissions row(s) across ${dupGroups} (app_id, permission_id) key(s).`,
        );
      } else {
        console.log("[pre-push] app_permissions has no duplicates.");
      }
    } else {
      console.log("[pre-push] app_permissions table not present yet — skipping dedup.");
    }

    if (
      (await tableExists(client, "executive_meeting_notifications")) &&
      (await tableExists(client, "executive_meetings"))
    ) {
      const orphan = await client.query(
        `DELETE FROM executive_meeting_notifications n
          WHERE n.meeting_id IS NOT NULL
            AND NOT EXISTS (
              SELECT 1 FROM executive_meetings m WHERE m.id = n.meeting_id
            )`,
      );
      const removed = orphan.rowCount ?? 0;
      if (removed > 0) {
        console.log(
          `[pre-push] Removed ${removed} orphan executive_meeting_notifications row(s).`,
        );
      } else {
        console.log("[pre-push] No orphan executive_meeting_notifications rows.");
      }
    } else {
      console.log(
        "[pre-push] executive_meeting_notifications/executive_meetings not both present — skipping orphan cleanup.",
      );
    }

    await client.query("COMMIT");
  } catch (err) {
    await client.query("ROLLBACK").catch(() => {});
    throw err;
  } finally {
    await client.end();
  }
}

main().catch((err) => {
  console.error("[pre-push] cleanup failed:", err);
  process.exit(1);
});
