/**
 * MSW Handlers - 拦截所有 HTTP / GraphQL 请求返回 mock 数据
 *
 * 拦截路径（contract.md §2.3 + §4.2）：
 * - POST /api/auth/login → 返回固定 JWT + UserInfo
 * - POST /api/v1/teacher/graphql → 按 operationName 返回对应 GraphQL 响应
 *
 * 切换：NEXT_PUBLIC_API_MOCKING=enabled 时启用（见 src/mocks/index.ts）
 *
 * 维护者：ai13（teacher-portal）
 */

import { http, HttpResponse } from "msw";
import { mockUser, mockUserInfo, mockToken } from "./fixtures/user";
import { mockViewports } from "./fixtures/viewports";
import { mockClasses, findClass } from "./fixtures/classes";
import { generateMockStudents } from "./fixtures/students";
import { generateMockExams, findMockExamDetail, createMockExam } from "./fixtures/exams";
import { generateMockHomework, findMockHomeworkDetail, createMockHomework } from "./fixtures/homework";
import { generateMockGrades, recordMockGrade } from "./fixtures/grades";

/** ActionState 信封（coord-final-decisions F9 + 总裁 §3.4 方案 B） */
function envelope<T>(data: T) {
  return { success: true, errors: null, data };
}

/** GraphQL 响应体（urql 期望 { data: ... }） */
function graphqlData<T>(data: T) {
  return HttpResponse.json({ data });
}

/**
 * 根据 operationName 路由 GraphQL mock 响应
 *
 * 对应 graphql.ts 的 5 个 P2 Query + 4 个 P3 Query + 5 个 P3 Mutation/Query。
 */
function handleGraphQL(
  operationName: string,
  variables: Record<string, unknown>,
) {
  switch (operationName) {
    case "Dashboard":
      return graphqlData({
        dashboard: {
          user: mockUser,
          classes: mockClasses,
          viewports: mockViewports,
          stats: {
            totalExams: 8,
            pendingGrading: 12,
            todayHomework: 3,
          },
        },
      });

    case "Viewports":
      return graphqlData({ viewports: mockViewports });

    case "Me":
      return graphqlData({ me: mockUser });

    case "Classes":
      return graphqlData({ classes: mockClasses });

    case "Class": {
      const id = variables.id as string;
      return graphqlData({ class: findClass(id) });
    }

    case "ClassStudents": {
      const classId = variables.classId as string;
      return graphqlData({ classStudents: generateMockStudents(classId) });
    }

    case "ClassExams": {
      const classId = variables.classId as string;
      return graphqlData({ classExams: generateMockExams(classId) });
    }

    case "ClassHomework": {
      const classId = variables.classId as string;
      return graphqlData({ classHomework: generateMockHomework(classId) });
    }

    case "ExamGrades": {
      const examId = variables.examId as string;
      return graphqlData({ examGrades: generateMockGrades(examId) });
    }

    case "UpdateUser": {
      const input = variables.input as { name?: string; email?: string };
      return graphqlData({
        updateUser: { ...mockUser, ...input },
      });
    }

    case "CreateExam": {
      const input = variables.input as {
        classId: string;
        title: string;
        description?: string | null;
        examDate: string;
        duration: number;
        totalScore: number;
      };
      return graphqlData({ createExam: createMockExam(input) });
    }

    case "AssignHomework": {
      const input = variables.input as {
        classId: string;
        title: string;
        description?: string | null;
        dueDate: string;
      };
      return graphqlData({ assignHomework: createMockHomework(input) });
    }

    case "RecordGrade": {
      const input = variables.input as {
        studentId: string;
        examId?: string | null;
        homeworkId?: string | null;
        score: number;
        feedback?: string | null;
      };
      return graphqlData({ recordGrade: recordMockGrade(input) });
    }

    case "ExamDetail": {
      const id = variables.id as string;
      return graphqlData({ examDetail: findMockExamDetail(id) });
    }

    case "HomeworkDetail": {
      const id = variables.id as string;
      return graphqlData({ homeworkDetail: findMockHomeworkDetail(id) });
    }

    default:
      return HttpResponse.json(
        {
          errors: [
            {
              message: `Mock 未覆盖的 GraphQL operation: ${operationName}`,
              extensions: { code: "BFF_TEACHER_NOT_IMPLEMENTED" },
            },
          ],
        },
        { status: 200 },
      );
  }
}

export const handlers = [
  // POST /api/auth/login → 登录
  http.post("*/api/auth/login", async ({ request }) => {
    const body = (await request.json()) as {
      email?: string;
      password?: string;
    };
    if (!body.email || !body.password) {
      return HttpResponse.json(
        {
          success: false,
          error: { code: "GW_UNAUTHORIZED", message: "邮箱和密码必填" },
        },
        { status: 400 },
      );
    }
    return HttpResponse.json(
      envelope({
        user: mockUserInfo,
        tokens: { accessToken: mockToken, refreshToken: "mock-refresh" },
      }),
    );
  }),

  // POST /api/v1/teacher/graphql → GraphQL endpoint
  http.post("*/api/v1/teacher/graphql", async ({ request }) => {
    const body = (await request.json()) as {
      operationName?: string;
      query?: string;
      variables?: Record<string, unknown>;
    };

    const operationName =
      body.operationName ?? extractOperationName(body.query);
    const variables = body.variables ?? {};

    return handleGraphQL(operationName, variables);
  }),

  // GET /api/health → liveness
  http.get("*/api/health", () =>
    HttpResponse.json({ status: "ok", service: "teacher-portal" }),
  ),

  // GET /api/ready → readiness
  http.get("*/api/ready", () =>
    HttpResponse.json({
      status: "ok",
      service: "teacher-portal",
      checks: { msw: true },
    }),
  ),
];

/**
 * 从 query 字符串提取 operationName
 * 兜底：当客户端未传 operationName 时从 query 文本提取
 */
function extractOperationName(query?: string): string {
  if (!query) return "Unknown";
  const match = query.match(/(?:query|mutation)\s+(\w+)/);
  return match?.[1] ?? "Unknown";
}
