import { Router } from 'express'
import { authMiddleware, AuthRequest } from '../middleware/auth'
import { chat, chatStream, reviewContract, matchCase, predictRisks, predictRisksStream, predictStructuredStream, generateHRReportStream } from '../services/ai.service'
import { seedKnowledgeBase, addKnowledge, searchKnowledge, ensureRAGTable, searchHelp, seedHelpKnowledge } from '../services/rag.service'
import prisma from '../lib/prisma'
import { z } from 'zod'
import { decrypt } from '../lib/crypto'
import multer from 'multer'
import path from 'path'
import mammoth from 'mammoth'

const router = Router()

const PLAN_LIMITS: Record<string, { chat: number; review: number; case: number }> = {
  FREE: { chat: 10, review: 3, case: 3 },
  PRO: { chat: 100, review: 20, case: 20 },
  ENTERPRISE: { chat: 0, review: 0, case: 0 },
}

async function checkUsageLimit(orgId: string, type: 'chat' | 'review' | 'case'): Promise<void> {
  const org = await prisma.organization.findUnique({ where: { id: orgId } })
  if (!org) return
  const limits = PLAN_LIMITS[org.plan] || PLAN_LIMITS.FREE
  const limit = limits[type]
  if (limit === 0) return
  const now = new Date()
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1)
  const count = await prisma.auditLog.count({
    where: {
      orgId,
      action: `AI_${type.toUpperCase()}`,
      createdAt: { gte: monthStart },
    },
  })
  if (count >= limit) {
    throw { code: 'USAGE_LIMIT', message: `本月 AI${type === 'chat' ? '问答' : type === 'review' ? '合同审查' : '案例匹配'}次数已达上限（${limit}次），请升级套餐` }
  }
}

async function recordUsage(orgId: string, userId: string, type: 'chat' | 'review' | 'case'): Promise<void> {
  const month = new Date().toISOString().slice(0, 7)
  await prisma.auditLog.create({
    data: {
      orgId,
      userId,
      action: `AI_${type.toUpperCase()}`,
      entity: 'AI',
      entityId: null,
      detail: { month, type } as any,
      ip: '',
    },
  })
}

// 日期计算工具：计算两个日期之间的年月日差，以及相对当前的天数差
function calcDuration(start: Date, end: Date): string {
  let years = end.getFullYear() - start.getFullYear()
  let months = end.getMonth() - start.getMonth()
  let days = end.getDate() - start.getDate()
  if (days < 0) {
    months--
    const prevMonth = new Date(end.getFullYear(), end.getMonth(), 0)
    days += prevMonth.getDate()
  }
  if (months < 0) {
    years--
    months += 12
  }
  const parts: string[] = []
  if (years > 0) parts.push(`${years}年`)
  if (months > 0) parts.push(`${months}个月`)
  if (days > 0) parts.push(`${days}天`)
  return parts.length > 0 ? parts.join('') : '不足1天'
}

function daysFromNow(date: Date): number {
  return Math.floor((date.getTime() - Date.now()) / (1000 * 60 * 60 * 24))
}

/**
 * 解密身份证号（不脱敏，AI 需要完整身份证号来正确读取生日等信息）
 */
function decryptIdCard(encrypted: string | null): string {
  if (!encrypted) return '未登记'
  try {
    const plain = decrypt(encrypted)
    if (plain && plain.length >= 10) {
      return plain
    }
    return '未登记'
  } catch {
    return '未登记'
  }
}

async function buildOrgContext(orgId: string): Promise<string> {
  const [employees, risks] = await Promise.all([
    prisma.employee.findMany({
      where: { orgId, status: 'ACTIVE' },
      include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 } },
    }),
    prisma.riskItem.findMany({
      where: { orgId, status: 'PENDING' },
      include: { employee: true },
    }),
  ])

  const now = new Date()
  const empSummary = employees.map((e) => {
    const contract = e.contracts[0]
    const daysToExpire = contract?.endDate ? daysFromNow(new Date(contract.endDate)) : null
    const tenure = calcDuration(new Date(e.hireDate), now)
    const specialStatus: string[] = []
    if (e.isPregnant) specialStatus.push('孕期/哺乳期')
    if (e.isInMedicalPeriod) specialStatus.push('医疗期')
    if (e.isWorkInjured) specialStatus.push('工伤')
    return `- ${e.name}（身份证:${decryptIdCard(e.idCardNumber)}，${e.department}），入职${e.hireDate.toISOString().slice(0, 10)}（已工作${tenure}），${contract ? `合同:${contract.contractType}，${contract.endDate ? `到期${contract.endDate.toISOString().slice(0, 10)}（剩余${daysToExpire}天）` : '无固定期限'}` : '未签合同'}${specialStatus.length > 0 ? `，特殊状态:${specialStatus.join('/')}` : ''}`
  }).join('\n')

  const riskSummary = risks.map((r) => `- ${r.title}（${r.level}）：${r.description || '无详细描述'}`).join('\n')

  return `员工列表（${employees.length}人）：
${empSummary}

当前风险项（${risks.length}项）：
${riskSummary}`
}

router.post('/chat', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { messages } = req.body as { messages: { role: 'user' | 'assistant'; content: string }[] }
    if (!messages || !Array.isArray(messages)) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 messages 参数' } })
    }
    await checkUsageLimit(req.user!.orgId, 'chat')
    const orgContext = await buildOrgContext(req.user!.orgId)
    const reply = await chat(messages, orgContext)
    await recordUsage(req.user!.orgId, req.user!.id, 'chat')
    res.json({ success: true, data: { reply } })
  } catch (err) {
    next(err)
  }
})

