/**
 * 电子签署路由 — 管理端
 *
 * 完整签署流程：
 * 1. HR 发起签署（校验组织电子签开关 + 自动渲染模板文件内容 + 创建证据链）
 * 2. 员工在 portal 端查看待签文件 → 发送验证码 → 验证码确认签署
 * 3. 签署完成 → 回写合同 + 追加证据链 + 生成签署确认文件
 * 4. 易签宝回调（对接后启用）：更新状态 + 回写PDF
 *
 * 证据链事件：发起签署 / 验证码发送 / 签署完成 / 取消签署
 */
import { Router, Response, NextFunction } from 'express'
import { z } from 'zod'
import jwt from 'jsonwebtoken'
import multer from 'multer'
import path from 'path'
import fs from 'fs'
import prisma from '../lib/prisma'
import { authMiddleware, AuthRequest } from '../middleware/auth'
import { auditLog } from '../middleware/auditLog'
import { createEvidence, appendEvidence } from '../services/evidence.service'
import { renderTemplate, getTemplateById } from '../services/template.service'
import { decrypt } from '../lib/crypto'

const router = Router()
router.use(authMiddleware)

const AUTO_LOGIN_SECRET = process.env.JWT_SECRET || 'dev-secret'

/** 场景与组织电子签开关的映射 */
const SCENE_ORG_FLAG_MAP: Record<string, string | null> = {
  CONTRACT: null, // 合同签署不需要额外开关（默认允许）
  RESIGNATION: null, // 离职协议不需要额外开关
  POLICY: 'esignPolicyEnabled',
  PAYSLIP: 'esignPayslipEnabled',
  ONBOARDING: 'esignOnboardingEnabled',
}

/** 场景与模板ID的映射（自动渲染文件内容） */
const SCENE_TEMPLATE_MAP: Record<string, string | null> = {
  CONTRACT: 'tpl_fixed_term_contract',
  RESIGNATION: 'tpl_termination_agreement',
  POLICY: null,
  PAYSLIP: null,
  ONBOARDING: null,
}

const createSignSchema = z.object({
  contractId: z.string().optional(),
  employeeId: z.string().min(1),
  documentTitle: z.string().min(1),
  documentContent: z.string().optional(),
  remark: z.string().optional(),
  scene: z.string().optional(),
  templateId: z.string().optional(), // 可指定模板，不传则按 scene 自动匹配
  templateVars: z.record(z.string()).optional(), // 模板变量
})

/**
 * 签署记录列表
 */
router.get('/', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const status = req.query.status as string | undefined
    const scene = req.query.scene as string | undefined
    const records = await prisma.eSignRecord.findMany({
      where: {
        orgId: req.user!.orgId,
        ...(status && { status }),
        ...(scene && { scene }),
      },
      include: {
        employee: { select: { id: true, name: true, department: true, phone: true, idCardNumber: true } },
      },
      orderBy: { createdAt: 'desc' },
    })
    const recordsWithIdCard = records.map((r: any) => ({
      ...r,
      employee: r.employee ? { ...r.employee, idCardNumber: (() => { try { const v = r.employee.idCardNumber; return v ? (v.includes(':') ? decrypt(v) : v) : null } catch { return null } })() } : r.employee,
    }))
    res.json({ success: true, data: recordsWithIdCard })
  } catch (err) { next(err) }
})

/**
 * 待签合同列表（按员工聚合）
 * GET /esign/pending
 *
 * 汇总两类未签署记录，按员工聚合：
 * 1. EsignRecord 中 status 为 PENDING/SIGNING 的（所有场景）
 * 2. LaborContract 中 signDate 为空且员工在职的（纸质合同未登记签署日期）
 *
 * 返回格式：[{ employeeId, name, department, phone, pendingItems: [{ type, title, scene, signMethod, status, createdAt, recordId, contractId }] }]
 */
