import "server-only"

/**
 * 监控埋点接口（预留）
 *
 * 在关键 Server Action 中调用 trackEvent 记录业务事件，用于：
 * - 公告阅读率、消息回复率等关键指标统计
 * - 通知发送失败告警
 * - 用户行为漏斗分析
 *
 * 当前实现：输出到 console.info，不阻塞主流程。
 * 后续扩展：可接入外部监控服务（如 Sentry / PostHog / 自建埋点系统），
 * 只需在 trackEventToSink 中替换实现即可，调用方无需改动。
 */

/** 事件名称（使用点号分隔的命名空间，如 "announcement.published"） */
export type EventName =
  | "announcement.created"
  | "announcement.updated"
  | "announcement.published"
  | "announcement.archived"
  | "announcement.deleted"
  | "announcement.pin_toggled"
  | "announcement.marked_read"
  | "announcement.action_error"
  | "message.sent"
  | "message.send_failed"
  | "message.deleted"
  | "message.marked_read"
  | "message.star_toggled"
  | "message.recalled"
  | "message.template_created"
  | "message.group_sent"
  | "message.group_send_failed"
  | "message.reported"
  | "message.report_failed"
  | "message.user_blocked"
  | "message.user_unblocked"
  | "notification.marked_read"
  | "notification.marked_all_read"
  | "notification.sent"
  | "notification.send_failed"
  | "notification.archived"
  | "attendance.recorded"
  | "attendance.batch_recorded"
  | "attendance.updated"
  | "attendance.deleted"
  | "attendance.rules_saved"
  // L-5 在线请假流程
  | "leave_request.created"
  | "leave_request.reviewed"
  | "leave_request.cancelled"
  | "elective.course_created"
  | "elective.course_updated"
  | "elective.course_deleted"
  | "elective.selection_opened"
  | "elective.selection_closed"
  | "elective.course_selected"
  | "elective.course_dropped"
  | "elective.lottery_completed"
  // 6.7: 考试/作业模块监控事件
  | "exam.created"
  | "exam.updated"
  | "exam.published"
  | "exam.archived"
  | "exam.deleted"
  | "exam.duplicated"
  | "exam.ai_generated"
  | "exam.submitted"
  | "exam.graded"
  | "homework.created"
  | "homework.updated"
  | "homework.published"
  | "homework.archived"
  | "homework.deleted"
  | "homework.submitted"
  | "homework.graded"
  | "homework.auto_save_failed"
  | "homework.excellent_viewed"
  | "homework.remind_unsubmitted"
  | "homework.started"
  | "homework.answer_saved"
  | "homework.scan_deleted"
  // AI 模块监控事件
  | "ai.chat"
  | "ai.chat_stream"
  | "ai.similar_question"
  | "ai.grading_assist"
  | "ai.lesson_content"
  | "ai.question_variant"
  | "ai.weakness_analysis"
  | "ai.child_summary"
  | "ai.study_path"
  | "ai.explain_error"
  // 审计模块监控事件
  | "audit.exported"
  | "audit.viewed"
  | "audit.retention"
  // files 模块监控事件
  | "file.uploaded"
  | "file.upload_failed"
  | "file.deleted"
  | "file.batch_deleted"
  | "file.viewed"
  | "file.action_error"
  // auth 模块监控事件（audit-P1-9）
  // 登录成功/失败、登出、注册、2FA 启用/禁用、账户锁定、速率限制触发
  // 用于监控：登录成功率、异常登录地理/设备告警、2FA 启用率、账户锁定触发率、限流触发率
  | "auth.signin_success"
  | "auth.signin_failure"
  | "auth.signout"
  | "auth.signup"
  | "auth.2fa_enabled"
  | "auth.2fa_disabled"
  | "auth.account_locked"
  | "auth.rate_limited"
  // invitation-codes 模块监控事件（audit-P2-3）
  // 用于监控：邀请码生成/使用/删除、注册转化率（邀请码注册 vs 开放注册）
  | "invitation_codes.generated"
  | "invitation_codes.consumed"
  | "invitation_codes.deleted"

/** 埋点事件负载 */
export interface TrackEventPayload {
  /** 事件名称 */
  event: EventName
  /** 当前用户 ID（可选，未登录场景为 undefined） */
  userId?: string
  /** 目标对象 ID（如公告 ID、消息 ID） */
  targetId?: string
  /** 目标对象类型（如 "announcement"、"message"） */
  targetType?: string
  /** 附加属性（如受众人数、渠道类型） */
  properties?: Record<string, unknown>
}

/**
 * 将事件发送到外部监控服务。
 *
 * 当前为占位实现：仅输出到 console.info。
 * 接入真实服务时替换此函数体即可。
 */
function trackEventToSink(payload: TrackEventPayload): void {
  console.info(
    `[TrackEvent] ${payload.event} userId=${payload.userId ?? "-"} targetId=${payload.targetId ?? "-"}${payload.properties ? ` properties=${JSON.stringify(payload.properties)}` : ""}`
  )
}

/**
 * 记录一个监控事件。
 *
 * 非阻塞：任何异常都被吞掉，确保不影响主业务流程。
 *
 * @example
 * ```ts
 * await trackEvent({
 *   event: "announcement.published",
 *   userId: ctx.userId,
 *   targetId: id,
 *   targetType: "announcement",
 *   properties: { audienceSize: userIds.length },
 * })
 * ```
 */
export async function trackEvent(payload: TrackEventPayload): Promise<void> {
  try {
    trackEventToSink(payload)
  } catch {
    // 埋点失败不影响主流程
  }
}

/**
 * 6.7: 考试/作业模块专用埋点函数
 *
 * 封装 trackEvent，自动设置 targetType，简化调用方代码。
 *
 * @example
 * ```ts
 * await trackExamEvent("exam.published", { userId: ctx.userId, targetId: examId })
 * await trackExamEvent("homework.submitted", {
 *   userId: ctx.userId,
 *   targetId: submissionId,
 *   properties: { questionCount, duration: 1200 }
 * })
 * ```
 */
export async function trackExamEvent(
  event: Extract<EventName, `exam.${string}` | `homework.${string}`>,
  params: {
    userId?: string
    targetId?: string
    properties?: Record<string, unknown>
  }
): Promise<void> {
  const targetType = event.startsWith("exam.") ? "exam" : "homework"
  await trackEvent({
    event,
    userId: params.userId,
    targetId: params.targetId,
    targetType,
    properties: params.properties,
  })
}

/**
 * auth 模块专用埋点函数（audit-P1-9）
 *
 * 封装 trackEvent，自动设置 targetType="user"，简化 auth.ts / login-service.ts 等调用方代码。
 *
 * @example
 * ```ts
 * await trackAuthEvent("auth.signin_success", { userId: user.id, properties: { roles: ["teacher"] } })
 * await trackAuthEvent("auth.account_locked", { userId, properties: { attempts: 5 } })
 * ```
 */
export async function trackAuthEvent(
  event: Extract<EventName, `auth.${string}`>,
  params: {
    userId?: string
    targetId?: string
    properties?: Record<string, unknown>
  }
): Promise<void> {
  await trackEvent({
    event,
    userId: params.userId,
    targetId: params.targetId ?? params.userId,
    targetType: "user",
    properties: params.properties,
  })
}