router.post('/chat-stream', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { messages } = req.body as { messages: { role: 'user' | 'assistant'; content: string }[] }
    if (!messages || !Array.isArray(messages)) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 messages 参数' } })
    }
    await checkUsageLimit(req.user!.orgId, 'chat')
    const orgContext = await buildOrgContext(req.user!.orgId)
    res.setHeader('Content-Type', 'text/event-stream')
    res.setHeader('Cache-Control', 'no-cache')
    res.setHeader('Connection', 'keep-alive')
    res.setHeader('X-Accel-Buffering', 'no')
    res.flushHeaders()
    let usageRecorded = false
    try {
      for await (const delta of chatStream(messages, orgContext)) {
        res.write(`data: ${JSON.stringify({ delta })}\n\n`)
        if (typeof (res as any).flush === 'function') (res as any).flush()
      }
      res.write('data: [DONE]\n\n')
    } catch (streamErr: any) {
      res.write(`data: ${JSON.stringify({ error: streamErr.message || 'AI 服务异常' })}\n\n`)
      res.write('data: [DONE]\n\n')
    } finally {
      if (!usageRecorded) {
        await recordUsage(req.user!.orgId, req.user!.id, 'chat')
        usageRecorded = true
      }
    }
    res.end()
  } catch (err) {
    if (!res.headersSent) next(err)
    else res.end()
  }
})

router.post('/review', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { contractText } = req.body as { contractText: string }
    if (!contractText) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少合同文本' } })
    }
    await checkUsageLimit(req.user!.orgId, 'review')
    const result = await reviewContract(contractText)
    await recordUsage(req.user!.orgId, req.user!.id, 'review')
    res.json({ success: true, data: { text: result.text, structured: result.structured } })
  } catch (err) {
    next(err)
  }
})

router.post('/match-case', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { scenario } = req.body as { scenario: string }
    if (!scenario) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少争议情形描述' } })
    }
    await checkUsageLimit(req.user!.orgId, 'case')
    const result = await matchCase(scenario)
    await recordUsage(req.user!.orgId, req.user!.id, 'case')
    res.json({ success: true, data: { result } })
  } catch (err) {
    next(err)
  }
})

// 案例匹配结果转待办（RiskItem）
router.post('/case-to-todo', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const schema = z.object({
      employeeId: z.string().min(1),
      title: z.string().min(1),
      description: z.string().min(1),
      level: z.enum(['HIGH', 'MEDIUM', 'LOW']).default('MEDIUM'),
      type: z.enum(['CONTRACT', 'SALARY', 'TERMINATION', 'MONTHLY', 'ONBOARDING']).default('TERMINATION'),
    })
    const data = schema.parse(req.body)
    const risk = await prisma.riskItem.create({
      data: {
        orgId: req.user!.orgId,
        employeeId: data.employeeId,
        title: data.title,
        description: data.description,
        level: data.level,
        type: data.type,
        status: 'PENDING',
      },
    })
    res.json({ success: true, data: risk })
  } catch (err) {
    next(err)
  }
})

router.get('/predict', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const department = req.query.department as string
    const employeeId = req.query.employeeId as string
    const riskType = req.query.riskType as string

    let orgContext = await buildOrgContext(req.user!.orgId)
    let scopeHint = ''

    if (employeeId) {
      const emp = await prisma.employee.findFirst({ where: { id: employeeId, orgId: req.user!.orgId }, include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 }, terminations: { orderBy: { createdAt: 'desc' }, take: 1 } } })
      if (emp) {
        const contract = emp.contracts[0]
        const term = emp.terminations[0]
        const statusMap: Record<string, string> = { DRAFT: '草稿', PENDING_APPROVAL: '待审批', APPROVED: '已审批', EXECUTING: '执行中', COMPLETED: '已完成', REJECTED: '已驳回', CANCELLED: '已撤销' }
        const typeMap: Record<string, string> = { RESIGNATION: '员工离职', TERMINATION: '公司解聘' }
        const reasonMap: Record<string, string> = { NEGOTIATED: '协商一致', FAULT: '员工过错', NONFAULT: '非过错解除', LAYOFF: '经济性裁员', EXPIRED: '合同到期', RESIGNATION: '员工主动离职' }
        const checklist = term?.checklist as any || {}
        const handoverItems = (term?.handoverItems as any[]) || []
        const handoverDone = handoverItems.length > 0 ? handoverItems.every((h: any) => h.done) : false
        const agreementSigned = !!checklist.agreement_signed
        const socialInsEnd = term?.socialInsEndMonth ? `，社保截止${term.socialInsEndMonth}` : ''
        const housingFundEnd = term?.housingFundEndMonth ? `，公积金截止${term.housingFundEndMonth}` : ''
        const tenure = calcDuration(new Date(emp.hireDate), term ? new Date(term.terminationDate) : new Date())
        const contractDaysLeft = contract?.endDate ? daysFromNow(new Date(contract.endDate)) : null
        orgContext = `当前日期：${new Date().toISOString().slice(0, 10)}
员工详情：
- 姓名：${emp.name}
- 身份证号：${decryptIdCard(emp.idCardNumber)}
- 部门：${emp.department}
- 入职日期：${emp.hireDate.toISOString().slice(0, 10)}（已工作${tenure}）
- 状态：${emp.status}
- 特殊状态：${[emp.isPregnant && '孕期/哺乳期', emp.isInMedicalPeriod && '医疗期', emp.isWorkInjured && '工伤'].filter(Boolean).join('、') || '无'}
- 合同：${contract ? `${contract.contractType}，${contract.startDate.toISOString().slice(0, 10)}至${contract.endDate ? contract.endDate.toISOString().slice(0, 10) : '无固定期限'}${contractDaysLeft !== null ? `（距到期${contractDaysLeft}天）` : ''}` : '未签合同'}${term ? `\n- 离职/解聘记录：${typeMap[term.type] || term.type}，原因：${reasonMap[term.reason] || term.reason}，离职日期：${term.terminationDate.toISOString().slice(0, 10)}，流程状态：${statusMap[term.status] || term.status}，经济补偿金：¥${term.compensation.toFixed(2)}${term.resignationReason ? `，离职原因说明：${term.resignationReason}` : ''}${socialInsEnd}${housingFundEnd}，${handoverDone ? '工作交接已完成' : '工作交接未完成'}，${agreementSigned ? '已签署解除协议' : '未签署解除协议'}` : ''}`
        scopeHint = `请只针对员工【${emp.name}（身份证:${decryptIdCard(emp.idCardNumber)}）】进行风险预测，不要分析其他员工。以上数据中的工龄、天数等均已由系统计算，请直接使用，不要重新计算。`
      }
    } else if (department) {
      const employees = await prisma.employee.findMany({ where: { orgId: req.user!.orgId, department, status: 'ACTIVE' }, include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 } } })
      const empSummary = employees.map(e => `- ${e.name}（身份证:${decryptIdCard(e.idCardNumber)}），入职${e.hireDate.toISOString().slice(0, 10)}，${e.contracts[0] ? e.contracts[0].contractType : '未签合同'}`).join('\n')
      orgContext = `部门【${department}】员工列表（${employees.length}人）：\n${empSummary}`
      scopeHint = `请只针对【${department}】部门的员工进行风险预测，不要分析其他部门的员工。`
    }

    if (riskType && riskType !== 'all') {
      const riskLabel = riskType === 'contract' ? '合同' : riskType === 'salary' ? '薪酬' : riskType === 'termination' ? '解聘' : riskType
      scopeHint += `\n请重点关注【${riskLabel}】类风险，其他类型风险可简要提及。`
    }

    if (scopeHint) {
      orgContext = `${scopeHint}\n\n${orgContext}`
    }

    const result = await predictRisks(orgContext)
    res.json({ success: true, data: { result } })
  } catch (err) {
    next(err)
  }
})

