/**
 * GraphQL 操作字符串测试
 *
 * 验证每个 gql 操作字符串包含正确的 operationName 和 query/mutation 关键字。
 * 操作名需与 MSW handlers.ts 的 operationName 分发对齐。
 */

import { describe, it, expect } from "vitest";
import {
  // 查询操作
  CURRENT_USER_QUERY,
  MY_CLASSES_QUERY,
  MY_EXAMS_QUERY,
  EXAM_DETAIL_QUERY,
  MY_HOMEWORK_QUERY,
  HOMEWORK_DETAIL_QUERY,
  MY_GRADES_QUERY,
  MY_ATTENDANCE_QUERY,
  TEXTBOOKS_QUERY,
  CHAPTERS_QUERY,
  LEARNING_PATH_QUERY,
  STUDENT_DASHBOARD_QUERY,
  MY_WEAKNESS_QUERY,
  MY_TREND_QUERY,
  MY_NOTIFICATIONS_QUERY,
  SERVER_TIME_QUERY,
  // 扩展查询
  MY_SCHEDULE_QUERY,
  STUDENT_GROWTH_QUERY,
  ASSIGNMENT_ANALYSIS_QUERY,
  MY_PROFILE_QUERY,
  // 批次 A 扩展查询
  MY_ERROR_BOOK_QUERY,
  MY_LEAVE_REQUESTS_QUERY,
  MY_ELECTIVE_SELECTIONS_QUERY,
  AVAILABLE_ELECTIVE_COURSES_QUERY,
  MY_PRACTICE_SESSIONS_QUERY,
  START_PRACTICE_SESSION_QUERY,
  ANNOUNCEMENTS_QUERY,
  ANNOUNCEMENT_DETAIL_QUERY,
  MY_LESSON_PLANS_QUERY,
  LESSON_PLAN_DETAIL_QUERY,
  MY_COURSE_PLANS_QUERY,
  COURSE_PLAN_DETAIL_QUERY,
  MY_REPORT_CARD_QUERY,
  MY_DIAGNOSTIC_REPORTS_QUERY,
  MY_MASTERY_SUMMARY_QUERY,
  // 变更操作
  SUBMIT_HOMEWORK_MUTATION,
  SUBMIT_EXAM_MUTATION,
  SAVE_EXAM_DRAFT_MUTATION,
  MARK_AS_READ_MUTATION,
  MARK_ALL_AS_READ_MUTATION,
  RECORD_EXAM_VIOLATION_MUTATION,
  RECORD_PASTE_EVENT_MUTATION,
  UPDATE_NOTIFICATION_PREFERENCE_MUTATION,
  // 扩展变更
  UPDATE_PROFILE_MUTATION,
  CHANGE_PASSWORD_MUTATION,
  REQUEST_EXTENSION_MUTATION,
  JOIN_CLASS_MUTATION,
  LEAVE_CLASS_MUTATION,
  // 批次 A 扩展变更
  ADD_ERROR_BOOK_ITEM_MUTATION,
  UPDATE_ERROR_BOOK_ITEM_MUTATION,
  DELETE_ERROR_BOOK_ITEM_MUTATION,
  CREATE_LEAVE_REQUEST_MUTATION,
  CANCEL_LEAVE_REQUEST_MUTATION,
  SELECT_ELECTIVE_COURSE_MUTATION,
  DROP_ELECTIVE_COURSE_MUTATION,
  SUBMIT_PRACTICE_ANSWER_MUTATION,
  MARK_ANNOUNCEMENT_READ_MUTATION,
} from "./operations";

/** 将 gql DocumentNode 转为字符串以检查内容 */
function asString(node: unknown): string {
  if (node === null || node === undefined) return "";
  if (typeof node === "string") return node;
  if (typeof node === "object" && node !== null) {
    const obj = node as Record<string, unknown>;
    if (obj.loc && typeof obj.loc === "object" && obj.loc !== null) {
      const loc = obj.loc as Record<string, unknown>;
      if (typeof loc.source === "object" && loc.source !== null) {
        const source = loc.source as Record<string, unknown>;
        if (typeof source.body === "string") return source.body;
      }
      if (typeof loc.body === "string") return loc.body;
    }
    if (typeof obj.toString === "function") {
      const str = obj.toString();
      if (str !== "[object Object]") return str;
    }
  }
  return String(node);
}

