import "server-only"

/**
 * AI 内容安全过滤
 *
 * 多层防护：
 * 1. 输入过滤：检查用户输入是否包含不当内容
 * 2. 输出过滤：检查 AI 回复是否包含不当内容
 * 3. 每日限制：按用户 + 日期计数（原子操作，防 TOCTOU 竞态）
 *
 * 参考 Khanmigo 的多层 moderation 模式。
 *
 * 注意：当前为内存实现，多实例部署需替换为 Redis（INCR + EXPIRE）。
 */

// ---------------------------------------------------------------------------
// 不当内容关键词（基础过滤，生产环境应接入专业 Moderation API）
// ---------------------------------------------------------------------------

const BLOCKED_INPUT_PATTERNS: readonly RegExp[] = [
  /\b(violence|kill|murder|suicide|self[- ]?harm|cut myself)\b/i,
  /\b(porn|sex|nude|nsfw|explicit)\b/i,
  /\b(drug|cocaine|heroin|weed|marijuana)\b/i,
  /\b(hack|exploit|malware|virus|phishing)\b/i,
  // PII 请求
  /\b(your (password|credit card|ssn|social security|bank account))\b/i,
  /\b(home address|phone number|real name)\b/i,
]

const BLOCKED_OUTPUT_PATTERNS: readonly RegExp[] = [
  /\b(violence|kill|murder|suicide|self[- ]?harm)\b/i,
  /\b(porn|sex|nude|nsfw|explicit)\b/i,
  /\b(drug|cocaine|heroin)\b/i,
]

const STUDENT_BLOCKED_PATTERNS: readonly RegExp[] = [
  // 学生侧额外限制：禁止直接给出作业答案
  /\b(here is the (complete )?answer|the answer is:?)\b/i,
  // 强化：匹配"答案是 X" / "正确答案是 X" / "final answer: X"
  /\b(the (correct )?answer is\s*[:：]?\s*[A-Z\d])/i,
  /\bfinal answer[:：]\s*\S+/i,
  /\b答案(是|应该为|为)\s*[:：]?\s*[A-F\d]/i,
]

// ---------------------------------------------------------------------------
// 输入过滤
// ---------------------------------------------------------------------------

export type SafetyFilterResult = {
  blocked: boolean
  reason?: string
}

export const filterUserInput = (
  content: string,
  options?: { isStudent?: boolean }
): SafetyFilterResult => {
  const text = String(content ?? "")

  for (const pattern of BLOCKED_INPUT_PATTERNS) {
    if (pattern.test(text)) {
      return {
        blocked: true,
        reason: "Input contains inappropriate content",
      }
    }
  }

  if (options?.isStudent) {
    for (const pattern of STUDENT_BLOCKED_PATTERNS) {
      if (pattern.test(text)) {
        return {
          blocked: true,
          reason: "Student input blocked by safety filter",
        }
      }
    }
  }

  return { blocked: false }
}

// ---------------------------------------------------------------------------
// 输出过滤
// ---------------------------------------------------------------------------

export const filterAiOutput = (
  content: string,
  options?: { isStudent?: boolean }
): SafetyFilterResult => {
  const text = String(content ?? "")

  for (const pattern of BLOCKED_OUTPUT_PATTERNS) {
    if (pattern.test(text)) {
      return {
        blocked: true,
        reason: "AI output contains inappropriate content",
      }
    }
  }

  if (options?.isStudent) {
    for (const pattern of STUDENT_BLOCKED_PATTERNS) {
      if (pattern.test(text)) {
        return {
          blocked: true,
          reason: "AI output blocked for student safety",
        }
      }
    }
  }

  return { blocked: false }
}

// ---------------------------------------------------------------------------
// 每日限制（原子操作，防 TOCTOU 竞态）
// ---------------------------------------------------------------------------

const DAILY_LIMITS: Record<string, number> = {
  student: 50,
  teacher: 200,
  parent: 30,
  admin: 500,
}

export const getDailyLimit = (role: string): number => {
  return DAILY_LIMITS[role] ?? 50
}

/**
 * 每日使用计数（内存实现，多实例需替换为 Redis）
 *
 * 注意：当前为单实例内存映射，多实例部署下每个实例独立计数，
 * 实际可用次数 = 限额 × 实例数。生产环境应接入 Redis INCR + EXPIRE。
 */
const dailyUsageMap = new Map<string, { date: string; count: number }>()

