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

vi.mock("@/lib/rpa/worker-health", () => ({
  isAnyRpaWorkerHealthy: vi.fn(),
}));

vi.mock("@/lib/rpa/spawn-address-candidates", () => ({
  spawnFetchMothershipAddressCandidates: vi.fn(),
}));

vi.mock("@/workers/rpa/queue", () => ({
  addAddressCandidatesJob: vi.fn(),
}));

const redisGet = vi.fn();

vi.mock("@/lib/redis", () => ({
  ensureRedisReady: vi.fn().mockResolvedValue(undefined),
  getRedis: vi.fn(() => ({
    setex: vi.fn().mockResolvedValue("OK"),
    get: redisGet,
  })),
  resetRedisClient: vi.fn(),
}));

import { spawnFetchMothershipAddressCandidates } from "@/lib/rpa/spawn-address-candidates";
import { isAnyRpaWorkerHealthy } from "@/lib/rpa/worker-health";
import { requestMothershipCandidatesViaWorker } from "@/modules/address/candidates-queue";
import { addAddressCandidatesJob } from "@/workers/rpa/queue";

const input = {
  pickup: {
    street: "1234 Warehouse Blvd",
    city: "Los Angeles",
    state: "CA",
    zip: "90001",
  },
  delivery: {
    street: "5678 Distribution Dr",
    city: "Dallas",
    state: "TX",
    zip: "75201",
  },
};

const mockResult = {
  pickup_candidates: [{ display_label: "A", option_id: "1" }],
  delivery_candidates: [{ display_label: "B", option_id: "2" }],
  requires_selection: false,
};

describe("requestMothershipCandidatesViaWorker", () => {
  afterEach(() => {
    vi.clearAllMocks();
    redisGet.mockReset();
    delete process.env.RPA_QUEUE_ENABLED;
  });

  it("Worker 无心跳时默认走 spawn", async () => {
    delete process.env.RPA_PARKED_SESSION;
    vi.mocked(isAnyRpaWorkerHealthy).mockResolvedValue(false);
    vi.mocked(spawnFetchMothershipAddressCandidates).mockResolvedValue(
      mockResult,
    );

    const result = await requestMothershipCandidatesViaWorker(input);

    expect(result).toEqual(mockResult);
    expect(spawnFetchMothershipAddressCandidates).toHaveBeenCalledWith(input);
  });

  it("Worker 无心跳且 RPA_PARKED_SESSION=true 时抛错", async () => {
    process.env.RPA_QUEUE_ENABLED = "true";
    process.env.RPA_PARKED_SESSION = "true";
    vi.mocked(isAnyRpaWorkerHealthy).mockResolvedValue(false);

    await expect(requestMothershipCandidatesViaWorker(input)).rejects.toMatchObject(
      { code: "PAGE_LOAD_TIMEOUT" },
    );
    expect(spawnFetchMothershipAddressCandidates).not.toHaveBeenCalled();
  });

  it("Worker 有心跳时只走队列等待结果，不 spawn", async () => {
    process.env.RPA_QUEUE_ENABLED = "true";
    vi.mocked(isAnyRpaWorkerHealthy).mockResolvedValue(true);
    vi.mocked(addAddressCandidatesJob).mockResolvedValue(undefined);
    redisGet
      .mockResolvedValueOnce(null)
      .mockResolvedValueOnce(
        JSON.stringify({ ok: true, data: mockResult }),
      );

    const result = await requestMothershipCandidatesViaWorker(input);

    expect(result).toEqual(mockResult);
    expect(addAddressCandidatesJob).toHaveBeenCalled();
    expect(spawnFetchMothershipAddressCandidates).not.toHaveBeenCalled();
  });
});