describe("GraphQL operations", () => {
  const queries: Array<[string, unknown, string]> = [
    ["CURRENT_USER_QUERY", CURRENT_USER_QUERY, "currentUser"],
    ["MY_CLASSES_QUERY", MY_CLASSES_QUERY, "myClasses"],
    ["MY_EXAMS_QUERY", MY_EXAMS_QUERY, "myExams"],
    ["EXAM_DETAIL_QUERY", EXAM_DETAIL_QUERY, "examDetail"],
    ["MY_HOMEWORK_QUERY", MY_HOMEWORK_QUERY, "myHomework"],
    ["HOMEWORK_DETAIL_QUERY", HOMEWORK_DETAIL_QUERY, "homeworkDetail"],
    ["MY_GRADES_QUERY", MY_GRADES_QUERY, "myGrades"],
    ["MY_ATTENDANCE_QUERY", MY_ATTENDANCE_QUERY, "myAttendance"],
    ["TEXTBOOKS_QUERY", TEXTBOOKS_QUERY, "textbooks"],
    ["CHAPTERS_QUERY", CHAPTERS_QUERY, "chapters"],
    ["LEARNING_PATH_QUERY", LEARNING_PATH_QUERY, "learningPath"],
    ["STUDENT_DASHBOARD_QUERY", STUDENT_DASHBOARD_QUERY, "studentDashboard"],
    ["MY_WEAKNESS_QUERY", MY_WEAKNESS_QUERY, "myWeakness"],
    ["MY_TREND_QUERY", MY_TREND_QUERY, "myTrend"],
    ["MY_NOTIFICATIONS_QUERY", MY_NOTIFICATIONS_QUERY, "myNotifications"],
    ["SERVER_TIME_QUERY", SERVER_TIME_QUERY, "serverTime"],
    ["MY_SCHEDULE_QUERY", MY_SCHEDULE_QUERY, "mySchedule"],
    ["STUDENT_GROWTH_QUERY", STUDENT_GROWTH_QUERY, "studentGrowth"],
    ["ASSIGNMENT_ANALYSIS_QUERY", ASSIGNMENT_ANALYSIS_QUERY, "assignmentAnalysis"],
    ["MY_PROFILE_QUERY", MY_PROFILE_QUERY, "myProfile"],
    ["MY_ERROR_BOOK_QUERY", MY_ERROR_BOOK_QUERY, "myErrorBook"],
    ["MY_LEAVE_REQUESTS_QUERY", MY_LEAVE_REQUESTS_QUERY, "myLeaveRequests"],
    ["MY_ELECTIVE_SELECTIONS_QUERY", MY_ELECTIVE_SELECTIONS_QUERY, "myElectiveSelections"],
    ["AVAILABLE_ELECTIVE_COURSES_QUERY", AVAILABLE_ELECTIVE_COURSES_QUERY, "availableElectiveCourses"],
    ["MY_PRACTICE_SESSIONS_QUERY", MY_PRACTICE_SESSIONS_QUERY, "myPracticeSessions"],
    ["START_PRACTICE_SESSION_QUERY", START_PRACTICE_SESSION_QUERY, "startPracticeSession"],
    ["ANNOUNCEMENTS_QUERY", ANNOUNCEMENTS_QUERY, "announcements"],
    ["ANNOUNCEMENT_DETAIL_QUERY", ANNOUNCEMENT_DETAIL_QUERY, "announcementDetail"],
    ["MY_LESSON_PLANS_QUERY", MY_LESSON_PLANS_QUERY, "myLessonPlans"],
    ["LESSON_PLAN_DETAIL_QUERY", LESSON_PLAN_DETAIL_QUERY, "lessonPlanDetail"],
    ["MY_COURSE_PLANS_QUERY", MY_COURSE_PLANS_QUERY, "myCoursePlans"],
    ["COURSE_PLAN_DETAIL_QUERY", COURSE_PLAN_DETAIL_QUERY, "coursePlanDetail"],
    ["MY_REPORT_CARD_QUERY", MY_REPORT_CARD_QUERY, "myReportCard"],
    ["MY_DIAGNOSTIC_REPORTS_QUERY", MY_DIAGNOSTIC_REPORTS_QUERY, "myDiagnosticReports"],
    ["MY_MASTERY_SUMMARY_QUERY", MY_MASTERY_SUMMARY_QUERY, "myMasterySummary"],
  ];

  const mutations: Array<[string, unknown, string]> = [
    ["SUBMIT_HOMEWORK_MUTATION", SUBMIT_HOMEWORK_MUTATION, "submitHomework"],
    ["SUBMIT_EXAM_MUTATION", SUBMIT_EXAM_MUTATION, "submitExam"],
    ["SAVE_EXAM_DRAFT_MUTATION", SAVE_EXAM_DRAFT_MUTATION, "saveExamDraft"],
    ["MARK_AS_READ_MUTATION", MARK_AS_READ_MUTATION, "markAsRead"],
    ["MARK_ALL_AS_READ_MUTATION", MARK_ALL_AS_READ_MUTATION, "markAllAsRead"],
    ["RECORD_EXAM_VIOLATION_MUTATION", RECORD_EXAM_VIOLATION_MUTATION, "recordExamViolation"],
    ["RECORD_PASTE_EVENT_MUTATION", RECORD_PASTE_EVENT_MUTATION, "recordPasteEvent"],
    ["UPDATE_NOTIFICATION_PREFERENCE_MUTATION", UPDATE_NOTIFICATION_PREFERENCE_MUTATION, "updateNotificationPreference"],
    ["UPDATE_PROFILE_MUTATION", UPDATE_PROFILE_MUTATION, "updateProfile"],
    ["CHANGE_PASSWORD_MUTATION", CHANGE_PASSWORD_MUTATION, "changePassword"],
    ["REQUEST_EXTENSION_MUTATION", REQUEST_EXTENSION_MUTATION, "requestExtension"],
    ["JOIN_CLASS_MUTATION", JOIN_CLASS_MUTATION, "joinClass"],
    ["LEAVE_CLASS_MUTATION", LEAVE_CLASS_MUTATION, "leaveClass"],
    ["ADD_ERROR_BOOK_ITEM_MUTATION", ADD_ERROR_BOOK_ITEM_MUTATION, "addErrorBookItem"],
    ["UPDATE_ERROR_BOOK_ITEM_MUTATION", UPDATE_ERROR_BOOK_ITEM_MUTATION, "updateErrorBookItem"],
    ["DELETE_ERROR_BOOK_ITEM_MUTATION", DELETE_ERROR_BOOK_ITEM_MUTATION, "deleteErrorBookItem"],
    ["CREATE_LEAVE_REQUEST_MUTATION", CREATE_LEAVE_REQUEST_MUTATION, "createLeaveRequest"],
    ["CANCEL_LEAVE_REQUEST_MUTATION", CANCEL_LEAVE_REQUEST_MUTATION, "cancelLeaveRequest"],
    ["SELECT_ELECTIVE_COURSE_MUTATION", SELECT_ELECTIVE_COURSE_MUTATION, "selectElectiveCourse"],
    ["DROP_ELECTIVE_COURSE_MUTATION", DROP_ELECTIVE_COURSE_MUTATION, "dropElectiveCourse"],
    ["SUBMIT_PRACTICE_ANSWER_MUTATION", SUBMIT_PRACTICE_ANSWER_MUTATION, "submitPracticeAnswer"],
    ["MARK_ANNOUNCEMENT_READ_MUTATION", MARK_ANNOUNCEMENT_READ_MUTATION, "markAnnouncementRead"],
  ];

  describe.each(queries)("查询 %s", (exportName, operation, operationName) => {
    it("应包含 query 关键字", () => {
      const text = asString(operation);
      expect(text).toContain("query");
    });

    it("应包含正确的 operationName", () => {
      const text = asString(operation);
      expect(text).toContain(`query ${operationName}`);
    });

    it("不应包含 mutation 关键字", () => {
      const text = asString(operation);
      expect(text).not.toContain("mutation");
    });

    it("应为非空字符串", () => {
      const text = asString(operation);
      expect(text.trim().length).toBeGreaterThan(0);
      expect(exportName).toBeDefined();
    });
  });

  describe.each(mutations)("变更 %s", (exportName, operation, operationName) => {
    it("应包含 mutation 关键字", () => {
      const text = asString(operation);
      expect(text).toContain("mutation");
    });

    it("应包含正确的 operationName", () => {
      const text = asString(operation);
      expect(text).toContain(`mutation ${operationName}`);
    });

    it("不应包含 query 关键字作为操作类型", () => {
      const text = asString(operation);
      // mutation 字符串中不应出现 "query xxx {" 形式
      expect(text).not.toMatch(/^query\s+\w+/);
    });

    it("应为非空字符串", () => {
      const text = asString(operation);
      expect(text.trim().length).toBeGreaterThan(0);
      expect(exportName).toBeDefined();
    });
  });

  it("查询操作数量应为 35", () => {
    expect(queries).toHaveLength(35);
  });

  it("变更操作数量应为 22", () => {
    expect(mutations).toHaveLength(22);
  });

  it("所有操作名应唯一", () => {
    const allNames = [
      ...queries.map(([, , name]) => name),
      ...mutations.map(([, , name]) => name),
    ];
    const unique = new Set(allNames);
    expect(unique.size).toBe(allNames.length);
  });
});