router.get('/predict-stream', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const department = req.query.department as string
    const employeeId = req.query.employeeId as string
    const riskType = req.query.riskType as string

    let orgContext = await buildOrgContext(req.user!.orgId)
    let scopeHint = ''

    if (employeeId) {
      const emp = await prisma.employee.findFirst({ where: { id: employeeId, orgId: req.user!.orgId }, include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 }, terminations: { orderBy: { createdAt: 'desc' }, take: 1 } } })
      if (emp) {
        const contract = emp.contracts[0]
        const term = emp.terminations[0]
        const statusMap: Record<string, string> = { DRAFT: '草稿', PENDING_APPROVAL: '待审批', APPROVED: '已审批', EXECUTING: '执行中', COMPLETED: '已完成', REJECTED: '已驳回', CANCELLED: '已撤销' }
        const typeMap: Record<string, string> = { RESIGNATION: '员工离职', TERMINATION: '公司解聘' }
        const reasonMap: Record<string, string> = { NEGOTIATED: '协商一致', FAULT: '员工过错', NONFAULT: '非过错解除', LAYOFF: '经济性裁员', EXPIRED: '合同到期', RESIGNATION: '员工主动离职' }
        const checklist = term?.checklist as any || {}
        const handoverItems = (term?.handoverItems as any[]) || []
        const handoverDone = handoverItems.length > 0 ? handoverItems.every((h: any) => h.done) : false
        const agreementSigned = !!checklist.agreement_signed
        const socialInsEnd = term?.socialInsEndMonth ? `，社保截止${term.socialInsEndMonth}` : ''
        const housingFundEnd = term?.housingFundEndMonth ? `，公积金截止${term.housingFundEndMonth}` : ''
        const tenure = calcDuration(new Date(emp.hireDate), term ? new Date(term.terminationDate) : new Date())
        const contractDaysLeft = contract?.endDate ? daysFromNow(new Date(contract.endDate)) : null
        orgContext = `当前日期：${new Date().toISOString().slice(0, 10)}
员工详情：
- 姓名：${emp.name}
- 身份证号：${decryptIdCard(emp.idCardNumber)}
- 部门：${emp.department}
- 入职日期：${emp.hireDate.toISOString().slice(0, 10)}（已工作${tenure}）
- 状态：${emp.status}
- 特殊状态：${[emp.isPregnant && '孕期/哺乳期', emp.isInMedicalPeriod && '医疗期', emp.isWorkInjured && '工伤'].filter(Boolean).join('、') || '无'}
- 合同：${contract ? `${contract.contractType}，${contract.startDate.toISOString().slice(0, 10)}至${contract.endDate ? contract.endDate.toISOString().slice(0, 10) : '无固定期限'}${contractDaysLeft !== null ? `（距到期${contractDaysLeft}天）` : ''}` : '未签合同'}${term ? `\n- 离职/解聘记录：${typeMap[term.type] || term.type}，原因：${reasonMap[term.reason] || term.reason}，离职日期：${term.terminationDate.toISOString().slice(0, 10)}，流程状态：${statusMap[term.status] || term.status}，经济补偿金：¥${term.compensation.toFixed(2)}${term.resignationReason ? `，离职原因说明：${term.resignationReason}` : ''}${socialInsEnd}${housingFundEnd}，${handoverDone ? '工作交接已完成' : '工作交接未完成'}，${agreementSigned ? '已签署解除协议' : '未签署解除协议'}` : ''}`
        scopeHint = `请只针对员工【${emp.name}（身份证:${decryptIdCard(emp.idCardNumber)}）】进行风险预测，不要分析其他员工。以上数据中的工龄、天数等均已由系统计算，请直接使用，不要重新计算。`
      }
    } else if (department) {
      const employees = await prisma.employee.findMany({ where: { orgId: req.user!.orgId, department, status: 'ACTIVE' }, include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 } } })
      const empSummary = employees.map(e => `- ${e.name}（身份证:${decryptIdCard(e.idCardNumber)}），入职${e.hireDate.toISOString().slice(0, 10)}，${e.contracts[0] ? e.contracts[0].contractType : '未签合同'}`).join('\n')
      orgContext = `部门【${department}】员工列表（${employees.length}人）：\n${empSummary}`
      scopeHint = `请只针对【${department}】部门的员工进行风险预测，不要分析其他部门的员工。`
    }

    if (riskType && riskType !== 'all') {
      const riskLabel = riskType === 'contract' ? '合同' : riskType === 'salary' ? '薪酬' : riskType === 'termination' ? '解聘' : riskType
      scopeHint += `\n请重点关注【${riskLabel}】类风险，其他类型风险可简要提及。`
    }

    if (scopeHint) {
      orgContext = `${scopeHint}\n\n${orgContext}`
    }

    await checkUsageLimit(req.user!.orgId, 'chat')
    res.setHeader('Content-Type', 'text/event-stream')
    res.setHeader('Cache-Control', 'no-cache')
    res.setHeader('Connection', 'keep-alive')
    res.setHeader('X-Accel-Buffering', 'no')
    res.flushHeaders()

    let usageRecorded = false
    try {
      for await (const delta of predictRisksStream(orgContext)) {
        res.write(`data: ${JSON.stringify({ delta })}\n\n`)
        if (typeof (res as any).flush === 'function') (res as any).flush()
      }
      res.write('data: [DONE]\n\n')
    } catch (streamErr: any) {
      res.write(`data: ${JSON.stringify({ error: streamErr.message || 'AI 服务异常' })}\n\n`)
      res.write('data: [DONE]\n\n')
    } finally {
      if (!usageRecorded) {
        await recordUsage(req.user!.orgId, req.user!.id, 'chat')
        usageRecorded = true
      }
    }
    res.end()
  } catch (err) {
    if (!res.headersSent) next(err)
    else res.end()
  }
})