router.get('/pending', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const orgId = req.user!.orgId

    // 1. 查询未完成的 EsignRecord
    const pendingEsign = await prisma.eSignRecord.findMany({
      where: {
        orgId,
        status: { in: ['PENDING', 'SIGNING'] },
      },
      include: {
        employee: { select: { id: true, name: true, department: true, phone: true, status: true, idCardNumber: true } },
      },
      orderBy: { createdAt: 'desc' },
    })

    // 2. 查询 signDate 为空的 LaborContract（且员工在职）
    const pendingContracts = await prisma.laborContract.findMany({
      where: {
        orgId,
        signDate: null,
        employee: { status: 'ACTIVE' },
      },
      include: {
        employee: { select: { id: true, name: true, department: true, phone: true, status: true, idCardNumber: true } },
      },
      orderBy: { createdAt: 'desc' },
    })

    // 3. 按员工聚合
    const employeeMap = new Map<string, {
      employeeId: string
      name: string
      department: string | null
      phone: string | null
      idCardNumber: string | null
      pendingItems: any[]
    }>()

    // 辅助函数：添加员工到 map
    const ensureEmployee = (emp: { id: string; name: string; department: string | null; phone: string | null; idCardNumber?: string | null }) => {
      if (!employeeMap.has(emp.id)) {
        employeeMap.set(emp.id, {
          employeeId: emp.id,
          name: emp.name,
          department: emp.department,
          phone: emp.phone,
          idCardNumber: (() => { try { const v = emp.idCardNumber; return v ? (v.includes(':') ? decrypt(v) : v) : null } catch { return null } })(),
          pendingItems: [],
        })
      }
      return employeeMap.get(emp.id)!
    }

    // 汇总 EsignRecord
    for (const r of pendingEsign) {
      const emp = ensureEmployee(r.employee)
      emp.pendingItems.push({
        type: 'esign',
        recordId: r.id,
        contractId: r.contractId,
        title: r.documentTitle,
        scene: r.scene,
        signMethod: r.signMethod,
        status: r.status,
        createdAt: r.createdAt,
      })
    }

    // 汇总 LaborContract（排除已有 EsignRecord 关联的，避免重复）
    const CONTRACT_TYPE_LABEL: Record<string, string> = {
      FIXED: '固定期限劳动合同',
      UNFIXED: '无固定期限劳动合同',
      UNSIGNED: '未签合同',
      LABOR: '劳务协议',
      INTERNSHIP: '实习协议',
      DISPATCH: '劳务派遣合同',
      OUTSOURCING: '外包合同',
      PARTTIME: '非全日制合同',
    }
    const esignContractIds = new Set(pendingEsign.filter(r => r.contractId).map(r => r.contractId))
    for (const c of pendingContracts) {
      if (esignContractIds.has(c.id)) continue // 已有电子签署记录的不重复
      const emp = ensureEmployee(c.employee)
      emp.pendingItems.push({
        type: 'contract',
        recordId: null,
        contractId: c.id,
        title: CONTRACT_TYPE_LABEL[c.contractType] || `${c.contractType}合同`,
        scene: 'CONTRACT',
        signMethod: c.signMethod,
        status: 'PENDING',
        createdAt: c.createdAt,
      })
    }

    // 转为数组，按待签数量降序、姓名排序
    const result = Array.from(employeeMap.values()).sort((a, b) => {
      if (b.pendingItems.length !== a.pendingItems.length) return b.pendingItems.length - a.pendingItems.length
      return a.name.localeCompare(b.name)
    })

    res.json({ success: true, data: result })
  } catch (err) { next(err) }
})

/**
 * 登记线下合同签署日期
 * POST /esign/sign-date  body: { contractId, signDate }
 *
 * 适用于纸质合同（signMethod=PAPER）未登记签署日期的情况。
 * 电子签合同的签署日期由电签系统回写，不通过此接口修改。
 */
