// useCreateLeaveRequest Hook 单测
// 依据：02-architecture-design.md §4.2 GraphQL 接入
// 覆盖：成功提交 / mutation 错误返回 / loading 状态

import {
  describe,
  it,
  expect,
  beforeAll,
  afterAll,
  afterEach,
} from "vitest";
import { renderHook, act, cleanup } from "@testing-library/react";
import {
  Provider as UrqlProvider,
  Client,
  cacheExchange,
  fetchExchange,
} from "urql";
import { graphql, HttpResponse } from "msw";
import type { ReactNode } from "react";
import { server } from "@/test/mocks/server";
import { useCreateLeaveRequest } from "./useCreateLeaveRequest";
import type { LeaveRequestInput } from "@/types";

function createTestClient(): Client {
  return new Client({
    url: "/api/v1/parent/v1/graphql",
    exchanges: [cacheExchange, fetchExchange],
    fetchOptions: { headers: { "X-Requested-With": "XMLHttpRequest" } },
  });
}

function renderUseCreateLeaveRequest() {
  const client = createTestClient();
  const wrapper = ({ children }: { children: ReactNode }) => (
    <UrqlProvider value={client}>{children}</UrqlProvider>
  );
  return renderHook(() => useCreateLeaveRequest(), { wrapper });
}

const validInput: LeaveRequestInput = {
  childId: "student-001",
  type: "sick",
  startDate: "2026-07-15",
  endDate: "2026-07-16",
  reason: "感冒发烧需要在家休息",
};

beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
afterEach(() => {
  cleanup();
  server.resetHandlers();
});
afterAll(() => server.close());

describe("useCreateLeaveRequest", () => {
  it("初始状态 loading 为 false 且 error 为 undefined", () => {
    const { result } = renderUseCreateLeaveRequest();
    expect(result.current.loading).toBe(false);
    expect(result.current.error).toBeUndefined();
  });

  it("成功提交返回 success=true", async () => {
    const { result } = renderUseCreateLeaveRequest();

    let createResult: { success: boolean } | undefined;
    await act(async () => {
      createResult = await result.current.createLeave(validInput);
    });

    expect(createResult?.success).toBe(true);
    expect(result.current.loading).toBe(false);
    expect(result.current.error).toBeUndefined();
  });

  it("提交后 loading 最终回到 false", async () => {
    const { result } = renderUseCreateLeaveRequest();

    let resolved = false;
    await act(async () => {
      const r = await result.current.createLeave(validInput);
      resolved = r.success;
    });

    expect(resolved).toBe(true);
    expect(result.current.loading).toBe(false);
  });

  it("mutation 返回错误时返回 success=false 并设置 error", async () => {
    server.resetHandlers(
      graphql.mutation("CreateLeaveRequest", () =>
        HttpResponse.json(
          { errors: [{ message: "请假提交失败：日期冲突" }] },
          { status: 200 },
        ),
      ),
    );

    const { result } = renderUseCreateLeaveRequest();

    let createResult: { success: boolean; error?: unknown } | undefined;
    await act(async () => {
      createResult = await result.current.createLeave(validInput);
    });

    expect(createResult?.success).toBe(false);
    expect(createResult?.error).toBeDefined();
    expect(result.current.error?.message).toContain("日期冲突");
    expect(result.current.loading).toBe(false);
  });

  it("提交时携带正确的 input 变量", async () => {
    let capturedInput: unknown = null;
    server.resetHandlers(
      graphql.mutation("CreateLeaveRequest", ({ variables }) => {
        capturedInput = variables.input;
        return HttpResponse.json({
          data: {
            createLeaveRequest: {
              id: "leave-new",
              childId: "student-001",
              type: "sick",
              startDate: "2026-07-15",
              endDate: "2026-07-16",
              reason: "感冒发烧",
              status: "pending",
              submittedAt: "2026-07-13T10:00:00Z",
            },
          },
        });
      }),
    );

    const { result } = renderUseCreateLeaveRequest();

    await act(async () => {
      await result.current.createLeave(validInput);
    });

    expect(capturedInput).toEqual(validInput);
  });
});
