import "server-only"

import { getTranslations } from "next-intl/server"

import { createNotification } from "@/modules/notifications/data-access"
import { getSubjectNameById } from "@/modules/school/data-access"
import { getParentIdsByStudentIds } from "@/modules/parent/data-access"
import type { DataScope } from "@/shared/types/permissions"

import { getGradeTrend } from "../data-access-analytics"
import { detectScoreAnomaly, type ScoreAnomalyResult } from "../stats-service"

/**
 * v4-P1-6: 成绩录入后通知学生和家长。
 * 通知失败不阻断成绩录入主流程。
 *
 * P1-1 重构：从 actions.ts 抽取到 lib/notify.ts，使 actions.ts 降至 800 行以内。
 */
export async function notifyGradeEntered(params: {
  studentIds: string[]
  title: string
  subjectId?: string
  score?: number
  fullScore?: number
}): Promise<void> {
  if (params.studentIds.length === 0) return

  const t = await getTranslations("grades")
  const subjectName = params.subjectId
    ? (await getSubjectNameById(params.subjectId)) ?? t("action.unknownSubject")
    : t("action.unknownSubject")
  const scoreText =
    params.score !== undefined && params.fullScore !== undefined
      ? `${params.score}/${params.fullScore}`
      : t("action.scoreEntered")

  const title = t("action.notificationTitle", { title: params.title })
  const content = t("action.studentNotification", { subject: subjectName, score: scoreText })

  // 通知学生本人（P2-7 改进：使用 Promise.allSettled 并行化）
  await Promise.allSettled(
    params.studentIds.map((studentId) =>
      createNotification({
        userId: studentId,
        type: "grade",
        title,
        content,
        link: "/student/grades",
      }),
    ),
  )

  // 通知家长
  try {
    const parentIds = await getParentIdsByStudentIds(params.studentIds)
    const parentContent = t("action.parentNotification", { subject: subjectName, score: scoreText })
    await Promise.allSettled(
      parentIds.map((parentId) =>
        createNotification({
          userId: parentId,
          type: "grade",
          title,
          content: parentContent,
          link: "/parent/grades",
        }),
      ),
    )
  } catch {
    // 家长查询失败忽略
  }
}

/**
 * P3-2: 检测学生成绩异常并在必要时通知班主任 + 家长。
 *
 * 异常检测逻辑：
 * 1. 拉取学生在该班级 + 科目下的历史成绩趋势（按时间升序）
 * 2. 调用 stats-service.detectScoreAnomaly 比较最新成绩与历史均分
 * 3. 若下降幅度超过阈值（10 分 / 10% 警告；20 分 / 20% 严重），
 *    则向家长推送预警通知
 *
 * 该函数为 fire-and-forget 调用，异常不阻断主流程。
 * 每个学生独立检测，互相隔离。
 *
 * @param params.studentIds - 需要检测的学生 ID 列表
 * @param params.classId - 班级 ID（用于趋势查询的 scope 过滤）
 * @param params.subjectId - 科目 ID（可选，缺失则跨科目聚合）
 * @param params.scope - 当前用户的数据范围
 */
export async function notifyScoreAnomalyIfNeeded(params: {
  studentIds: string[]
  classId: string
  subjectId?: string
  scope: DataScope
}): Promise<void> {
  if (params.studentIds.length === 0) return

  // 每个学生独立检测，互不阻断
  await Promise.allSettled(
    params.studentIds.map(async (studentId) => {
      try {
        const trendResult = await getGradeTrend({
          classId: params.classId,
          subjectId: params.subjectId,
          studentId,
          scope: params.scope,
        })

        if (!trendResult || trendResult.points.length === 0) return

        const anomaly = detectScoreAnomaly(trendResult.points)
        if (!anomaly.isAnomaly) return

        await sendAnomalyNotification({
          studentId,
          anomaly,
          subjectId: params.subjectId,
        })
      } catch (error) {
        console.error(
          `[grade-anomaly] 检测学生 ${studentId} 异常失败:`,
          error,
        )
      }
    }),
  )
}

/**
 * P3-2: 发送异常预警通知给学生本人 + 家长。
 */
async function sendAnomalyNotification(params: {
  studentId: string
  anomaly: ScoreAnomalyResult
  subjectId?: string
}): Promise<void> {
  const t = await getTranslations("grades")
  const subjectName = params.subjectId
    ? (await getSubjectNameById(params.subjectId)) ?? t("action.unknownSubject")
    : t("action.unknownSubject")

  const severityLabel =
    params.anomaly.severity === "critical"
      ? t("anomaly.severityCritical")
      : t("anomaly.severityWarning")

  const title = t("anomaly.notificationTitle", { subject: subjectName })
  const content = t("anomaly.notificationContent", {
    subject: subjectName,
    severity: severityLabel,
    latestScore: params.anomaly.latestScore.toFixed(1),
    historicalAverage: params.anomaly.historicalAverage.toFixed(1),
    drop: params.anomaly.drop.toFixed(1),
  })

  // 通知学生本人
  await Promise.allSettled([
    createNotification({
      userId: params.studentId,
      type: "grade",
      title,
      content,
      link: "/student/grades",
    }),
  ])

  // 通知家长
  try {
    const parentIds = await getParentIdsByStudentIds([params.studentId])
    await Promise.allSettled(
      parentIds.map((parentId) =>
        createNotification({
          userId: parentId,
          type: "grade",
          title,
          content,
          link: "/parent/grades",
        }),
      ),
    )
  } catch {
    // 家长查询失败忽略
  }
}
