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

const mockCreate = vi.fn();
const mockUpdate = vi.fn();
const mockGenerateQuoteId = vi.fn();
const mockEnqueue = vi.fn();
const mockHandleConflict = vi.fn();

vi.mock("@/lib/prisma", () => ({
  prisma: {
    quoteRecord: {
      create: (...args: unknown[]) => mockCreate(...args),
      update: (...args: unknown[]) => mockUpdate(...args),
    },
  },
}));

vi.mock("@/modules/quote/quote-id", () => ({
  generateQuoteId: () => mockGenerateQuoteId(),
  isQuoteIdUniqueConflict: (error: unknown) =>
    typeof error === "object" &&
    error !== null &&
    (error as { code?: string }).code === "P2002",
  handleQuoteIdConflict: (...args: unknown[]) => mockHandleConflict(...args),
}));

vi.mock("@/modules/priority1/rpa-queue", () => ({
  enqueuePriority1QuoteJob: (...args: unknown[]) => mockEnqueue(...args),
}));

vi.mock("@/modules/metrics/collector", () => ({
  safeRecord: (task: () => Promise<void>) => {
    void task();
  },
  markQuoteStarted: vi.fn(),
}));

import { DEFAULT_PRIORITY1_DEMO } from "@/workers/rpa/priority1/demo-input";
import {
  Priority1EnqueueError,
  submitPriority1Quote,
} from "@/modules/priority1/orchestrator";

describe("submitPriority1Quote", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockGenerateQuoteId.mockResolvedValue("QTE_20260701_0001");
    mockCreate.mockResolvedValue({});
    mockUpdate.mockResolvedValue({});
    mockEnqueue.mockResolvedValue(undefined);
  });

  it("入队成功返回 processing", async () => {
    const result = await submitPriority1Quote({
      request_id: "req-1",
      customer_id: "CUST_001",
      priority1_input: DEFAULT_PRIORITY1_DEMO,
    });
    expect(result).toEqual({
      quote_id: "QTE_20260701_0001",
      status: "processing",
    });
    expect(mockEnqueue).toHaveBeenCalledOnce();
  });

  it("Redis 入队失败时抛出可读错误并标记 quote 失败", async () => {
    mockEnqueue.mockRejectedValue(new Error("REDIS_URL 未配置"));

    await expect(
      submitPriority1Quote({
        request_id: "req-2",
        customer_id: "CUST_001",
        priority1_input: DEFAULT_PRIORITY1_DEMO,
      }),
    ).rejects.toBeInstanceOf(Priority1EnqueueError);

    expect(mockUpdate).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { quoteId: "QTE_20260701_0001" },
        data: expect.objectContaining({
          status: "failed",
          errorCode: "QUOTE_UNAVAILABLE",
        }),
      }),
    );
  });
});
