import { beforeEach, describe, expect, it, vi } from "vitest";

const { mockOptima, mockJson, mockError } = vi.hoisted(() => ({
  mockOptima: {
    sales: { createOpportunity: vi.fn() },
  },
  mockJson: vi.fn((data, init?) => {
    return new Response(JSON.stringify(data), {
      status: init?.status ?? 200,
    });
  }),
  mockError: vi.fn((status: number, message: string) => {
    throw { status, body: { message } };
  }),
}));

vi.mock("$lib", () => ({ optima: mockOptima }));
vi.mock("@sveltejs/kit", () => ({ json: mockJson, error: mockError }));

import { POST } from "./+server";

describe("POST /api/sales/opportunities", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.spyOn(console, "error").mockImplementation(() => {});
  });

  it("throws 401 when no access token", async () => {
    const event = {
      locals: {},
      request: {
        json: vi
          .fn()
          .mockResolvedValue({ name: "Deal", expectedCloseDate: "2026-12-01" }),
      },
    };

    await expect(POST(event as any)).rejects.toEqual(
      expect.objectContaining({ status: 401 })
    );
  });

  it("throws 400 when name is missing", async () => {
    const event = {
      locals: { session: { accessToken: "tok" } },
      request: {
        json: vi
          .fn()
          .mockResolvedValue({ name: "", expectedCloseDate: "2026-12-01" }),
      },
    };

    await expect(POST(event as any)).rejects.toEqual(
      expect.objectContaining({ status: 400 })
    );
  });

  it("throws 400 when expectedCloseDate is missing", async () => {
    const event = {
      locals: { session: { accessToken: "tok" } },
      request: {
        json: vi.fn().mockResolvedValue({ name: "Deal" }),
      },
    };

    await expect(POST(event as any)).rejects.toEqual(
      expect.objectContaining({ status: 400 })
    );
  });

  it("creates opportunity successfully", async () => {
    const created = { id: "opp-1", name: "Big Deal" };
    mockOptima.sales.createOpportunity.mockResolvedValueOnce(created);

    const event = {
      locals: { session: { accessToken: "tok" } },
      request: {
        json: vi.fn().mockResolvedValue({
          name: "Big Deal",
          expectedCloseDate: "2026-12-01",
          notes: "Some notes",
        }),
      },
    };

    await POST(event as any);

    expect(mockOptima.sales.createOpportunity).toHaveBeenCalledWith("tok", {
      name: "Big Deal",
      expectedCloseDate: "2026-12-01",
      notes: "Some notes",
      type: undefined,
      stage: undefined,
      status: undefined,
      priority: undefined,
      interest: undefined,
      primarySalesRep: undefined,
      secondarySalesRep: undefined,
      company: undefined,
      contact: undefined,
      source: undefined,
      customerPO: undefined,
    });
    expect(mockJson).toHaveBeenCalledWith(created, { status: 201 });
  });

  it("returns error status from API failure", async () => {
    mockOptima.sales.createOpportunity.mockRejectedValueOnce({
      status: 422,
      response: { data: { message: "Validation error" } },
    });

    const event = {
      locals: { session: { accessToken: "tok" } },
      request: {
        json: vi.fn().mockResolvedValue({
          name: "Deal",
          expectedCloseDate: "2026-12-01",
        }),
      },
    };

    await expect(POST(event as any)).rejects.toBeDefined();
  });
});
