import "server-only"

/**
 * 选修课模块跨模块依赖的接口抽象（P2-2.1.4）。
 *
 * 目的：将 elective 对 school/users/classes 模块的直接 import 收敛到此文件，
 * 便于单测时 mock 单一入口，未来替换实现只需改此文件。
 *
 * 注意：实际实现仍委托给各模块的 data-access，此处仅做接口聚合。
 */

import { getGradeOptions, getSubjectOptions } from "@/modules/school/data-access"
import { getUserNamesByIds } from "@/modules/users/data-access"
import { getStudentActiveGradeId } from "@/modules/classes/data-access"

/** 科目/年级/教师名称解析接口 */
export interface CourseDisplayResolver {
  /** 根据教师 ID 列表获取用户名映射 */
  getUserNamesByIds: (ids: string[]) => Promise<Map<string, { name: string | null }>>
  /** 获取所有科目选项 */
  getSubjectOptions: () => Promise<Array<{ id: string; name: string }>>
  /** 获取所有年级选项 */
  getGradeOptions: () => Promise<Array<{ id: string; name: string }>>
}

/** 学生年级解析接口 */
export interface StudentGradeResolver {
  /** 获取学生当前激活的年级 ID */
  getStudentActiveGradeId: (studentId: string) => Promise<string | null>
}

/**
 * 默认实现：委托给各模块的 data-access。
 * 单测时可注入 mock 实现替换。
 */
export const defaultCourseDisplayResolver: CourseDisplayResolver = {
  getUserNamesByIds,
  getSubjectOptions,
  getGradeOptions,
}

export const defaultStudentGradeResolver: StudentGradeResolver = {
  getStudentActiveGradeId,
}

/**
 * 可注入的解析器实例（单测时可覆盖）。
 * 使用闭包而非全局可变变量，避免并发测试污染。
 */
let courseDisplayResolver: CourseDisplayResolver = defaultCourseDisplayResolver
let studentGradeResolver: StudentGradeResolver = defaultStudentGradeResolver

/**
 * 获取当前注入的课程显示名称解析器。
 */
export function getCourseDisplayResolver(): CourseDisplayResolver {
  return courseDisplayResolver
}

/**
 * 获取当前注入的学生年级解析器。
 */
export function getStudentGradeResolver(): StudentGradeResolver {
  return studentGradeResolver
}

/**
 * 注入自定义解析器（仅用于测试）。
 * 调用后需在测试结束后调用 `resetResolvers()` 恢复默认实现。
 */
export function setCourseDisplayResolver(resolver: CourseDisplayResolver): void {
  courseDisplayResolver = resolver
}

export function setStudentGradeResolver(resolver: StudentGradeResolver): void {
  studentGradeResolver = resolver
}

/** 恢复默认解析器（测试 teardown 调用） */
export function resetResolvers(): void {
  courseDisplayResolver = defaultCourseDisplayResolver
  studentGradeResolver = defaultStudentGradeResolver
}
