import { render, screen, fireEvent, waitFor, cleanup } from "@testing-library/react";
import { expect, test, vi, beforeEach, afterEach } from "vitest";
import Home from "./page";

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

afterEach(() => {
  cleanup();
});

test("renders loading state initially", () => {
  vi.spyOn(global, "fetch").mockImplementation(() => new Promise(() => {}));
  render(<Home />);
  expect(screen.getByText("...")).toBeDefined();
});

test("renders counter value after fetch", async () => {
  vi.spyOn(global, "fetch").mockResolvedValue({
    json: () => Promise.resolve({ value: 42 }),
  } as Response);

  render(<Home />);
  await waitFor(() => {
    expect(screen.getByText("42")).toBeDefined();
  });
});

test("renders +1 button", async () => {
  vi.spyOn(global, "fetch").mockResolvedValue({
    json: () => Promise.resolve({ value: 0 }),
  } as Response);

  render(<Home />);
  expect(screen.getByText("+1")).toBeDefined();
});

test("clicking button calls increment endpoint", async () => {
  const fetchSpy = vi.spyOn(global, "fetch")
    .mockResolvedValueOnce({ json: () => Promise.resolve({ value: 0 }) } as Response)
    .mockResolvedValueOnce({ json: () => Promise.resolve({ value: 1 }) } as Response);

  render(<Home />);
  await waitFor(() => expect(screen.getByText("0")).toBeDefined());

  fireEvent.click(screen.getByText("+1"));

  await waitFor(() => {
    expect(fetchSpy).toHaveBeenCalledWith(
      "http://localhost:8000/api/counter/increment",
      { method: "POST" }
    );
  });
});

test("clicking button updates displayed count", async () => {
  vi.spyOn(global, "fetch")
    .mockResolvedValueOnce({ json: () => Promise.resolve({ value: 0 }) } as Response)
    .mockResolvedValueOnce({ json: () => Promise.resolve({ value: 1 }) } as Response);

  render(<Home />);
  await waitFor(() => expect(screen.getByText("0")).toBeDefined());

  fireEvent.click(screen.getByText("+1"));
  await waitFor(() => expect(screen.getByText("1")).toBeDefined());
});