// ========== 结构化判赔预测 ==========

router.post('/predict-structured', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { scenarioType, keyFacts } = req.body as {
      scenarioType: string
      keyFacts: {
        employeeName?: string
        violationFact?: string
        region?: string
        monthlySalary?: string
        democracyStatus?: string
        disciplinaryRecord?: string
        extraInfo?: string
      }
    }
    if (!scenarioType) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少争议场景类型' } })
    }

    // 构建企业上下文：如果指定了员工则获取员工详情，否则用全量上下文
    let orgContext = await buildOrgContext(req.user!.orgId)
    if (keyFacts.employeeName) {
      const emp = await prisma.employee.findFirst({
        where: { orgId: req.user!.orgId, name: keyFacts.employeeName, status: 'ACTIVE' },
        include: {
          contracts: { orderBy: { createdAt: 'desc' }, take: 1 },
          disciplinaryRecords: { orderBy: { violationDate: 'desc' }, take: 10 },
        },
      })
      if (emp) {
        const contract = emp.contracts[0]
        const tenure = calcDuration(new Date(emp.hireDate), new Date())
        const contractDaysLeft = contract?.endDate ? daysFromNow(new Date(contract.endDate)) : null

        // 自动补全 keyFacts：系统已有数据优先，HR 手动填写覆盖
        let salary = 0
        try { salary = Number(decrypt(emp.monthlySalary)) || 0 } catch { salary = Number(emp.monthlySalary) || 0 }
        if (!keyFacts.monthlySalary && salary > 0) {
          keyFacts.monthlySalary = String(salary)
        }
        if (!keyFacts.region && emp.city) {
          keyFacts.region = emp.city
        }

        // 特殊状态已在 orgContext 中展示，不再重复追加到 extraInfo

        // 自动补充违纪记录
        if (emp.disciplinaryRecords.length > 0) {
          const recordText = emp.disciplinaryRecords.map((r: any) => {
            const typeMap: Record<string, string> = { LATE: '迟到', ABSENT: '旷工', INSUBORDINATION: '不服从管理', MISCONDUCT: '违纪', VIOLATE_POLICY: '违反制度', OTHER: '其他' }
            const severityMap: Record<string, string> = { WARNING: '警告', SERIOUS: '严重', SEVERE: '极其严重' }
            const actionMap: Record<string, string> = { ORAL_WARNING: '口头警告', WRITTEN_WARNING: '书面警告', DEDUCTION: '扣款', DEMOTION: '降职', TERMINATION: '辞退' }
            return `${r.violationDate.toISOString().slice(0, 10)} ${typeMap[r.violationType] || r.violationType}（${severityMap[r.severity] || r.severity}），处理：${actionMap[r.action] || r.action}${r.employeeAck ? '，员工已签字确认' : '，员工未签字'}`
          }).join('；')
          const discText = `系统违纪记录（${emp.disciplinaryRecords.length}条）：${recordText}`
          keyFacts.extraInfo = keyFacts.extraInfo ? `${keyFacts.extraInfo}；${discText}` : discText
        }

        orgContext = `员工详情：
- 姓名：${emp.name}
- 部门：${emp.department}
- 入职日期：${emp.hireDate.toISOString().slice(0, 10)}（已工作${tenure}）
- 状态：${emp.status}
- 特殊状态：${[emp.isPregnant && '孕期/哺乳期', emp.isInMedicalPeriod && '医疗期', emp.isWorkInjured && '工伤'].filter(Boolean).join('、') || '无'}
- 合同：${contract ? `${contract.contractType}，${contract.startDate.toISOString().slice(0, 10)}至${contract.endDate ? contract.endDate.toISOString().slice(0, 10) : '无固定期限'}${contractDaysLeft !== null ? `（距到期${contractDaysLeft}天）` : ''}` : '未签合同'}
- 违纪记录：${emp.disciplinaryRecords.length}条${emp.disciplinaryRecords.length > 0 ? `（最近：${emp.disciplinaryRecords[0].violationDate.toISOString().slice(0, 10)}）` : ''}\n\n${orgContext}`
      }
    }

    await checkUsageLimit(req.user!.orgId, 'chat')
    res.setHeader('Content-Type', 'text/event-stream')
    res.setHeader('Cache-Control', 'no-cache')
    res.setHeader('Connection', 'keep-alive')
    res.setHeader('X-Accel-Buffering', 'no')
    res.flushHeaders()

    let usageRecorded = false
    try {
      for await (const delta of predictStructuredStream(scenarioType, keyFacts, orgContext)) {
        res.write(`data: ${JSON.stringify({ delta })}\n\n`)
        if (typeof (res as any).flush === 'function') (res as any).flush()
      }
      res.write('data: [DONE]\n\n')
    } catch (streamErr: any) {
      res.write(`data: ${JSON.stringify({ error: streamErr.message || 'AI 服务异常' })}\n\n`)
      res.write('data: [DONE]\n\n')
    } finally {
      if (!usageRecorded) {
        await recordUsage(req.user!.orgId, req.user!.id, 'chat')
        usageRecorded = true
      }
    }
    res.end()
  } catch (err) {
    if (!res.headersSent) next(err)
    else res.end()
  }
})