router.post('/sign-date', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { contractId, signDate } = req.body
    if (!contractId || !signDate) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 contractId 或 signDate' } })
    }
    const contract = await prisma.laborContract.findFirst({
      where: { id: contractId, orgId: req.user!.orgId },
      select: { id: true, signMethod: true, contractType: true, employeeId: true, employee: { select: { name: true } } },
    })
    if (!contract) {
      return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '合同不存在' } })
    }
    if (contract.signMethod === 'ELECTRONIC') {
      return res.status(400).json({ success: false, error: { code: 'VALIDATION_ERROR', message: '电子签合同的签署日期由电签系统自动回写，不可手动修改' } })
    }
    // 解析日期字符串（YYYY-MM-DD），手动构造本地中午时间避免时区偏移
    const dateStr = String(signDate).slice(0, 10)
    const [y, m, d] = dateStr.split('-').map(Number)
    const parsedDate = new Date(y, (m || 1) - 1, d || 1, 12, 0, 0, 0)
    if (isNaN(parsedDate.getTime())) {
      return res.status(400).json({ success: false, error: { code: 'VALIDATION_ERROR', message: '签署日期格式无效' } })
    }
    // 签署日期不能晚于当前日期
    const today = new Date()
    today.setHours(23, 59, 59, 999)
    if (parsedDate > today) {
      return res.status(400).json({ success: false, error: { code: 'VALIDATION_ERROR', message: '签署日期不能晚于当前日期' } })
    }
    // 更新合同签署日期
    await prisma.laborContract.update({
      where: { id: contractId },
      data: { signDate: parsedDate },
    })
    // 同时创建一条已完成的线下手签 EsignRecord，使签署记录 Tab 可见
    const existingRecord = await prisma.eSignRecord.findFirst({
      where: { contractId, status: 'COMPLETED' },
      select: { id: true },
    })
    if (!existingRecord) {
      // 合同类型枚举转中文
      const CONTRACT_TYPE_LABEL: Record<string, string> = {
        FIXED: '固定期限劳动合同',
        UNFIXED: '无固定期限劳动合同',
        UNSIGNED: '未签合同',
        LABOR: '劳务协议',
        INTERNSHIP: '实习协议',
        DISPATCH: '劳务派遣合同',
        OUTSOURCING: '外包合同',
        PARTTIME: '非全日制合同',
      }
      const contractLabel = CONTRACT_TYPE_LABEL[contract.contractType] || '合同'
      await prisma.eSignRecord.create({
        data: {
          orgId: req.user!.orgId,
          contractId,
          employeeId: contract.employeeId,
          scene: 'CONTRACT',
          signMethod: 'PAPER',
          documentTitle: `${contractLabel}线下签署登记`,
          status: 'COMPLETED',
          completedAt: parsedDate,  // 完成时间 = 实际签署日期
          signedAt: parsedDate,     // 签署时间 = HR 选择的签署日期
          signedLocation: null,
          initiatedBy: req.user!.id,
          createdBy: req.user!.id,
          remark: 'HR 登记线下签署日期',
        },
      })
    }
    await auditLog(req, 'SIGN_DATE', 'CONTRACT', contractId, { employeeName: contract.employee.name, signDate: parsedDate.toISOString() })
    res.json({ success: true, data: { message: '签署日期已登记', signDate: parsedDate.toISOString() } })
  } catch (err) { next(err) }
})

/**
 * 催办 — 生成员工一次性自动登录链接（指向员工端签署页）
 * POST /esign/remind  body: { employeeId }
 *
 * 返回自动登录 URL，HR 可复制或生成二维码发给员工
 */
router.post('/remind', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { employeeId } = req.body
    if (!employeeId) {
      return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 employeeId' } })
    }
    const employee = await prisma.employee.findFirst({
      where: { id: employeeId, orgId: req.user!.orgId, status: 'ACTIVE' },
      select: { id: true, name: true, phone: true, orgId: true, idCardNumber: true },
    })
    if (!employee) {
      return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '员工不存在或已离职' } })
    }
    // 生成一次性 token（24 小时有效，给员工充足时间签署）
    const token = jwt.sign(
      { id: employee.id, orgId: employee.orgId, role: 'EMPLOYEE_AUTO', name: employee.name },
      AUTO_LOGIN_SECRET,
      { expiresIn: '24h' },
    )
    const url = `${process.env.PORTAL_BASE_URL || ''}/portal/auto-login?token=${token}&redirect=/portal/esign`
    await auditLog(req, 'REMIND', 'ESIGN', employeeId, { employeeName: employee.name })
    res.json({ success: true, data: { url, token, employeeName: employee.name, employeeIdCardNumber: (() => { try { const v = employee.idCardNumber; return v ? (v.includes(':') ? decrypt(v) : v) : null } catch { return null } })(), phone: employee.phone } })
  } catch (err) { next(err) }
})

/**
 * 发起签署
 * - 校验组织电子签开关
 * - 自动从模板渲染文件内容
 * - 创建 ESignRecord
 * - 创建证据链（发起签署事件）
 */
