import prisma from '../lib/prisma'
import { sha256 } from '../lib/crypto'

/**
 * 证据链服务 — 管理操作证据链，用于劳动仲裁举证
 */

export type EvidenceCategory =
  | 'CONTRACT_SIGN'
  | 'ONBOARD'
  | 'PAYSLIP_CONFIRM'
  | 'DISCIPLINARY'
  | 'ATTENDANCE'
  | 'TERMINATION'

/**
 * 创建证据链记录
 */
export async function createEvidence(params: {
  orgId: string
  category: EvidenceCategory
  refId?: string
  employeeId?: string
  events: Array<{ action: string; timestamp: string; ip?: string; userAgent?: string; smsCode?: string; location?: string }>
  createdBy: string
}) {
  const eventsJson = JSON.stringify(params.events)
  const hash = sha256(eventsJson + params.orgId + params.category + (params.refId || ''))

  return prisma.evidenceChain.create({
    data: {
      orgId: params.orgId,
      category: params.category,
      refId: params.refId || null,
      employeeId: params.employeeId || null,
      events: params.events,
      hash,
      createdBy: params.createdBy,
    },
  })
}

/**
 * 追加证据事件到已有证据链
 */
export async function appendEvidence(orgId: string, evidenceId: string, event: { action: string; timestamp: string; ip?: string; userAgent?: string; smsCode?: string; location?: string }) {
  const existing = await prisma.evidenceChain.findFirst({ where: { id: evidenceId, orgId } })
  if (!existing) {
    throw { code: 'NOT_FOUND', message: '证据链不存在' }
  }

  const events = [...(existing.events as any[]), event]
  const eventsJson = JSON.stringify(events)
  const hash = sha256(eventsJson + orgId + existing.category + (existing.refId || ''))

  return prisma.evidenceChain.update({
    where: { id: evidenceId },
    data: { events, hash },
  })
}

/**
 * 获取某操作的完整证据链
 */
export async function getEvidenceByRef(orgId: string, category: string, refId: string) {
  return prisma.evidenceChain.findMany({
    where: { orgId, category, refId },
    orderBy: { createdAt: 'asc' },
  })
}

/**
 * 获取某员工所有证据链
 */
export async function getEvidenceByEmployee(orgId: string, employeeId: string) {
  return prisma.evidenceChain.findMany({
    where: { orgId, employeeId },
    orderBy: { createdAt: 'desc' },
  })
}

/**
 * 获取证据链详情
 */
export async function getEvidenceDetail(orgId: string, id: string) {
  const evidence = await prisma.evidenceChain.findFirst({ where: { id, orgId } })
  if (!evidence) {
    throw { code: 'NOT_FOUND', message: '证据链不存在' }
  }
  return evidence
}

/**
 * 验证证据链完整性（重新计算哈希对比）
 * 注意：PostgreSQL 的 json 类型会按 key 字母序重排属性，导致 JSON.stringify 结果与原始不一致。
 * 因此验证时需要尝试两种方式：原始序列化和排序后序列化。
 */
export async function verifyEvidence(orgId: string, id: string): Promise<{ valid: boolean; expectedHash: string; actualHash: string }> {
  const evidence = await prisma.evidenceChain.findFirst({ where: { id, orgId } })
  if (!evidence) {
    throw { code: 'NOT_FOUND', message: '证据链不存在' }
  }

  const events = evidence.events as any[]
  const eventsJson = JSON.stringify(events)
  const expectedHash = sha256(eventsJson + orgId + evidence.category + (evidence.refId || ''))

  // 如果标准序列化不匹配，尝试按 key 排序后序列化（兼容 PostgreSQL json 类型重排）
  if (expectedHash !== evidence.hash) {
    const sortedEvents = events.map(e => {
      const sorted: any = {}
      Object.keys(e).sort().forEach(k => sorted[k] = e[k])
      return sorted
    })
    const sortedJson = JSON.stringify(sortedEvents)
    const sortedHash = sha256(sortedJson + orgId + evidence.category + (evidence.refId || ''))
    return {
      valid: sortedHash === evidence.hash,
      expectedHash: sortedHash,
      actualHash: evidence.hash,
    }
  }

  return {
    valid: true,
    expectedHash,
    actualHash: evidence.hash,
  }
}

/**
 * 获取组织级证据链列表（支持按类别筛选）
 */
export async function getEvidenceList(orgId: string, category?: string, page: number = 1, pageSize: number = 20) {
  const where: any = { orgId }
  if (category && category !== 'ALL') {
    where.category = category
  }

  const [total, records] = await Promise.all([
    prisma.evidenceChain.count({ where }),
    prisma.evidenceChain.findMany({
      where,
      include: { employee: { select: { id: true, name: true, department: true } } },
      orderBy: { createdAt: 'desc' },
      skip: (page - 1) * pageSize,
      take: pageSize,
    }),
  ])

  return {
    total,
    page,
    pageSize,
    records: records.map((r: any) => {
      const events = Array.isArray(r.events) ? r.events : []
      const firstEvent = events.length > 0 ? events[0] : null
      const lastEvent = events.length > 0 ? events[events.length - 1] : null
      return {
        id: r.id,
        category: r.category,
        refId: r.refId,
        employeeId: r.employeeId,
        employeeName: r.employee?.name || null,
        employeeDept: r.employee?.department || null,
        eventCount: events.length,
        firstAction: firstEvent?.action || null,
        lastAction: lastEvent?.action || null,
        firstTimestamp: firstEvent?.timestamp || null,
        lastTimestamp: lastEvent?.timestamp || null,
        hash: r.hash,
        hashShort: r.hash ? r.hash.substring(0, 16) : null,
        createdAt: r.createdAt.toISOString(),
      }
    }),
  }
}

/**
 * 验证全部证据链完整性
 */
export async function verifyAllEvidence(orgId: string) {
  const records = await prisma.evidenceChain.findMany({ where: { orgId } })
  let valid = 0
  let invalid = 0
  for (const r of records) {
    const events = r.events as any[]
    const eventsJson = JSON.stringify(events)
    const expectedHash = sha256(eventsJson + orgId + r.category + (r.refId || ''))
    if (expectedHash === r.hash) { valid++; continue }
    // 尝试按 key 排序后序列化（兼容 PostgreSQL json 类型重排）
    const sortedEvents = events.map(e => {
      const sorted: any = {}
      Object.keys(e).sort().forEach(k => sorted[k] = e[k])
      return sorted
    })
    const sortedJson = JSON.stringify(sortedEvents)
    const sortedHash = sha256(sortedJson + orgId + r.category + (r.refId || ''))
    if (sortedHash === r.hash) valid++
    else invalid++
  }
  return { total: records.length, valid, invalid }
}