// ========== AI 会话历史 ==========

router.get('/conversations', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const type = req.query.type as string | undefined
    const where: any = { orgId: req.user!.orgId, userId: req.user!.id }
    if (type) {
      const prefixes: Record<string, string> = {
        chat: 'chat:',
        predict: 'predict:',
        review: 'review:',
        case: 'case:',
      }
      const prefix = prefixes[type] || type
      where.title = { startsWith: prefix }
    }
    const conversations = await prisma.aIConversation.findMany({
      where,
      orderBy: { updatedAt: 'desc' },
      take: 50,
      select: { id: true, title: true, createdAt: true, updatedAt: true },
    })
    res.json({ success: true, data: conversations })
  } catch (err) {
    next(err)
  }
})

router.get('/conversations/:id', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const conv = await prisma.aIConversation.findFirst({
      where: { id: req.params.id, orgId: req.user!.orgId, userId: req.user!.id },
    })
    if (!conv) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '会话不存在' } })
    res.json({ success: true, data: conv })
  } catch (err) {
    next(err)
  }
})

router.post('/conversations', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { title, messages } = req.body as { title?: string; messages: any[] }
    const conv = await prisma.aIConversation.create({
      data: {
        orgId: req.user!.orgId,
        userId: req.user!.id,
        title: title || (messages.find(m => m.role === 'user')?.content.slice(0, 30) || '新对话'),
        messages: messages || [],
      },
    })
    res.json({ success: true, data: conv })
  } catch (err) {
    next(err)
  }
})

router.put('/conversations/:id', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { title, messages } = req.body as { title?: string; messages?: any[] }
    const conv = await prisma.aIConversation.updateMany({
      where: { id: req.params.id, orgId: req.user!.orgId, userId: req.user!.id },
      data: {
        ...(title ? { title } : {}),
        ...(messages ? { messages } : {}),
      },
    })
    if (conv.count === 0) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '会话不存在' } })
    res.json({ success: true })
  } catch (err) {
    next(err)
  }
})

router.delete('/conversations/:id', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const conv = await prisma.aIConversation.deleteMany({
      where: { id: req.params.id, orgId: req.user!.orgId, userId: req.user!.id },
    })
    if (conv.count === 0) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '会话不存在' } })
    res.json({ success: true })
  } catch (err) {
    next(err)
  }
})

// ========== AI 审查记录保存到员工档案 ==========

router.post('/review/save', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const schema = z.object({
      employeeId: z.string(),
      type: z.enum(['REVIEW', 'CASE']),
      input: z.string(),
      result: z.string(),
    })
    const data = schema.parse(req.body)
    const record = await prisma.aIReviewRecord.create({
      data: {
        orgId: req.user!.orgId,
        employeeId: data.employeeId,
        type: data.type,
        input: data.input,
        result: data.result,
        createdBy: req.user!.id,
      },
    })
    res.json({ success: true, data: record })
  } catch (err) {
    next(err)
  }
})

router.get('/review/employee/:employeeId', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const records = await prisma.aIReviewRecord.findMany({
      where: { orgId: req.user!.orgId, employeeId: req.params.employeeId },
      orderBy: { createdAt: 'desc' },
      take: 20,
    })
    res.json({ success: true, data: records })
  } catch (err) {
    next(err)
  }
})

// RAG 知识库管理
router.post('/rag/seed', authMiddleware, async (_req: AuthRequest, res, next) => {
  try {
    await seedKnowledgeBase()
    res.json({ success: true, data: { message: '知识库初始化完成' } })
  } catch (err) {
    next(err)
  }
})

router.post('/rag/add', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { title, content, source, category } = req.body
    if (!title || !content) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 title 或 content' } })
    }
    const result = await addKnowledge(title, content, source || '自定义', category || '其他')
    res.json({ success: true, data: result })
  } catch (err) {
    next(err)
  }
})

