import { describe, expect, it, vi } from "vitest";
import { deletePibiRequest, PIBI_ORDERED_TEXT_PROP } from "./deletePibiRequest";
import type { RunDeletePibiTx, SyncMeasuresField } from "./deletePibiRequest";

function makeDeps(overrides?: {
  txResult?: { remainingMeasureNames: string[] };
  txError?: Error;
  syncResult?: { ok: true } | { ok: false; error: string };
}) {
  const txResult = overrides?.txResult ?? { remainingMeasureNames: ["ASHP"] };

  const runDeleteTx: RunDeletePibiTx = vi.fn(async () => {
    if (overrides?.txError) throw overrides.txError;
    return txResult;
  });

  const syncMeasuresField: SyncMeasuresField = vi.fn(async () => {
    return overrides?.syncResult ?? ({ ok: true } as const);
  });

  return { runDeleteTx, syncMeasuresField };
}

describe("deletePibiRequest — happy path", () => {
  it("deletes row, re-syncs remaining deal measures to HubSpot", async () => {
    const deps = makeDeps({
      txResult: { remainingMeasureNames: ["ASHP"] },
    });

    const result = await deletePibiRequest({
      id: 7n,
      dealId: "deal-1",
      deps,
    });

    expect(result).toEqual({ ok: true, hubspotSync: "ok" });

    expect(deps.runDeleteTx).toHaveBeenCalledWith({ id: 7n, dealId: "deal-1" });

    expect(deps.syncMeasuresField).toHaveBeenCalledWith({
      hubspotDealId: "deal-1",
      propName: PIBI_ORDERED_TEXT_PROP,
      measureNames: ["ASHP"],
    });
  });

  it("syncs empty list when last PIBI is deleted", async () => {
    const deps = makeDeps({ txResult: { remainingMeasureNames: [] } });

    const result = await deletePibiRequest({ id: 1n, dealId: "deal-2", deps });

    expect(result).toEqual({ ok: true, hubspotSync: "ok" });
    expect(deps.syncMeasuresField).toHaveBeenCalledWith({
      hubspotDealId: "deal-2",
      propName: PIBI_ORDERED_TEXT_PROP,
      measureNames: [],
    });
  });
});

describe("deletePibiRequest — DB failure", () => {
  it("returns ok=false, skips HubSpot when tx throws", async () => {
    const deps = makeDeps({ txError: new Error("row not found") });

    const result = await deletePibiRequest({ id: 99n, dealId: "deal-x", deps });

    expect(result).toEqual({ ok: false, error: "row not found" });
    expect(deps.syncMeasuresField).not.toHaveBeenCalled();
  });
});

describe("deletePibiRequest — HubSpot failure", () => {
  it("returns ok=true with hubspotSync=failed", async () => {
    const deps = makeDeps({
      syncResult: { ok: false, error: "hubspot down" },
    });

    const result = await deletePibiRequest({ id: 5n, dealId: "deal-h", deps });

    expect(result).toMatchObject({
      ok: true,
      hubspotSync: "failed",
      hubspotError: "hubspot down",
    });
  });
});