router.post('/create', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const data = createSignSchema.parse(req.body)
    const scene = data.scene || 'CONTRACT'

    // 1. 校验组织电子签开关
    const orgFlag = SCENE_ORG_FLAG_MAP[scene]
    if (orgFlag) {
      const org = await prisma.organization.findUnique({
        where: { id: req.user!.orgId },
        select: { [orgFlag]: true, name: true } as any,
      })
      if (org && !(org as any)[orgFlag]) {
        return res.status(403).json({
          success: false,
          error: { code: 'ESIGN_DISABLED', message: `组织未开启${scene === 'POLICY' ? '规章制度' : scene === 'PAYSLIP' ? '工资条' : scene === 'ONBOARDING' ? '入职文件' : '该场景'}电子签功能，请在系统设置中开启` },
        })
      }
    }

    // 2. 获取员工信息
    const employee = await prisma.employee.findFirst({
      where: { id: data.employeeId, orgId: req.user!.orgId },
      select: { id: true, name: true, phone: true, department: true, idCardNumber: true, position: true, monthlySalary: true, hireDate: true },
    })
    if (!employee) {
      return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '员工不存在' } })
    }

    // 3. 自动渲染文件内容（优先使用指定模板，否则按 scene 匹配）
    let documentContent = data.documentContent || ''
    if (!documentContent) {
      const templateId = data.templateId || SCENE_TEMPLATE_MAP[scene]
      if (templateId) {
        const template = getTemplateById(templateId)
        if (template) {
          // 自动填充模板变量
          const org = await prisma.organization.findUnique({ where: { id: req.user!.orgId }, select: { name: true } })
          const vars: Record<string, string> = {
            companyName: org?.name || '',
            employeeName: employee.name || '',
            idCard: employee.idCardNumber || '',
            position: employee.position || '',
            monthlySalary: String(employee.monthlySalary || ''),
            ...data.templateVars,
          }
          documentContent = renderTemplate(templateId, vars) || ''
        }
      }
    }

    // 4. 创建签署记录
    const record = await prisma.eSignRecord.create({
      data: {
        orgId: req.user!.orgId,
        contractId: data.contractId || null,
        employeeId: data.employeeId,
        scene,
        documentTitle: data.documentTitle,
        documentContent: documentContent || null,
        status: 'PENDING',
        initiatedBy: req.user!.id,
        createdBy: req.user!.id,
        remark: data.remark || null,
        expiredAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
      },
    })

    // 5. 创建证据链 — 发起签署事件
    await createEvidence({
      orgId: req.user!.orgId,
      category: 'CONTRACT_SIGN',
      refId: record.id,
      employeeId: data.employeeId,
      events: [{
        action: `发起电子签署：${data.documentTitle}`,
        timestamp: new Date().toISOString(),
        ip: req.ip,
        userAgent: req.headers['user-agent'] as string,
        location: `场景：${scene}，发起人：${req.user!.id}`,
      }],
      createdBy: req.user!.id,
    }).catch(() => {})

    await auditLog(req, 'ESIGN_CREATE', 'ESIGN_RECORD', record.id, { employeeId: data.employeeId, scene, documentTitle: data.documentTitle })

    res.json({
      success: true,
      data: record,
      message: '签署记录已创建，员工可在员工端查看并签署',
    })
  } catch (err) { next(err) }
})

/**
 * 签署记录详情
 */
router.get('/:id', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const record = await prisma.eSignRecord.findFirst({
      where: { id: req.params.id, orgId: req.user!.orgId },
      include: {
        employee: { select: { id: true, name: true, department: true, phone: true, idCardNumber: true } },
      },
    })
    if (!record) return res.status(404).json({ success: false, error: { message: '记录不存在' } })
    const recordWithIdCard = {
      ...record,
      employee: record.employee ? { ...record.employee, idCardNumber: (() => { try { const v = record.employee.idCardNumber; return v ? (v.includes(':') ? decrypt(v) : v) : null } catch { return null } })() } : record.employee,
    }
    res.json({ success: true, data: recordWithIdCard })
  } catch (err) { next(err) }
})

/**
 * 查询签署状态
 */
router.get('/:id/status', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const record = await prisma.eSignRecord.findFirst({
      where: { id: req.params.id, orgId: req.user!.orgId },
    })
    if (!record) return res.status(404).json({ success: false, error: { message: '记录不存在' } })

    // 检查是否已过期但状态仍为 PENDING
    if (record.status === 'PENDING' && record.expiredAt && record.expiredAt < new Date()) {
      const updated = await prisma.eSignRecord.update({
        where: { id: record.id },
        data: { status: 'EXPIRED' },
      })
      return res.json({ success: true, data: updated })
    }

    res.json({ success: true, data: record })
  } catch (err) { next(err) }
})

/**
 * 获取签署记录的证据链
 */
router.get('/:id/evidence', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const evidence = await prisma.evidenceChain.findMany({
      where: { orgId: req.user!.orgId, refId: req.params.id },
      orderBy: { createdAt: 'asc' },
    })
    res.json({ success: true, data: evidence })
  } catch (err) { next(err) }
})