router.post('/rag/search', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { query, topK } = req.body
    if (!query) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 query' } })
    }
    const results = await searchKnowledge(query, topK || 5)
    res.json({ success: true, data: { results } })
  } catch (err) {
    next(err)
  }
})

// 知识库列表
router.get('/rag/list', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    await ensureRAGTable()
    const category = req.query.category as string | undefined
    const items = category
      ? await prisma.$queryRaw`SELECT id, title, content, source, category, created_at FROM rag_knowledge WHERE category = ${category} ORDER BY created_at DESC LIMIT 200` as any[]
      : await prisma.$queryRaw`SELECT id, title, content, source, category, created_at FROM rag_knowledge ORDER BY created_at DESC LIMIT 200` as any[]
    res.json({ success: true, data: items })
  } catch (err) {
    next(err)
  }
})

// 帮助文档 RAG 搜索（语义匹配）
router.post('/rag/help-search', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { query, topK } = req.body
    if (!query) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 query' } })
    }
    const results = await searchHelp(query, topK || 5)
    res.json({ success: true, data: { results } })
  } catch (err) {
    next(err)
  }
})

// 帮助文档初始化（注入帮助种子数据到 RAG 知识库）
router.post('/rag/help-seed', authMiddleware, async (_req: AuthRequest, res, next) => {
  try {
    await seedHelpKnowledge()
    res.json({ success: true, data: { message: '帮助文档已注入知识库' } })
  } catch (err) {
    next(err)
  }
})

// 删除知识条目
router.delete('/rag/:id', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    await ensureRAGTable()
    await prisma.$executeRaw`DELETE FROM rag_knowledge WHERE id = ${req.params.id}`
    res.json({ success: true })
  } catch (err) {
    next(err)
  }
})

// ========== 合同到期决策助手 ==========

router.post('/contract-decision', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const { employeeId } = req.body as { employeeId: string }
    if (!employeeId) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 employeeId' } })
    }

    const emp = await prisma.employee.findFirst({
      where: { id: employeeId, orgId: req.user!.orgId },
      include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 } },
    })
    if (!emp) {
      return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '员工不存在' } })
    }

    const contract = emp.contracts[0]
    if (!contract || !contract.endDate) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '该员工无固定期限合同或未签合同，不适用到期决策' } })
    }

    // 解密薪资
    let salary = 0
    try { salary = Number(decrypt(emp.monthlySalary)) || 0 } catch { salary = Number(emp.monthlySalary) || 0 }

    const today = new Date()
    const hireDate = emp.hireDate
    const endDate = contract.endDate
    const totalMonths = (endDate.getFullYear() - hireDate.getFullYear()) * 12 + (endDate.getMonth() - hireDate.getMonth())
    const years = Math.floor(totalMonths / 12)
    const remainingMonths = totalMonths % 12
    let n = years
    if (remainingMonths >= 6) n = years + 1
    else if (remainingMonths > 0) n = years + 0.5
    if (n <= 0) n = 0.5

    const daysToExpiry = Math.ceil((endDate.getTime() - today.getTime()) / 86400000)

    // 三选项成本对比
    const options = [
      {
        key: 'RENEW',
        title: '续签合同',
        cost: 0,
        description: '与员工续签劳动合同，保持劳动关系延续',
        legalRisk: '低',
        details: {
          compensation: 0,
          noticePeriod: '无需通知',
          notes: '续签时如维持或提高条件，员工拒绝则无需补偿；降低条件员工拒绝需支付 N',
        },
      },
      {
        key: 'EXPIRE_NO_RENEW',
        title: '到期不续签',
        cost: salary * n,
        description: '合同到期后公司决定不续签，需支付经济补偿金 N',
        legalRisk: '中',
        details: {
          compensation: salary * n,
          n,
          monthlySalary: salary,
          noticePeriod: '建议提前30天书面通知',
          notes: '公司提出不续签需支付经济补偿金（N）；员工主动提出不续签则无需支付',
        },
      },
      {
        key: 'EXPIRE_WAIT',
        title: '逾期不处理（风险最高）',
        cost: salary * (n + 1),
        description: '合同到期后继续用工但不签新合同，可能被认定为事实劳动关系',
        legalRisk: '高',
        details: {
          compensation: salary * (n + 1),
          n,
          monthlySalary: salary,
          notes: '逾期超过1个月未续签，员工可主张双倍工资；满1年视为已订立无固定期限劳动合同',
        },
      },
    ]

    // 构建 AI 建议请求
    const decisionContext = `员工合同到期决策分析：
- 姓名：${emp.name}
- 部门：${emp.department}
- 入职日期：${hireDate.toISOString().slice(0, 10)}
- 合同到期日：${endDate.toISOString().slice(0, 10)}（距今${daysToExpiry}天）
- 月薪：¥${salary.toFixed(2)}
- 工龄：${years}年${remainingMonths}月（经济补偿月数 N=${n}）
- 特殊状态：${[emp.isPregnant && '孕期/哺乳期', emp.isInMedicalPeriod && '医疗期', emp.isWorkInjured && '工伤'].filter(Boolean).join('、') || '无'}

三选项成本对比：
1. 续签：成本 ¥0
2. 到期不续签：成本 ¥${(salary * n).toFixed(2)}（经济补偿 N=${n}）
3. 逾期不处理：风险成本 ¥${(salary * (n + 1)).toFixed(2)}（双倍工资风险）

请给出专业建议，分析每个选项的法律风险和实际影响，推荐最优方案。`

    let aiAdvice = ''
    try {
      await checkUsageLimit(req.user!.orgId, 'chat')
      const result = await chat([{ role: 'user', content: decisionContext }], '')
      aiAdvice = result
      await recordUsage(req.user!.orgId, req.user!.id, 'chat')
    } catch {
      aiAdvice = 'AI 建议生成失败，请参考以上成本对比数据自行判断。'
    }

    res.json({
      success: true,
      data: {
        employee: {
          id: emp.id,
          name: emp.name,
          department: emp.department,
          hireDate: hireDate.toISOString().slice(0, 10),
          contractEndDate: endDate.toISOString().slice(0, 10),
          daysToExpiry,
          monthlySalary: salary,
          workYears: years,
          workMonths: remainingMonths,
          n,
          isPregnant: emp.isPregnant,
          isInMedicalPeriod: emp.isInMedicalPeriod,
          isWorkInjured: emp.isWorkInjured,
        },
        options,
        aiAdvice,
      },
    })
  } catch (err) {
    next(err)
  }
})

