import type { ClassInfoDto, ExamDto, GradeDto, HomeworkDto } from "./dtos.js";
import { callWithMetrics } from "./grpc/call-with-metrics.js";
import {
  MOCK_CLASSES,
  MOCK_EXAMS,
  MOCK_GRADES,
  MOCK_HOMEWORK,
} from "./mock-data.js";

/**
 * CoreEdu 下游客户端接口（对齐 02-architecture-design.md §7.1 交互矩阵）。
 *
 * 方法：
 * - listGradesByStudent: GradeService.ListGradesByStudent（✅ 已有）
 * - listHomeworkByClass: HomeworkService.ListHomeworkByClass（✅ 已有）
 * - listExamsByClass: ExamService.ListExamsByClass（✅ 已有）
 * - getClass: ClassService.GetClass（❌ ISSUE-008 待仲裁，proto 缺 ClassService）
 */
export interface CoreEduClient {
  listGradesByStudent(studentId: string): Promise<GradeDto[]>;
  listHomeworkByClass(classId: string): Promise<HomeworkDto[]>;
  listExamsByClass(classId: string): Promise<ExamDto[]>;
  getClass(classId: string): Promise<ClassInfoDto>;
}

/**
 * Mock CoreEdu 客户端（DEV_MODE=true 时使用）。
 *
 * 固定数据：每学生 5 个成绩 / 每班级 3 个作业 + 3 个考试。
 */
export class MockCoreEduClient implements CoreEduClient {
  async listGradesByStudent(studentId: string): Promise<GradeDto[]> {
    const grades = MOCK_GRADES[studentId];
    if (!grades) {
      return [];
    }
    return grades.map((g) => ({ ...g }));
  }

  async listHomeworkByClass(classId: string): Promise<HomeworkDto[]> {
    const homework = MOCK_HOMEWORK[classId];
    if (!homework) {
      return [];
    }
    return homework.map((h) => ({ ...h }));
  }

  async listExamsByClass(classId: string): Promise<ExamDto[]> {
    const exams = MOCK_EXAMS[classId];
    if (!exams) {
      return [];
    }
    return exams.map((e) => ({ ...e }));
  }

  async getClass(classId: string): Promise<ClassInfoDto> {
    const cls = MOCK_CLASSES[classId];
    if (!cls) {
      return { id: classId, name: "未知班级", gradeId: "unknown" };
    }
    return { ...cls };
  }
}

/**
 * gRPC CoreEdu 客户端。
 *
 * 通过 proto-loader 动态加载 core_edu.proto，调用 Exam/Homework/Grade Service RPCs。
 *
 * 注意：ClassService.GetClass 尚未在 proto 中定义（ISSUE-008 待仲裁）。
 */
export class GrpcCoreEduClient implements CoreEduClient {
  private readonly gradeClient: unknown;
  private readonly homeworkClient: unknown;
  private readonly examClient: unknown;

  constructor(
    gradeClient: unknown,
    homeworkClient: unknown,
    examClient: unknown,
  ) {
    this.gradeClient = gradeClient;
    this.homeworkClient = homeworkClient;
    this.examClient = examClient;
  }

  async listGradesByStudent(studentId: string): Promise<GradeDto[]> {
    const res = await callWithMetrics<
      { studentId: string },
      { grades: GradeDto[] }
    >(this.gradeClient, "listGradesByStudent", { studentId }, "core-edu");
    return res.grades ?? [];
  }

  async listHomeworkByClass(classId: string): Promise<HomeworkDto[]> {
    const res = await callWithMetrics<
      { classId: string },
      { homework: HomeworkDto[] }
    >(this.homeworkClient, "listHomeworkByClass", { classId }, "core-edu");
    return res.homework ?? [];
  }

  async listExamsByClass(classId: string): Promise<ExamDto[]> {
    const res = await callWithMetrics<
      { classId: string },
      { exams: ExamDto[] }
    >(this.examClient, "listExamsByClass", { classId }, "core-edu");
    return res.exams ?? [];
  }

  async getClass(classId: string): Promise<ClassInfoDto> {
    // ISSUE-008: ClassService proto 缺失，待仲裁后启用
    // 补全后：callWithMetrics(this.classClient, "getClass", { classId }, "core-edu")
    // 当前返回默认值，避免阻塞 P4 开发
    return { id: classId, name: "未知班级", gradeId: "unknown" };
  }
}
