// src/lib/backlink/import.test.ts
// Integration test — gated on DB_TESTS=1, run against the *_test DB only.
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";

// server-only throws outside Next.js; stub it for the test runner.
mock.module("server-only", () => ({}));

const RUN_DB = process.env.DB_TESTS === "1";

describe("namespaceSourceId (pure)", () => {
  test("raw crate slug gets the org prefix", async () => {
    const { namespaceSourceId } = await import("./import");
    expect(namespaceSourceId("org-a", "x-com")).toBe("org-a__x-com");
  });

  test("already-prefixed id is left as is (no double prefix)", async () => {
    const { namespaceSourceId } = await import("./import");
    expect(namespaceSourceId("org-a", "org-a__x-com")).toBe("org-a__x-com");
  });
});

describe.skipIf(!RUN_DB)("upsertLinkSources (postgres)", () => {
  let db: typeof import("@/lib/db/client").db;
  let client: typeof import("@/lib/db/client").client;
  let schema: typeof import("@/lib/db/domain-schema");
  let auth: typeof import("@/lib/db/auth-schema");
  let helper: typeof import("./import");
  type CanonicalSource = import("./import-types").CanonicalSource;
  const ORG = "demo-org";
  const ORG_B = "demo-org-b";

  beforeEach(async () => {
    ({ db, client } = await import("@/lib/db/client"));
    schema = await import("@/lib/db/domain-schema");
    auth = await import("@/lib/db/auth-schema");
    helper = await import("./import");
    const { assertTestDb } = await import("@/lib/db/assert-test-db");
    await assertTestDb();
    await db.delete(schema.linkSources);
  });

  afterAll(async () => {
    // NB: do NOT client.end() — shared singleton; closing breaks directory runs.
    void client;
  });

  const row = (over: Partial<CanonicalSource> = {}) => ({
    id: "x-com",
    platform: "X",
    url: "https://x.com",
    domainNorm: "x.com",
    kind: "other" as const,
    da: 10,
    effort: "medium" as const,
    linkType: "dofollow" as const,
    language: "en",
    themes: [],
    tags: [],
    note: null,
    ...over,
  });

  test("inserts a new source with an org-namespaced id", async () => {
    await helper.upsertLinkSources(ORG, [row()]);
    const got = await db.select().from(schema.linkSources);
    expect(got).toHaveLength(1);
    expect(got[0].id).toBe(`${ORG}__x-com`);
    expect(got[0].platform).toBe("X");
  });

  test("updates existing but preserves flags", async () => {
    await db.insert(schema.linkSources).values({
      ...row({ da: 5 }),
      id: `${ORG}__x-com`, // stored form = namespaced
      orgId: ORG,
      flags: { toxic: true, disavow: false },
    });
    await helper.upsertLinkSources(ORG, [row({ da: 99, platform: "X2" })]);
    const [got] = await db.select().from(schema.linkSources);
    expect(got.da).toBe(99);
    expect(got.platform).toBe("X2");
    expect(got.flags).toEqual({ toxic: true, disavow: false }); // preserved
  });

  test("two orgs import the same URL — both rows exist, each org sees its own", async () => {
    await db
      .insert(auth.organization)
      .values({
        id: ORG_B,
        name: "Demo B",
        slug: "demo-org-b",
        createdAt: new Date(),
      })
      .onConflictDoNothing();
    await helper.upsertLinkSources(ORG, [row({ da: 10 })]);
    await helper.upsertLinkSources(ORG_B, [row({ da: 42 })]);
    const all = await db.select().from(schema.linkSources);
    expect(all).toHaveLength(2);
    const a = all.find((r) => r.orgId === ORG);
    const b = all.find((r) => r.orgId === ORG_B);
    expect(a?.id).toBe(`${ORG}__x-com`);
    expect(b?.id).toBe(`${ORG_B}__x-com`);
    expect(a?.da).toBe(10); // org A untouched by org B's import
    expect(b?.da).toBe(42);
  });

  test("re-import by the same org updates, not duplicates", async () => {
    await helper.upsertLinkSources(ORG, [row({ da: 10 })]);
    await helper.upsertLinkSources(ORG, [row({ da: 77 })]);
    const got = await db.select().from(schema.linkSources);
    expect(got).toHaveLength(1);
    expect(got[0].da).toBe(77);
  });

  test("bootstrap-style pre-prefixed id is not double-prefixed", async () => {
    await helper.upsertLinkSources(ORG, [row({ id: `${ORG}__x-com` })]);
    const [got] = await db.select().from(schema.linkSources);
    expect(got.id).toBe(`${ORG}__x-com`);
  });
});
