import { describe, it, expect, vi, beforeEach } from "vitest";
import { createRequest, parseJsonResponse } from "@/__tests__/helpers/api-test-utils";

vi.mock("@/lib/prisma", () => ({
  prisma: {},
}));

vi.mock("@/lib/roomRepository", () => ({
  createRoom: vi.fn().mockResolvedValue("ROOM01"),
}));

vi.mock("@/lib/amap", () => ({
  requireAmapApiKey: vi.fn().mockReturnValue("test-key"),
}));

const mockFetch = vi.fn();
vi.stubGlobal("fetch", mockFetch);

import { POST } from "./route";
import { createRoom } from "@/lib/roomRepository";

const mockCtx = { params: Promise.resolve({}) };

beforeEach(() => {
  vi.clearAllMocks();
});

describe("POST /api/room/create", () => {
  it("creates a room with restaurants from Amap", async () => {
    mockFetch.mockResolvedValue({
      json: () =>
        Promise.resolve({
          status: "1",
          pois: [
            {
              id: "poi-1",
              name: "好吃餐厅",
              distance: "300",
              type: "餐饮服务;中餐厅;川菜",
              address: "测试路1号",
              location: "121.4,31.2",
              business: { rating: "4.5", cost: "80" },
              photos: [{ url: "https://img.example.com/1.jpg" }],
            },
          ],
        }),
    });

    const req = createRequest("/api/room/create", {
      method: "POST",
      body: { lat: 31.2, lng: 121.4, userId: "user-1" },
    });
    const res = await POST(req, mockCtx);
    const { status, data } = await parseJsonResponse(res);

    expect(status).toBe(200);
    expect(data.roomId).toBe("ROOM01");
    expect(data.restaurants).toHaveLength(1);
    expect(data.restaurants[0].name).toBe("好吃餐厅");
    expect(createRoom).toHaveBeenCalled();
  });

  it("returns 400 for invalid coordinates", async () => {
    const req = createRequest("/api/room/create", {
      method: "POST",
      body: { lat: "invalid", lng: 121.4, userId: "user-1" },
    });
    const res = await POST(req, mockCtx);
    expect(res.status).toBe(400);
  });

  it("returns 400 for out-of-range coordinates", async () => {
    const req = createRequest("/api/room/create", {
      method: "POST",
      body: { lat: 100, lng: 121.4, userId: "user-1" },
    });
    const res = await POST(req, mockCtx);
    expect(res.status).toBe(400);
  });

  it("returns 404 when no restaurants found", async () => {
    mockFetch.mockResolvedValue({
      json: () => Promise.resolve({ status: "1", pois: [] }),
    });

    const req = createRequest("/api/room/create", {
      method: "POST",
      body: { lat: 31.2, lng: 121.4, userId: "user-1" },
    });
    const res = await POST(req, mockCtx);
    expect(res.status).toBe(404);
  });

  it("returns 503 when Amap API fails", async () => {
    mockFetch.mockRejectedValue(new Error("network error"));

    const req = createRequest("/api/room/create", {
      method: "POST",
      body: { lat: 31.2, lng: 121.4, userId: "user-1" },
    });
    const res = await POST(req, mockCtx);
    expect(res.status).toBe(503);
  });

  it("filters restaurants by price range", async () => {
    mockFetch.mockResolvedValue({
      json: () =>
        Promise.resolve({
          status: "1",
          pois: [
            {
              id: "poi-1",
              name: "便宜店",
              location: "121.4,31.2",
              business: { cost: "30" },
            },
            {
              id: "poi-2",
              name: "贵店",
              location: "121.4,31.2",
              business: { cost: "150" },
            },
          ],
        }),
    });

    const req = createRequest("/api/room/create", {
      method: "POST",
      body: { lat: 31.2, lng: 121.4, userId: "user-1", priceRange: "under50" },
    });
    const res = await POST(req, mockCtx);
    const { data } = await parseJsonResponse(res);

    expect(data.restaurants).toHaveLength(1);
    expect(data.restaurants[0].name).toBe("便宜店");
  });
});
