import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import React from "react";
import { ToastContext, type ToastContextValue } from "@/hooks/useToast";

vi.mock("next/navigation", () => ({
  useRouter: () => ({
    push: vi.fn(),
    back: vi.fn(),
  }),
  useParams: () => ({ code: "ABC123" }),
}));

vi.mock("@/lib/userId", () => ({
  getCachedProfile: vi.fn().mockReturnValue({ id: "u1", username: "test", avatar: "🐱" }),
  isRegistered: vi.fn().mockReturnValue(true),
}));

vi.mock("@/hooks/useShare", () => ({
  useShare: () => ({
    copyToClipboard: vi.fn().mockResolvedValue(true),
    share: vi.fn(),
  }),
}));

vi.mock("canvas-confetti", () => ({
  default: vi.fn(),
}));

vi.mock("@/components/ShareCardModal", () => ({
  default: () => null,
}));

vi.mock("@/components/ContractCompletionModal", () => ({
  default: () => null,
}));

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

import BlindboxCodePage from "./page";

const toastCtx: ToastContextValue = { show: vi.fn() };

function renderPage() {
  return render(
    React.createElement(
      ToastContext.Provider,
      { value: toastCtx },
      React.createElement(BlindboxCodePage),
    ),
  );
}

beforeEach(() => {
  vi.clearAllMocks();
  mockFetch.mockResolvedValue({
    ok: true,
    json: () =>
      Promise.resolve({
        room: {
          id: "bb-1",
          code: "ABC123",
          name: "周末房间",
          creatorId: "u1",
          city: null,
          lat: null,
          lng: null,
          ideaCount: 3,
          memberCount: 2,
          drawnCount: 0,
        },
        ideas: [],
        members: [
          { id: "u1", username: "test", avatar: "🐱" },
        ],
        myIdeas: [],
        drawnHistory: [],
        pendingContracts: [],
      }),
  });
});

describe("BlindboxCodePage", () => {
  it("loads room data", async () => {
    renderPage();
    await waitFor(() => {
      expect(mockFetch).toHaveBeenCalled();
    });
    const fetchCall = mockFetch.mock.calls.find(
      (c: string[]) => typeof c[0] === "string" && c[0].includes("/api/blindbox/room/ABC123"),
    );
    expect(fetchCall).toBeDefined();
  });

  it("fetches room data and loads user ideas", async () => {
    renderPage();
    await waitFor(() => {
      expect(mockFetch).toHaveBeenCalled();
    });
    const urls = mockFetch.mock.calls.map((c: string[]) => c[0]);
    expect(urls.some((u: string) => u.includes("blindbox/room/ABC123"))).toBe(true);
  });
});