/**
 * 易签宝回调接口（无需认证）
 * 对接易签宝后启用：验证签名 + 更新状态 + 回写PDF + 追加证据链
 */
router.post('/callback', async (req, res: Response, next: NextFunction) => {
  try {
    const { flowId, status, signedPdfUrl, ...rest } = req.body

    // TODO: 对接易签宝后验证回调签名
    // if (!verifyEsignCallback(req.headers, req.body)) {
    //   return res.status(401).json({ success: false, error: { message: '无效回调' } })
    // }

    if (flowId) {
      const record = await prisma.eSignRecord.findFirst({ where: { flowId } })
      if (record) {
        await prisma.eSignRecord.update({
          where: { id: record.id },
          data: {
            status: status || 'COMPLETED',
            signedPdfUrl: signedPdfUrl || null,
            completedAt: status === 'COMPLETED' ? new Date() : null,
            callbackData: rest as any,
          },
        })

        // 签署完成 → 回写合同 + 追加证据链
        if (status === 'COMPLETED') {
          if (record.contractId) {
            await prisma.laborContract.update({
              where: { id: record.contractId },
              data: {
                signMethod: 'ELECTRONIC',
                electronicContractUrl: signedPdfUrl || null,
              },
            })
          }

          await appendEvidence(record.orgId, '', {
            action: '易签宝回调：签署完成',
            timestamp: new Date().toISOString(),
            location: `flowId: ${flowId}，PDF: ${signedPdfUrl || '无'}`,
          }).catch(() => {})
        }

        await auditLog({} as any, 'ESIGN_CALLBACK', 'ESIGN_RECORD', record.id, { flowId, status })
      }
    }

    res.json({ success: true })
  } catch (err) { next(err) }
})

/**
 * 取消签署
 * - 更新状态为 CANCELLED
 * - 追加证据链
 */
router.post('/:id/cancel', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const record = await prisma.eSignRecord.findFirst({
      where: { id: req.params.id, orgId: req.user!.orgId },
    })
    if (!record) return res.status(404).json({ success: false, error: { message: '记录不存在' } })
    if (record.status === 'COMPLETED') {
      return res.status(400).json({ success: false, error: { message: '已完成的签署不可取消' } })
    }

    const updated = await prisma.eSignRecord.update({
      where: { id: record.id },
      data: { status: 'CANCELLED' },
    })

    // 追加证据链
    const evidence = await prisma.evidenceChain.findFirst({
      where: { orgId: req.user!.orgId, refId: record.id },
    })
    if (evidence) {
      await appendEvidence(req.user!.orgId, evidence.id, {
        action: '取消签署',
        timestamp: new Date().toISOString(),
        ip: req.ip,
        userAgent: req.headers['user-agent'] as string,
        location: `操作人：${req.user!.id}`,
      }).catch(() => {})
    }

    await auditLog(req, 'ESIGN_CANCEL', 'ESIGN_RECORD', record.id, {})

    res.json({ success: true, data: updated })
  } catch (err) { next(err) }
})

// ========== 线下手签登记 ==========

/** 线下签署扫描件上传目录 */
const paperSignDir = path.join(process.cwd(), 'uploads', 'paper-sign')
if (!fs.existsSync(paperSignDir)) fs.mkdirSync(paperSignDir, { recursive: true })

const paperSignUpload = multer({
  storage: multer.diskStorage({
    destination: paperSignDir,
    filename: (_req, file, cb) => {
      const ext = path.extname(file.originalname)
      cb(null, `${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`)
    },
  }),
  limits: { fileSize: 10 * 1024 * 1024 },
  fileFilter: (_req, file, cb) => {
    const allowed = ['.jpg', '.jpeg', '.png', '.pdf', '.bmp', '.webp', '.tiff', '.tif']
    const ext = path.extname(file.originalname).toLowerCase()
    if (allowed.includes(ext)) cb(null, true)
    else cb(new Error('仅支持 JPG/PNG/PDF/BMP/WEBP/TIFF 格式'))
  },
})

/**
 * 上传线下签署扫描件
 * 支持多文件上传，返回文件URL列表
 */
router.post('/paper-upload', authMiddleware, paperSignUpload.array('files', 10), async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const files = req.files as Express.Multer.File[]
    if (!files || files.length === 0) {
      return res.status(400).json({ success: false, error: { code: 'NO_FILE', message: '请选择文件' } })
    }
    const fileUrls = files.map(f => ({
      name: f.originalname,
      url: `/uploads/paper-sign/${f.filename}`,
      size: f.size,
    }))
    res.json({ success: true, data: fileUrls })
  } catch (err) { next(err) }
})

