import DataLoader from "dataloader";
import type { IamClient } from "../clients/iam.client.js";
import type { CoreEduClient } from "../clients/core-edu.client.js";
import type {
  ChildDto,
  ExamDto,
  GradeDto,
  HomeworkDto,
} from "../clients/dtos.js";

/**
 * Per-request DataLoader 容器（对齐 02-architecture-design.md §6.3）。
 *
 * DataLoader 防御 N+1：
 * - 同一 request 内相同 key 只调 1 次下游
 * - 不同 key 的调用在同一个 tick 批量发起（Promise.all 并行）
 *
 * proto 无 batch RPC，DataLoader 仅做 per-request 去重 + 并行调度。
 */
export interface Loaders {
  /** parentId → ChildDto[]（孩子列表，per-request 去重） */
  children: DataLoader<string, ChildDto[]>;
  /** studentId → GradeDto[]（成绩列表） */
  grades: DataLoader<string, GradeDto[]>;
  /** classId → HomeworkDto[]（作业列表） */
  homework: DataLoader<string, HomeworkDto[]>;
  /** classId → ExamDto[]（考试列表） */
  exams: DataLoader<string, ExamDto[]>;
}

/**
 * 创建 per-request DataLoader 实例集合。
 *
 * 每次请求调用此函数，生成独立的 DataLoader 实例，
 * 避免跨请求的批量调度。
 */
export function createLoaders(
  iamClient: IamClient,
  coreEduClient: CoreEduClient,
): Loaders {
  return {
    children: new DataLoader<string, ChildDto[]>(async (parentIds) => {
      // proto 无 batch RPC，逐个调用但并行执行
      const results = await Promise.all(
        parentIds.map((id) => iamClient.getChildrenByParent(id)),
      );
      return results;
    }),

    grades: new DataLoader<string, GradeDto[]>(async (studentIds) => {
      const results = await Promise.all(
        studentIds.map((id) => coreEduClient.listGradesByStudent(id)),
      );
      return results;
    }),

    homework: new DataLoader<string, HomeworkDto[]>(async (classIds) => {
      const results = await Promise.all(
        classIds.map((id) => coreEduClient.listHomeworkByClass(id)),
      );
      return results;
    }),

    exams: new DataLoader<string, ExamDto[]>(async (classIds) => {
      const results = await Promise.all(
        classIds.map((id) => coreEduClient.listExamsByClass(id)),
      );
      return results;
    }),
  };
}