// ========== AI 人力分析报告 ==========

router.post('/hr-report-stream', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const orgId = req.user!.orgId
    const month = new Date().toISOString().slice(0, 7)

    // 聚合企业数据
    const [employees, risks, batches] = await Promise.all([
      prisma.employee.findMany({
        where: { orgId, status: 'ACTIVE' },
        select: {
          name: true, department: true, gender: true, hireDate: true,
          birthDate: true, education: true, city: true,
          isPregnant: true, isInMedicalPeriod: true, isWorkInjured: true,
          contracts: { orderBy: { createdAt: 'desc' }, take: 1, select: { contractType: true, endDate: true, startDate: true } },
        },
      }),
      prisma.riskItem.findMany({
        where: { orgId, status: 'PENDING' },
        select: { title: true, level: true, type: true, description: true, employee: { select: { name: true } } },
      }),
      prisma.payrollBatch.findMany({
        where: { orgId, month, status: 'ARCHIVED' },
        select: { totalPay: true, totalSocialOrg: true, totalHousingOrg: true, totalTax: true, employeeCount: true },
      }),
    ])

    const now = new Date()

    // 员工概况
    const genderDist: Record<string, number> = {}
    const eduDist: Record<string, number> = {}
    const deptDist: Record<string, number> = {}
    let totalAge = 0, ageCount = 0
    let totalTenure = 0

    for (const e of employees) {
      const g = e.gender || '未知'
      genderDist[g] = (genderDist[g] || 0) + 1
      const edu = e.education || '未知'
      eduDist[edu] = (eduDist[edu] || 0) + 1
      deptDist[e.department] = (deptDist[e.department] || 0) + 1
      if (e.birthDate) {
        totalAge += now.getFullYear() - e.birthDate.getFullYear()
        ageCount++
      }
      totalTenure += (now.getTime() - e.hireDate.getTime()) / (365.25 * 24 * 3600 * 1000)
    }

    const avgAge = ageCount > 0 ? (totalAge / ageCount).toFixed(1) : '未知'
    const avgTenure = employees.length > 0 ? (totalTenure / employees.length).toFixed(1) : '0'

    // 成本数据
    const monthCost = batches.reduce((acc, b) => ({
      totalPay: acc.totalPay + b.totalPay,
      totalSocialOrg: acc.totalSocialOrg + b.totalSocialOrg,
      totalHousingOrg: acc.totalHousingOrg + b.totalHousingOrg,
      totalTax: acc.totalTax + b.totalTax,
      employeeCount: acc.employeeCount + b.employeeCount,
    }), { totalPay: 0, totalSocialOrg: 0, totalHousingOrg: 0, totalTax: 0, employeeCount: 0 })

    const totalCost = monthCost.totalPay + monthCost.totalSocialOrg + monthCost.totalHousingOrg
    const perCapita = monthCost.employeeCount > 0 ? totalCost / monthCost.employeeCount : 0

    // 特殊状态员工
    const specialEmployees = employees
      .filter(e => e.isPregnant || e.isInMedicalPeriod || e.isWorkInjured)
      .map(e => {
        const tags: string[] = []
        if (e.isPregnant) tags.push('孕期/哺乳期')
        if (e.isInMedicalPeriod) tags.push('医疗期')
        if (e.isWorkInjured) tags.push('工伤')
        return `${e.name}（${e.department}）：${tags.join('、')}`
      })

    // 合同即将到期（30天内）
    const expiringContracts = employees
      .filter(e => {
        const c = e.contracts[0]
        if (!c?.endDate) return false
        const days = Math.floor((c.endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24))
        return days >= 0 && days <= 30
      })
      .map(e => `${e.name}（${e.department}），到期日：${e.contracts[0].endDate?.toISOString().slice(0, 10)}`)

    const orgData = `企业人力数据概览（截至 ${now.toISOString().slice(0, 10)}）：

【员工概况】
- 在职员工总数：${employees.length} 人
- 性别分布：${Object.entries(genderDist).map(([k, v]) => `${k} ${v}人`).join('、')}
- 学历分布：${Object.entries(eduDist).map(([k, v]) => `${k} ${v}人`).join('、')}
- 平均年龄：${avgAge} 岁
- 平均司龄：${avgTenure} 年
- 部门分布：${Object.entries(deptDist).map(([k, v]) => `${k} ${v}人`).join('、')}

【本月人力成本】
- 工资总额：¥${monthCost.totalPay.toFixed(2)}
- 企业社保：¥${monthCost.totalSocialOrg.toFixed(2)}
- 企业公积金：¥${monthCost.totalHousingOrg.toFixed(2)}
- 个人所得税：¥${monthCost.totalTax.toFixed(2)}
- 企业总成本：¥${totalCost.toFixed(2)}
- 人均成本：¥${perCapita.toFixed(2)}
- 覆盖人数：${monthCost.employeeCount} 人

【当前风险项】（${risks.length} 项）
${risks.map(r => `- [${r.level}] ${r.title}（${r.employee?.name || '通用'}）：${r.description || '无描述'}`).join('\n')}

【特殊状态员工】（${specialEmployees.length} 人）
${specialEmployees.length > 0 ? specialEmployees.join('\n') : '无'}

【合同即将到期】（30天内，${expiringContracts.length} 人）
${expiringContracts.length > 0 ? expiringContracts.join('\n') : '无'}`

    await checkUsageLimit(orgId, 'chat')
    res.setHeader('Content-Type', 'text/event-stream')
    res.setHeader('Cache-Control', 'no-cache')
    res.setHeader('Connection', 'keep-alive')
    res.setHeader('X-Accel-Buffering', 'no')
    res.flushHeaders()

    let usageRecorded = false
    try {
      for await (const delta of generateHRReportStream(orgData)) {
        res.write(`data: ${JSON.stringify({ delta })}\n\n`)
        if (typeof (res as any).flush === 'function') (res as any).flush()
      }
      res.write('data: [DONE]\n\n')
    } catch (streamErr: any) {
      res.write(`data: ${JSON.stringify({ error: streamErr.message || 'AI 服务异常' })}\n\n`)
      res.write('data: [DONE]\n\n')
    } finally {
      if (!usageRecorded) {
        await recordUsage(orgId, req.user!.id, 'chat')
        usageRecorded = true
      }
    }
    res.end()
  } catch (err) {
    if (!res.headersSent) next(err)
    else res.end()
  }
})

