import { render, waitFor } from "@testing-library/react";

import { ProjectProvider } from "./ProjectContext";

const mockApiFetch = jest.fn();
const mockUseSession = jest.fn();
const mockSetCurrentProjectId = jest.fn();

jest.mock("next-auth/react", () => ({
  useSession: () => mockUseSession(),
}));

jest.mock("next/navigation", () => ({
  usePathname: () => "/login",
  useRouter: () => ({ push: jest.fn() }),
}));

jest.mock("@/components/project/ProjectSelector", () => ({
  ProjectSelector: () => <div>project selector</div>,
}));

jest.mock("@/config/config", () => ({
  config: {
    BACKEND_URL: "http://backend.test",
    MAP_EXTENT: [1, 2, 3, 4],
    MAP_WORKSPACE: "default-workspace",
  },
  NETWORK_NAME: "default-network",
  setMapExtent: jest.fn(),
  setMapWorkspace: jest.fn(),
  setNetworkName: jest.fn(),
}));

jest.mock("@/lib/apiFetch", () => ({
  apiFetch: (...args: unknown[]) => mockApiFetch(...args),
}));

jest.mock("@/lib/permissions", () => ({
  permissionCodes: { environmentManage: "environment:manage" },
}));

jest.mock("@/store/accessStore", () => ({
  useAccessStore: (selector: (state: { permissions: string[] }) => unknown) =>
    selector({ permissions: [] }),
}));

jest.mock("@/store/projectStore", () => ({
  useProjectStore: (
    selector: (state: { setCurrentProjectId: typeof mockSetCurrentProjectId }) => unknown,
  ) => selector({ setCurrentProjectId: mockSetCurrentProjectId }),
}));

const seedSavedProject = () => {
  localStorage.setItem("MAP_WORKSPACE", "fengyang");
  localStorage.setItem("NETWORK_NAME", "fengyang");
  localStorage.setItem("MAP_EXTENT", "1,2,3,4");
  localStorage.setItem(
    "active_project",
    "a2d67c84-fd9d-4feb-a500-c357244b2760",
  );
};

describe("ProjectProvider authentication boundary", () => {
  beforeEach(() => {
    localStorage.clear();
    mockApiFetch.mockReset();
    mockSetCurrentProjectId.mockReset();
    mockApiFetch.mockResolvedValue({
      ok: true,
      json: async () => ({}),
    });
  });

  it("does not restore or open a saved project while unauthenticated", () => {
    seedSavedProject();
    mockUseSession.mockReturnValue({ status: "unauthenticated" });

    render(
      <ProjectProvider>
        <div>login page</div>
      </ProjectProvider>,
    );

    expect(mockSetCurrentProjectId).not.toHaveBeenCalled();
    expect(mockApiFetch).not.toHaveBeenCalled();
  });

  it("restores and opens a saved project after authentication", async () => {
    seedSavedProject();
    mockUseSession.mockReturnValue({ status: "authenticated" });

    render(
      <ProjectProvider>
        <div>main page</div>
      </ProjectProvider>,
    );

    await waitFor(() => expect(mockApiFetch).toHaveBeenCalledTimes(2));
    expect(mockSetCurrentProjectId).toHaveBeenCalledWith(
      "a2d67c84-fd9d-4feb-a500-c357244b2760",
    );
  });
});
