// Integration — DB_TESTS=1, *_test uniquement. Valide le provisioning
// idempotent des partitions GSC (audit P4, drizzle/0059) :
// ensure_gsc_partitions() crée les partitions manquantes des N prochains
// mois pour gsc_query_snapshots ET gsc_page_snapshots, se rejoue sans erreur
// une fois qu'elles existent déjà, et gsc_default_partition_rowcounts()
// (canari) détecte une ligne tombée dans DEFAULT faute de partition dédiée.
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";

mock.module("server-only", () => ({}));

const RUN = process.env.DB_TESTS === "1";
const NOW = new Date();
const ORG = "gscp-prov-org";
const OWNER = "gscp-prov-owner";
const SITE = "gscp-prov-site";

/** "YYYY_MM" du mois courant + `offset` mois — même convention que 0050. */
function monthTag(offset: number): string {
  const d = new Date(
    Date.UTC(NOW.getUTCFullYear(), NOW.getUTCMonth() + offset, 1),
  );
  const y = d.getUTCFullYear();
  const m = String(d.getUTCMonth() + 1).padStart(2, "0");
  return `${y}_${m}`;
}

describe.skipIf(!RUN)(
  "ensure_gsc_partitions / canari DEFAULT (postgres)",
  () => {
    // biome-ignore lint/suspicious/noExplicitAny: imports dynamiques de test
    let db: any;
    // biome-ignore lint/suspicious/noExplicitAny: imports dynamiques de test
    let authSchema: any;
    // biome-ignore lint/suspicious/noExplicitAny: imports dynamiques de test
    let domain: any;
    // biome-ignore lint/suspicious/noExplicitAny: imports dynamiques de test
    let sqlTag: any;

    async function cleanup() {
      const { inArray } = await import("drizzle-orm");
      await db
        .delete(authSchema.organization)
        .where(inArray(authSchema.organization.id, [ORG]));
      await db
        .delete(authSchema.user)
        .where(inArray(authSchema.user.id, [OWNER]));
    }

    beforeEach(async () => {
      ({ db } = await import("@/lib/db/client"));
      authSchema = await import("@/lib/db/auth-schema");
      domain = await import("@/lib/db/domain-schema");
      ({ sql: sqlTag } = await import("drizzle-orm"));
      const { assertTestDb } = await import("@/lib/db/assert-test-db");
      await assertTestDb();
      await cleanup();
      await db.insert(authSchema.user).values({
        id: OWNER,
        name: OWNER,
        email: `${OWNER}@test.dev`,
        emailVerified: true,
        createdAt: NOW,
        updatedAt: NOW,
      });
      await db
        .insert(authSchema.organization)
        .values({ id: ORG, name: ORG, slug: ORG, createdAt: NOW });
      await db.insert(domain.sites).values({
        id: SITE,
        orgId: ORG,
        ownerUserId: OWNER,
        name: "GSC partition provisioning test",
        primaryLanguage: "fr",
        createdAt: NOW,
      });
    });

    afterAll(async () => {
      if (!RUN) return;
      await cleanup();
    });

    test("crée les partitions des N prochains mois pour les deux tables", async () => {
      await db.execute(sqlTag`select * from ensure_gsc_partitions(3)`);

      for (const table of ["gsc_query_snapshots", "gsc_page_snapshots"]) {
        for (let offset = 0; offset <= 3; offset++) {
          const childName = `${table}_${monthTag(offset)}`;
          const rows = await db.execute(
            sqlTag`select 1 from pg_inherits inh
                    join pg_class child on child.oid = inh.inhrelid
                    join pg_class par on par.oid = inh.inhparent
                    where par.relname = ${table} and child.relname = ${childName}`,
          );
          expect(rows.length).toBe(1);
        }
      }
    });

    test("rejeu idempotent : aucune erreur, tout est déjà 'exists'", async () => {
      // Le mois courant +0..3 a déjà été provisionné par le test précédent
      // (partitions globales, pas de reset entre tests) — ce rejeu ne doit
      // rien créer et ne doit pas lever d'exception.
      await db.execute(sqlTag`select * from ensure_gsc_partitions(3)`);
      const second = (await db.execute(
        sqlTag`select * from ensure_gsc_partitions(3)`,
        // biome-ignore lint/suspicious/noExplicitAny: ligne brute pg
      )) as any[];
      expect(second.length).toBeGreaterThan(0);
      expect(second.every((r) => r.action === "exists")).toBe(true);
    });

    test("ligne hors horizon → partition DEFAULT → canari la détecte", async () => {
      await db.insert(domain.gscQuerySnapshots).values({
        siteId: SITE,
        date: "2099-01-01",
        query: "canary-provisioning-test",
        clicks: 0,
        impressions: 0,
        ctr: 0,
        position: 0,
      });

      const [routed] = await db.execute(
        sqlTag`select count(*)::int as n from gsc_query_snapshots_default where site_id = ${SITE}`,
      );
      expect(routed?.n).toBe(1);

      const canary = (await db.execute(
        sqlTag`select * from gsc_default_partition_rowcounts()`,
        // biome-ignore lint/suspicious/noExplicitAny: lignes brutes pg
      )) as any[];
      const queryDefault = canary.find(
        (r) => r.partition_name === "gsc_query_snapshots_default",
      );
      expect(Number(queryDefault?.row_count)).toBeGreaterThan(0);

      // Le canari constate la fuite mais ne corrige rien tout seul : DEFAULT
      // ne se vide pas de lui-même (cf. runbook § remédiation).
      const [stillThere] = await db.execute(
        sqlTag`select count(*)::int as n from gsc_query_snapshots_default where site_id = ${SITE}`,
      );
      expect(stillThere?.n).toBe(1);
    });
  },
);
