import { describe, it, expect, vi } from "vitest";
import { upsertMerkmalValues } from "../upsertValues";
import type { MerkmalValueInput } from "@/lib/merkmale/types";

/**
 * Test-Double für die Drizzle-Transaktion. Es zeichnet nur auf, wie oft
 * delete/insert aufgerufen wurden — kein echtes Postgres. `upsertMerkmalValues`
 * ruft pro Wert genau ein `delete(...).where(...)` und (bei nicht-leerem Wert)
 * ein `insert(...).values(...)`.
 */
function makeFakeTx() {
  const deletes: unknown[] = [];
  const inserts: Record<string, unknown>[] = [];
  const tx = {
    delete: vi.fn(() => ({
      where: vi.fn(async (cond: unknown) => {
        deletes.push(cond);
      }),
    })),
    insert: vi.fn(() => ({
      values: vi.fn(async (v: Record<string, unknown>) => {
        inserts.push(v);
      }),
    })),
  };
  return { tx, deletes, inserts };
}

const MID = "11111111-1111-1111-1111-111111111111";

describe("upsertMerkmalValues", () => {
  it("löscht alten Wert und fügt neuen ein (delete-then-insert)", async () => {
    const { tx, deletes, inserts } = makeFakeTx();
    const werte: MerkmalValueInput[] = [{ merkmalId: MID, num: 2000 }];
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    await upsertMerkmalValues(tx as any, "vehicle", "veh-1", werte);
    expect(deletes).toHaveLength(1);
    expect(inserts).toHaveLength(1);
    expect(inserts[0]).toMatchObject({
      merkmalId: MID,
      entityTyp: "vehicle",
      entityId: "veh-1",
      valueNum: 2000,
      valueText: null,
      valueBool: null,
    });
  });

  it("schreibt bei leerem Wert nur delete, kein insert", async () => {
    const { tx, deletes, inserts } = makeFakeTx();
    const werte: MerkmalValueInput[] = [
      { merkmalId: MID, num: null, text: "", bool: null },
    ];
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    await upsertMerkmalValues(tx as any, "vehicle", "veh-1", werte);
    expect(deletes).toHaveLength(1);
    expect(inserts).toHaveLength(0);
  });

  it("schreibt boolean false als Wert (nicht als leer behandelt)", async () => {
    const { tx, inserts } = makeFakeTx();
    const werte: MerkmalValueInput[] = [{ merkmalId: MID, bool: false }];
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    await upsertMerkmalValues(tx as any, "equipment", "eq-1", werte);
    expect(inserts).toHaveLength(1);
    expect(inserts[0]).toMatchObject({ valueBool: false, valueNum: null, valueText: null });
  });
});