/** 线下手签登记 Schema */
const paperSignSchema = z.object({
  employeeId: z.string().min(1),
  contractId: z.string().optional(),
  scene: z.string().default('CONTRACT'),
  documentTitle: z.string().min(1),
  signedAt: z.string().min(1), // 签署日期
  signedLocation: z.string().optional(), // 签署地点
  witnessName: z.string().optional(), // 见证人姓名
  witnessPhone: z.string().optional(), // 见证人手机号
  scanFileUrls: z.array(z.object({
    name: z.string(),
    url: z.string(),
  })).min(1, '至少上传一份签署扫描件'),
  remark: z.string().optional(),
})

/**
 * 线下手签登记
 * - 创建 ESignRecord（signMethod=PAPER, status=COMPLETED）
 * - 保存签署信息（签署日期/地点/见证人/扫描件）
 * - 创建证据链（线下签署登记事件）
 * - 回写合同签署方式
 */
router.post('/paper-sign', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const data = paperSignSchema.parse(req.body)

    // 获取员工信息
    const employee = await prisma.employee.findFirst({
      where: { id: data.employeeId, orgId: req.user!.orgId },
      select: { id: true, name: true, department: true },
    })
    if (!employee) {
      return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '员工不存在' } })
    }

    // 签署日期不能晚于当前日期
    const signDate = new Date(data.signedAt)
    const todayEnd = new Date()
    todayEnd.setHours(23, 59, 59, 999)
    if (signDate > todayEnd) {
      return res.status(400).json({ success: false, error: { code: 'VALIDATION_ERROR', message: '签署日期不能晚于当前日期' } })
    }

    // 创建签署记录（线下手签直接为 COMPLETED 状态）
    const record = await prisma.eSignRecord.create({
      data: {
        orgId: req.user!.orgId,
        contractId: data.contractId || null,
        employeeId: data.employeeId,
        scene: data.scene,
        signMethod: 'PAPER',
        documentTitle: data.documentTitle,
        status: 'COMPLETED',
        initiatedBy: req.user!.id,
        createdBy: req.user!.id,
        remark: data.remark || null,
        completedAt: new Date(data.signedAt),
        expiredAt: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // 线下签署记录保留1年
        // 线下手签专用字段
        signedAt: new Date(data.signedAt),
        signedLocation: data.signedLocation || null,
        witnessName: data.witnessName || null,
        witnessPhone: data.witnessPhone || null,
        scanFileUrls: data.scanFileUrls as any,
        // 签署证据
        callbackData: {
          signMethod: 'PAPER',
          signedAt: data.signedAt,
          signedLocation: data.signedLocation,
          witnessName: data.witnessName,
          witnessPhone: data.witnessPhone,
          scanFileCount: data.scanFileUrls.length,
          registeredBy: req.user!.id,
          registeredAt: new Date().toISOString(),
        } as any,
      },
    })

    // 创建证据链 — 线下签署登记
    await createEvidence({
      orgId: req.user!.orgId,
      category: 'CONTRACT_SIGN',
      refId: record.id,
      employeeId: data.employeeId,
      events: [{
        action: `线下手签登记：${data.documentTitle}`,
        timestamp: new Date().toISOString(),
        ip: req.ip,
        userAgent: req.headers['user-agent'] as string,
        location: `签署日期：${data.signedAt.slice(0, 10)}，签署地点：${data.signedLocation || '未填写'}，见证人：${data.witnessName || '无'}，扫描件：${data.scanFileUrls.length}份`,
      }],
      createdBy: req.user!.id,
    }).catch(() => {})

    // 回写合同签署方式
    if (data.contractId) {
      await prisma.laborContract.update({
        where: { id: data.contractId },
        data: {
          signMethod: 'PAPER',
          // 第一份扫描件作为合同附件
          attachmentUrl: data.scanFileUrls[0]?.url || null,
        },
      })
    }

    await auditLog(req, 'PAPER_SIGN_REGISTER', 'ESIGN_RECORD', record.id, {
      employeeId: data.employeeId,
      documentTitle: data.documentTitle,
      signedAt: data.signedAt,
      scanFileCount: data.scanFileUrls.length,
    })

    res.json({
      success: true,
      data: record,
      message: '线下手签登记成功，证据链已记录',
    })
  } catch (err) { next(err) }
})

export default router