// ========== AI 文件审查上传 ==========

const reviewUpload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: 100 * 1024 * 1024 },
  fileFilter: (_req, file, cb) => {
    const ext = path.extname(file.originalname).toLowerCase()
    if (ext !== '.docx' && ext !== '.txt' && ext !== '.pdf') {
      return cb(null, false)
    }
    cb(null, true)
  },
})

router.post('/review/upload', authMiddleware, reviewUpload.single('file'), async (req: AuthRequest, res, next) => {
  try {
    if (!req.file) {
      return res.status(400).json({ success: false, error: { code: 'NO_FILE', message: '请上传 .docx / .txt / .pdf 文件' } })
    }
    const ext = path.extname(req.file.originalname).toLowerCase()
    let text = ''
    if (ext === '.docx') {
      const result = await mammoth.extractRawText({ buffer: req.file.buffer })
      text = result.value
    } else if (ext === '.txt') {
      text = req.file.buffer.toString('utf-8')
    } else if (ext === '.pdf') {
      // PDF 简单文本提取：提取括号内的文本流内容
      const raw = req.file.buffer.toString('latin1')
      const textMatches = raw.match(/\(([^)]+)\)/g)
      if (textMatches) {
        text = textMatches.map(m => m.slice(1, -1).replace(/\\[nrt()\\]/g, ' ')).join(' ')
      }
      if (!text || text.trim().length < 10) {
        return res.status(400).json({ success: false, error: { code: 'PDF_PARSE_FAIL', message: 'PDF 文件无法提取文本，可能是扫描件或图片格式。建议将文件另存为 .docx 后上传' } })
      }
    } else {
      return res.status(400).json({ success: false, error: { code: 'UNSUPPORTED', message: '暂不支持该格式，请上传 .docx / .txt / .pdf 文件' } })
    }
    if (text.length > 50000) {
      text = text.slice(0, 50000) + '\n\n[文本过长，已截断]'
    }
    res.json({ success: true, data: { text, fileName: req.file.originalname } })
  } catch (err) {
    next(err)
  }
})

// ========== 人工咨询服务 ==========

router.post('/consultation', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const schema = z.object({
      type: z.enum(['LEGAL', 'ARBITRATION', 'COURT']),
      title: z.string().min(1, '标题不能为空'),
      description: z.string().min(1, '描述不能为空'),
      contactName: z.string().min(1, '联系人不能为空'),
      contactPhone: z.string().regex(/^1[3-9]\d{9}$/, '手机号格式不正确'),
      aiConversationId: z.string().optional(),
      remark: z.string().optional(),
    })
    const data = schema.parse(req.body)
    const consultation = await (prisma as any).consultation.create({
      data: {
        orgId: req.user!.orgId,
        type: data.type,
        title: data.title,
        description: data.description,
        contactName: data.contactName,
        contactPhone: data.contactPhone,
        aiConversationId: data.aiConversationId || null,
        remark: data.remark || null,
        createdBy: req.user!.id,
      },
    })
    res.json({ success: true, data: consultation })
  } catch (err) {
    next(err)
  }
})

router.get('/consultations', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const consultations = await (prisma as any).consultation.findMany({
      where: { orgId: req.user!.orgId },
      orderBy: { createdAt: 'desc' },
      take: 50,
    })
    res.json({ success: true, data: consultations })
  } catch (err) {
    next(err)
  }
})

router.patch('/consultations/:id', authMiddleware, async (req: AuthRequest, res, next) => {
  try {
    const schema = z.object({
      status: z.enum(['PENDING', 'CONTACTED', 'COMPLETED', 'CANCELLED']),
      remark: z.string().optional(),
    })
    const data = schema.parse(req.body)
    const result = await (prisma as any).consultation.updateMany({
      where: { id: req.params.id, orgId: req.user!.orgId },
      data: {
        status: data.status,
        ...(data.remark !== undefined ? { remark: data.remark } : {}),
      },
    })
    if (result.count === 0) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '咨询记录不存在' } })
    res.json({ success: true })
  } catch (err) {
    next(err)
  }
})

export default router
