import type {
  ChildDto,
  ClassPerformanceDto,
  ExamDto,
  GradeDto,
  HomeworkDto,
  LearningTrendDto,
  StudentWeaknessDto,
  UserInfoDto,
  ViewportDto,
} from "../clients/dtos.js";
import type {
  ChildAnalyticsType,
  ChildType,
  ClassInfoType,
  ExamType,
  GradeType,
  HomeworkType,
  ParentType,
  TrendPointType,
  ViewportItemType,
  WeaknessTopicType,
} from "../graphql/types.js";

/**
 * Response Mapper（对齐 02-architecture-design.md §3.3）。
 *
 * 负责 proto DTO → GraphQL Type 的字段映射与类型转换：
 * - GradeDto.score (string) → GradeType.score (number)：Number.parseFloat
 * - TrendPointDto.date (int64 ms) → TrendPointType.date (DateTime ISO string)
 * - WeakPointDto.title → WeaknessTopicType.name，mastery → masteryRate
 * - 字段缺失时返回合理默认值（proto 未定义的字段）
 *
 * P4.6 将增强：Orchestrator 调用 mapper + fallback 策略统一降级。
 */

export function mapParent(dto: UserInfoDto): ParentType {
  return {
    id: dto.id,
    email: dto.email,
    name: dto.name,
    avatar: null,
    roles: dto.roles,
    dataScope: "CHILDREN",
  };
}

export function mapChild(dto: ChildDto): ChildType {
  return {
    id: dto.id,
    name: dto.name,
    grade: dto.grade,
    class: {
      id: dto.classId,
      name: dto.className,
      gradeId: dto.gradeId,
    },
  };
}

export function mapClassInfo(dto: {
  id: string;
  name: string;
  gradeId: string;
}): ClassInfoType {
  return { id: dto.id, name: dto.name, gradeId: dto.gradeId };
}

/**
 * GradeDto → GradeType。
 *
 * ISSUE-008：proto Grade.score 为 string，需转 Float。
 * proto Grade 无 examTitle / subject / rank 字段：
 * - examTitle：fallback 到 feedback 或 "未命名考试"
 * - subject：从 feedback 前缀提取（mock 数据格式 "数学表现良好"），真实 proto 补全后直接取
 * - rank：proto 无此字段，返回 null
 */
export function mapGrade(dto: GradeDto): GradeType {
  return {
    id: dto.id,
    examId: dto.examId,
    examTitle: dto.feedback || "未命名考试",
    subject: extractSubjectFromFeedback(dto.feedback),
    score: Number.parseFloat(dto.score) || 0,
    rank: null,
    gradedAt: dto.updatedAt,
  };
}

function extractSubjectFromFeedback(feedback: string): string {
  if (!feedback) return "未知科目";
  const subjects = ["数学", "语文", "英语", "科学", "美术", "音乐", "体育"];
  const found = subjects.find((s) => feedback.startsWith(s));
  return found ?? "综合";
}

export function mapHomework(dto: HomeworkDto): HomeworkType {
  const status = dto.status as HomeworkType["status"];
  return {
    id: dto.id,
    title: dto.title,
    classId: dto.classId,
    dueDate: dto.dueDate,
    status,
    submittedAt:
      status === "SUBMITTED" || status === "GRADED" ? dto.updatedAt : null,
  };
}

export function mapExam(dto: ExamDto): ExamType {
  const status = dto.status as ExamType["status"];
  return {
    id: dto.id,
    title: dto.title,
    classId: dto.classId,
    status,
    examDate: dto.examDate,
    publishedAt:
      status === "PUBLISHED" ||
      status === "SCORED" ||
      status === "IN_PROGRESS" ||
      status === "GRADING" ||
      status === "ARCHIVED"
        ? dto.updatedAt
        : null,
  };
}

export function mapViewport(dto: ViewportDto): ViewportItemType {
  return {
    key: dto.key,
    label: dto.label,
    route: dto.route,
    icon: dto.icon ?? null,
    sortOrder: dto.sortOrder,
    requiredPermission: dto.requiredPermission ?? null,
  };
}

export function mapWeakness(dto: StudentWeaknessDto): WeaknessTopicType[] {
  return dto.weakPoints.map((wp) => ({
    knowledgePointId: wp.knowledgePointId,
    name: wp.title,
    subject: "综合",
    masteryRate: wp.mastery,
  }));
}

export function mapTrend(dto: LearningTrendDto): TrendPointType[] {
  return dto.points.map((p) => ({
    date: new Date(p.date).toISOString(),
    score: p.score,
    subject: null,
  }));
}

/**
 * 聚合学情数据 → ChildAnalyticsType。
 *
 * classRank：从 ClassPerformanceDto.scores 排序计算。
 * classAverage：取 ClassPerformanceDto.averageScore。
 */
export function mapAnalytics(
  childId: string,
  weakness: StudentWeaknessDto,
  trend: LearningTrendDto,
  classPerf: ClassPerformanceDto | null,
): ChildAnalyticsType {
  let classRank: number | null = null;
  if (classPerf && classPerf.scores.length > 0) {
    const sorted = [...classPerf.scores].sort((a, b) => b.score - a.score);
    const idx = sorted.findIndex((s) => s.studentId === childId);
    classRank = idx >= 0 ? idx + 1 : null;
  }

  return {
    childId,
    weakness: mapWeakness(weakness),
    trend: mapTrend(trend),
    classRank,
    classAverage: classPerf?.averageScore ?? null,
  };
}
