import { ensureTestDBExists } from "../../__tests__/internal/ensureTestDBExists";
import { mockTestStd } from "../../__tests__/internal/mockTestStd";
import { getSchemaName } from "../../internal/getSchemaName";
import { listActiveSchemas } from "../../internal/listActiveSchemas";
import { promiseAll } from "../../internal/promiseAll";
import { sql } from "../../internal/quote";
import { runSql } from "../../internal/runSql";
import { move } from "../move";

let fromDsn: string;
let toDsn: string;

beforeEach(async () => {
  [fromDsn, toDsn] = await promiseAll([
    ensureTestDBExists({
      from: 1,
      to: 1,
      state: "active",
    }),
    ensureTestDBExists({
      dbNameSuffix: "to",
    }),
  ]);
});

(process.env["IN_JEST_PROJECT"] ? test.skip : test)(
  "move a microshard with tables",
  async () => {
    const out = mockTestStd();
    try {
      await runSql(
        fromDsn,
        sql`
          CREATE TABLE sh0001.tbl(id bigserial PRIMARY KEY, s text);
          INSERT INTO sh0001.tbl(s)
            SELECT s::text FROM generate_series(1, 1000) AS s;

          CREATE TABLE sh0001."weirdly""named;tbl"(id bigserial PRIMARY KEY, s text);
          INSERT INTO sh0001."weirdly""named;tbl"(s)
            SELECT s::text FROM generate_series(1, 1000) AS s;

          CREATE TABLE sh0001.partitioned_tbl(
            grp bigint,
            idx numeric(64, 32),
            PRIMARY KEY (grp, idx)
          ) PARTITION BY HASH (grp);
          CREATE TABLE sh0001.partitioned_tbl_p0
            PARTITION OF sh0001.partitioned_tbl
            FOR VALUES WITH (MODULUS 2, REMAINDER 0);
          CREATE TABLE sh0001.partitioned_tbl_p1
            PARTITION OF sh0001.partitioned_tbl
            FOR VALUES WITH (MODULUS 2, REMAINDER 1);
          INSERT INTO sh0001.partitioned_tbl(grp, idx)
            SELECT s, s FROM generate_series(1, 1000) AS s;
        `,
      );
      await move({
        schema: await getSchemaName(fromDsn, 1),
        fromDsn,
        toDsn,
        commitAction: "deactivate-activate",
      });
      expect(await listActiveSchemas({ dsn: toDsn })).toEqual(["sh0001"]);
      expect(await listActiveSchemas({ dsn: fromDsn })).toEqual([]);
      expect(
        await runSql.one(toDsn, sql`SELECT count(1) FROM sh0001.tbl`),
      ).toEqual("1000");
      expect(
        Number(
          await runSql.one(toDsn, sql`SELECT nextval('sh0001.tbl_id_seq')`),
        ),
      ).toBeGreaterThan(1500);
      expect(
        await runSql.one(
          toDsn,
          sql`SELECT count(1) FROM sh0001."weirdly""named;tbl"`,
        ),
      ).toEqual("1000");
      expect(
        await runSql.one(
          toDsn,
          sql`SELECT count(1) FROM sh0001.partitioned_tbl`,
        ),
      ).toEqual("1000");
      expect(out.stdout).toMatch(/ALTER SUBSCRIPTION.*ENABLE/m);
    } catch (e: unknown) {
      out.print();
      throw e;
    }
  },
);