export const checkDailyLimit = (userId: string, role: string): SafetyFilterResult => {
  const today = new Date().toISOString().slice(0, 10)
  const key = `${userId}:${today}`
  const limit = getDailyLimit(role)
  const current = dailyUsageMap.get(key)

  if (!current) {
    return { blocked: false }
  }

  if (current.count >= limit) {
    return {
      blocked: true,
      reason: `Daily limit reached (${current.count}/${limit})`,
    }
  }

  return { blocked: false }
}

export const incrementDailyUsage = (userId: string): void => {
  const today = new Date().toISOString().slice(0, 10)
  const key = `${userId}:${today}`
  const current = dailyUsageMap.get(key)

  if (current && current.date === today) {
    current.count += 1
  } else {
    dailyUsageMap.set(key, { date: today, count: 1 })
  }

  // 清理过期条目（防止内存泄漏）
  if (dailyUsageMap.size > 10000) {
    for (const [k, v] of dailyUsageMap.entries()) {
      if (v.date !== today) {
        dailyUsageMap.delete(k)
      }
    }
  }
}

/**
 * 原子化检查并递增每日使用计数
 *
 * 解决 checkDailyLimit + incrementDailyUsage 分离导致的 TOCTOU 竞态：
 * 并发请求在限额临界点同时通过检查，导致超额。
 *
 * 此函数在一次调用内完成「递增 + 判断是否超限」，
 * 若递增后超过限额，回滚计数并返回 blocked。
 *
 * @returns { blocked, currentCount, limit } — blocked 为 true 表示已超限
 */
export const tryConsumeDailyQuota = (
  userId: string,
  role: string
): { blocked: boolean; currentCount: number; limit: number } => {
  const today = new Date().toISOString().slice(0, 10)
  const key = `${userId}:${today}`
  const limit = getDailyLimit(role)
  const current = dailyUsageMap.get(key)

  // 原子递增
  const newCount = current && current.date === today ? current.count + 1 : 1
  dailyUsageMap.set(key, { date: today, count: newCount })

  // 清理过期条目
  if (dailyUsageMap.size > 10000) {
    for (const [k, v] of dailyUsageMap.entries()) {
      if (v.date !== today) {
        dailyUsageMap.delete(k)
      }
    }
  }

  if (newCount > limit) {
    // 超限，回滚计数（不惩罚用户因竞态多出的尝试）
    dailyUsageMap.set(key, { date: today, count: limit })
    return { blocked: true, currentCount: limit, limit }
  }

  return { blocked: false, currentCount: newCount, limit }
}

/**
 * 回退每日使用计数（当 AI 调用失败或内容被过滤时调用）
 *
 * 确保用户不会因 AI 输出被过滤或调用失败而损失配额。
 */
export const refundDailyQuota = (userId: string): void => {
  const today = new Date().toISOString().slice(0, 10)
  const key = `${userId}:${today}`
  const current = dailyUsageMap.get(key)

  if (current && current.date === today && current.count > 0) {
    current.count -= 1
  }
}

// ---------------------------------------------------------------------------
// 苏格拉底式辅导输出校验
// ---------------------------------------------------------------------------

export type SocraticValidationResult = {
  valid: boolean
  reason?: string
}

/**
 * 校验 AI 回复是否符合苏格拉底式辅导原则
 *
 * 规则：
 * 1. 回复必须以问号结尾（中英文均可）
 * 2. 不得包含超过 2 句连续陈述句而不提问
 * 3. 不得直接给出最终答案（复用 STUDENT_BLOCKED_PATTERNS）
 *
 * 用于学生侧 AI 对话，强制引导式教学。
 */
export const validateSocraticOutput = (content: string): SocraticValidationResult => {
  const text = String(content ?? "").trim()

  if (!text) {
    return { valid: false, reason: "Empty response" }
  }

  // 检查是否直接给出答案
  for (const pattern of STUDENT_BLOCKED_PATTERNS) {
    if (pattern.test(text)) {
      return { valid: false, reason: "Response contains direct answer" }
    }
  }

  // 检查是否以问号结尾
  if (!/[?？]$/.test(text)) {
    return { valid: false, reason: "Response must end with a question" }
  }

  // 检查连续陈述句数量（按句号/感叹号分割）
  const sentences = text.split(/[。！？.!?]/).filter((s) => s.trim().length > 0)
  let consecutiveStatements = 0
  for (const sentence of sentences) {
    // 如果句子本身是疑问句（包含 ? 或 ？），重置计数
    if (/[?？]/.test(sentence)) {
      consecutiveStatements = 0
    } else {
      consecutiveStatements += 1
      if (consecutiveStatements > 2) {
        return { valid: false, reason: "Too many consecutive statements without a question" }
      }
    }
  }

  return { valid: true }
}
