import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { expect, test, vi } from "vitest";

import { CommunityPostForm } from "@/features/community-posts/components/CommunityPostForm";
import { parseCommunityPostPrice } from "@/features/community-posts/components/community-post-form-helpers";
import type { ApiClient, ApiRequestOptions } from "@/shared/api/client";

type CapturedRequest = {
  readonly body?: BodyInit | null;
  readonly method?: string;
  readonly path: string;
};

function createClient(requests: CapturedRequest[]): ApiClient {
  return {
    async request<Data>(options: ApiRequestOptions<Data>): Promise<Data> {
      requests.push({ body: options.body, method: options.method, path: options.path });
      return options.responseSchema.parse(null);
    },
  };
}

function renderForm(requests: CapturedRequest[]) {
  const onCreated = vi.fn();
  render(<CommunityPostForm apiClient={createClient(requests)} characterId="101" createCropSource={(file) => Promise.resolve({ file, height: 600, previewUrl: "blob:post", width: 800 })} onCreated={onCreated} />);

  return onCreated;
}

test.each([
  "-1",
  "1.5",
  "100000",
])("Community price preserves and rejects invalid raw input %s through the submit button", async (rawValue) => {
  const requests: CapturedRequest[] = [];
  const onCreated = renderForm(requests);

  fireEvent.change(screen.getByLabelText("내용"), { target: { value: "가격 검증 게시글" } });
  fireEvent.change(screen.getByLabelText("가격"), { target: { value: rawValue } });
  fireEvent.click(screen.getByRole("button", { name: "생성" }));

  expect(screen.getByLabelText("가격")).toHaveValue(Number(rawValue));
  expect(await screen.findByText("가격은 0 이상 99,999 이하 정수 캔으로 입력하세요.")).toBeInTheDocument();
  expect(requests.filter((request) => request.method === "POST")).toHaveLength(0);
  expect(onCreated).not.toHaveBeenCalled();
});

test.each(["0", "99999"])("Community price allows boundary input %s", async (value) => {
  const requests: CapturedRequest[] = [];
  const onCreated = renderForm(requests);

  fireEvent.change(screen.getByLabelText("내용"), { target: { value: "가격 경계 게시글" } });
  fireEvent.change(screen.getByLabelText("가격"), { target: { value } });
  fireEvent.click(screen.getByRole("button", { name: "생성" }));

  await waitFor(() => expect(onCreated).toHaveBeenCalledTimes(1));
  expect(requests.filter((request) => request.method === "POST")).toHaveLength(1);
});

test("Community price parser rejects blank, negative, and decimal raw input", () => {
  expect(parseCommunityPostPrice("")).toBeNull();
  expect(parseCommunityPostPrice("-1")).toBeNull();
  expect(parseCommunityPostPrice("1.5")).toBeNull();
});
