import { Router, Response, NextFunction } from 'express'
import prisma from '../lib/prisma'
import { decrypt } from '../lib/crypto'
import { authMiddleware, AuthRequest } from '../middleware/auth'
import { z } from 'zod'
import { isInProbation } from '../services/contract.service'

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

function safeDecryptStr(encrypted: string | null): string | null {
  if (!encrypted) return null
  try {
    if (!encrypted.includes(':')) return encrypted
    return decrypt(encrypted)
  } catch { return null }
}

// ========== 加班费记录 ==========

const overtimeSchema = z.object({
  employeeId: z.string().min(1),
  month: z.string().regex(/^\d{4}-\d{2}$/),
  monthlyWage: z.number().positive(),
  weekdayHours: z.number().min(0).default(0),
  weekendHours: z.number().min(0).default(0),
  holidayHours: z.number().min(0).default(0),
})

// 获取加班费记录列表
router.get('/overtime', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { employeeId, month } = req.query
    const records = await prisma.overtimeRecord.findMany({
      where: {
        orgId: req.user!.orgId,
        ...(employeeId ? { employeeId: String(employeeId) } : {}),
        ...(month ? { month: String(month) } : {}),
      },
      include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } } },
      orderBy: { createdAt: 'desc' },
    })
    const data = records.map((r: any) => ({
      ...r,
      employee: r.employee ? { ...r.employee, idCardNumber: safeDecryptStr(r.employee.idCardNumber) } : r.employee,
    }))
    res.json({ success: true, data })
  } catch (err) {
    next(err)
  }
})

// 保存加班费记录
router.post('/overtime', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const data = overtimeSchema.parse(req.body)
    const otConfig = await prisma.overtimeConfig.findUnique({ where: { orgId: req.user!.orgId } }) ?? { weekdayRate: 1.5, weekendRate: 2.0, holidayRate: 3.0, monthlyDays: 21.75, dailyHours: 8 }
    const hourlyWage = data.monthlyWage / otConfig.monthlyDays / otConfig.dailyHours
    const weekdayPay = hourlyWage * otConfig.weekdayRate * data.weekdayHours
    const weekendPay = hourlyWage * otConfig.weekendRate * data.weekendHours
    const holidayPay = hourlyWage * otConfig.holidayRate * data.holidayHours
    const totalPay = weekdayPay + weekendPay + holidayPay

    const record = await prisma.overtimeRecord.upsert({
      where: {
        employeeId_month: { employeeId: data.employeeId, month: data.month },
      },
      update: {
        weekdayHours: data.weekdayHours,
        weekendHours: data.weekendHours,
        holidayHours: data.holidayHours,
        weekdayPay,
        weekendPay,
        holidayPay,
        totalPay,
      },
      create: {
        orgId: req.user!.orgId,
        employeeId: data.employeeId,
        month: data.month,
        weekdayHours: data.weekdayHours,
        weekendHours: data.weekendHours,
        holidayHours: data.holidayHours,
        weekdayPay,
        weekendPay,
        holidayPay,
        totalPay,
      },
    })
    res.json({ success: true, data: record })
  } catch (err) {
    next(err)
  }
})

// 更新加班记录（按ID）
const overtimeUpdateSchema = z.object({
  weekdayHours: z.number().min(0).optional(),
  weekendHours: z.number().min(0).optional(),
  holidayHours: z.number().min(0).optional(),
  monthlyWage: z.number().positive().optional(),
})

router.put('/overtime/:id', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { id } = req.params
    const data = overtimeUpdateSchema.parse(req.body)

    const existing = await prisma.overtimeRecord.findUnique({ where: { id } })
    if (!existing) {
      res.status(404).json({ success: false, message: '记录不存在' })
      return
    }

    const monthlyWage = data.monthlyWage ?? 0
    const weekdayHours = data.weekdayHours ?? existing.weekdayHours
    const weekendHours = data.weekendHours ?? existing.weekendHours
    const holidayHours = data.holidayHours ?? existing.holidayHours

    const otConfig = await prisma.overtimeConfig.findUnique({ where: { orgId: req.user!.orgId } }) ?? { weekdayRate: 1.5, weekendRate: 2.0, holidayRate: 3.0, monthlyDays: 21.75, dailyHours: 8 }
    const hourlyWage = monthlyWage / otConfig.monthlyDays / otConfig.dailyHours
    const weekdayPay = hourlyWage * otConfig.weekdayRate * weekdayHours
    const weekendPay = hourlyWage * otConfig.weekendRate * weekendHours
    const holidayPay = hourlyWage * otConfig.holidayRate * holidayHours
    const totalPay = weekdayPay + weekendPay + holidayPay

    const record = await prisma.overtimeRecord.update({
      where: { id },
      data: {
        weekdayHours,
        weekendHours,
        holidayHours,
        weekdayPay,
        weekendPay,
        holidayPay,
        totalPay,
      },
    })
    res.json({ success: true, data: record })
  } catch (err) {
    next(err)
  }
})

// 从考勤记录同步加班工时
router.post('/overtime/sync-from-attendance', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const orgId = req.user!.orgId
    const { month } = req.body as { month: string }
    if (!month || !/^\d{4}-\d{2}$/.test(month)) {
      return res.status(400).json({ success: false, message: '请提供有效的月份（YYYY-MM）' })
    }

    const monthStart = new Date(month + '-01')
    const monthEnd = new Date(monthStart)
    monthEnd.setMonth(monthEnd.getMonth() + 1)

    // 获取该月所有考勤记录（含加班工时）
    const records = await prisma.attendanceRecord.findMany({
      where: { orgId, date: { gte: monthStart, lt: monthEnd }, overtimeHours: { gt: 0 } },
    })

    if (records.length === 0) {
      return res.json({ success: false, message: '该月考勤记录中无加班工时' })
    }

    // 按员工汇总加班工时，按日期类型分类
    // 日期类型判断优先级：HolidayConfig > 周末判断
    // HolidayConfig 中 HOLIDAY=法定节假日(3倍), WORKDAY=调休工作日(1.5倍)
    const holidays = await prisma.holidayConfig.findMany({
      where: { orgId, date: { gte: monthStart, lt: monthEnd } },
    })
    const holidayMap = new Map<string, string>() // dateStr -> type
    for (const h of holidays) {
      holidayMap.set(h.date.toISOString().slice(0, 10), h.type)
    }

    const empMap = new Map<string, { weekday: number; weekend: number; holiday: number }>()
    for (const r of records) {
      const dateStr = r.date.toISOString().slice(0, 10)
      const day = new Date(dateStr + 'T00:00:00')
      const dayOfWeek = day.getDay() // 0=周日, 6=周六
      let type: 'weekday' | 'weekend' | 'holiday' = 'weekday'

      const holidayType = holidayMap.get(dateStr)
      if (holidayType === 'HOLIDAY') {
        // 法定节假日
        type = 'holiday'
      } else if (holidayType === 'WORKDAY') {
        // 调休工作日（周末调休上班），按工作日算
        type = 'weekday'
      } else if (dayOfWeek === 0 || dayOfWeek === 6) {
        // 普通周末
        type = 'weekend'
      }

      if (!empMap.has(r.employeeId)) {
        empMap.set(r.employeeId, { weekday: 0, weekend: 0, holiday: 0 })
      }
      const entry = empMap.get(r.employeeId)!
      entry[type] += r.overtimeHours || 0
    }

    // 获取员工月工资用于计算加班费
    let config = await prisma.overtimeConfig.findUnique({ where: { orgId } })
    if (!config) config = await prisma.overtimeConfig.create({ data: { orgId } })

    let synced = 0
    for (const [employeeId, hours] of empMap) {
      const emp = await prisma.employee.findFirst({ where: { id: employeeId }, select: { monthlySalary: true } })
      let monthlyWage = 0
      try { monthlyWage = emp?.monthlySalary ? Number(decrypt(emp.monthlySalary)) : 0 } catch { monthlyWage = Number(emp?.monthlySalary) || 0 }

      const hourlyWage = monthlyWage / config.monthlyDays / config.dailyHours
      const weekdayPay = hourlyWage * config.weekdayRate * hours.weekday
      const weekendPay = hourlyWage * config.weekendRate * hours.weekend
      const holidayPay = hourlyWage * config.holidayRate * hours.holiday
      const totalPay = weekdayPay + weekendPay + holidayPay

      await prisma.overtimeRecord.upsert({
        where: { employeeId_month: { employeeId, month } },
        update: {
          weekdayHours: hours.weekday,
          weekendHours: hours.weekend,
          holidayHours: hours.holiday,
          weekdayPay, weekendPay, holidayPay, totalPay,
        },
        create: {
          orgId, employeeId, month,
          weekdayHours: hours.weekday,
          weekendHours: hours.weekend,
          holidayHours: hours.holiday,
          weekdayPay, weekendPay, holidayPay, totalPay,
        },
      })
      synced++
    }

    res.json({ success: true, data: { synced, totalEmployees: empMap.size } })
  } catch (err) {
    next(err)
  }
})

// ========== 工资条管理 ==========

const payslipSchema = z.object({
  employeeId: z.string().min(1),
  month: z.string().regex(/^\d{4}-\d{2}$/),
  baseSalary: z.number().min(0).default(0),
  overtimePay: z.number().min(0).default(0),
  weekdayOvertimePay: z.number().min(0).default(0),
  weekendOvertimePay: z.number().min(0).default(0),
  holidayOvertimePay: z.number().min(0).default(0),
  allowance: z.number().min(0).default(0),
  deduction: z.number().min(0).default(0),
})

// 获取工资条列表
router.get('/payslip', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { month, employeeId } = req.query
    const payslips = await prisma.payslip.findMany({
      where: {
        orgId: req.user!.orgId,
        ...(month ? { month: String(month) } : {}),
        ...(employeeId ? { employeeId: String(employeeId) } : {}),
      },
      include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } } },
      orderBy: [{ month: 'desc' }, { employee: { name: 'asc' } }],
    })
    const data = payslips.map((p: any) => ({
      ...p,
      employee: p.employee ? { ...p.employee, idCardNumber: safeDecryptStr(p.employee.idCardNumber) } : p.employee,
    }))
    res.json({ success: true, data })
  } catch (err) {
    next(err)
  }
})

// 创建/更新工资条
router.post('/payslip', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const data = payslipSchema.parse(req.body)
    const totalPay = data.baseSalary + data.overtimePay + data.allowance - data.deduction

    const payslip = await prisma.payslip.upsert({
      where: {
        employeeId_month: { employeeId: data.employeeId, month: data.month },
      },
      update: {
        baseSalary: data.baseSalary,
        overtimePay: data.overtimePay,
        weekdayOvertimePay: data.weekdayOvertimePay,
        weekendOvertimePay: data.weekendOvertimePay,
        holidayOvertimePay: data.holidayOvertimePay,
        allowance: data.allowance,
        deduction: data.deduction,
        totalPay,
      },
      create: {
        orgId: req.user!.orgId,
        employeeId: data.employeeId,
        month: data.month,
        baseSalary: data.baseSalary,
        overtimePay: data.overtimePay,
        weekdayOvertimePay: data.weekdayOvertimePay,
        weekendOvertimePay: data.weekendOvertimePay,
        holidayOvertimePay: data.holidayOvertimePay,
        allowance: data.allowance,
        deduction: data.deduction,
        totalPay,
      },
    })
    res.json({ success: true, data: payslip })
  } catch (err) {
    next(err)
  }
})

// 从加班费记录自动生成工资条
router.post('/payslip/generate', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { month, employeeId, baseSalary, allowance, deduction } = req.body as {
      month: string
      employeeId: string
      baseSalary: number
      allowance?: number
      deduction?: number
    }

    const overtime = await prisma.overtimeRecord.findUnique({
      where: { employeeId_month: { employeeId, month } },
    })

    const overtimePay = overtime?.totalPay || 0
    const totalPay = baseSalary + overtimePay + (allowance || 0) - (deduction || 0)

    const payslip = await prisma.payslip.upsert({
      where: { employeeId_month: { employeeId, month } },
      update: {
        baseSalary,
        overtimePay,
        weekdayOvertimePay: overtime?.weekdayPay || 0,
        weekendOvertimePay: overtime?.weekendPay || 0,
        holidayOvertimePay: overtime?.holidayPay || 0,
        allowance: allowance || 0,
        deduction: deduction || 0,
        totalPay,
      },
      create: {
        orgId: req.user!.orgId,
        employeeId,
        month,
        baseSalary,
        overtimePay,
        weekdayOvertimePay: overtime?.weekdayPay || 0,
        weekendOvertimePay: overtime?.weekendPay || 0,
        holidayOvertimePay: overtime?.holidayPay || 0,
        allowance: allowance || 0,
        deduction: deduction || 0,
        totalPay,
      },
    })
    res.json({ success: true, data: payslip })
  } catch (err) {
    next(err)
  }
})

// 删除工资条
router.delete('/payslip/:id', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    await prisma.payslip.delete({
      where: { id: req.params.id, orgId: req.user!.orgId },
    })
    res.json({ success: true })
  } catch (err) {
    next(err)
  }
})

// ========== 批量生成工资条 ==========

const batchGenerateSchema = z.object({
  month: z.string().regex(/^\d{4}-\d{2}$/),
  allowances: z.record(z.string(), z.number().default(0)).optional(),
  deductions: z.record(z.string(), z.number().default(0)).optional(),
})

// 批量生成全员工资条
router.post('/payslip/batch-generate', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { month, allowances = {}, deductions = {} } = batchGenerateSchema.parse(req.body)

    const employees = await prisma.employee.findMany({
      where: { orgId: req.user!.orgId, status: 'ACTIVE' },
      include: {
        contracts: { orderBy: { createdAt: 'desc' }, take: 1 },
      },
    })

    const results: any[] = []
    for (const emp of employees) {
      const overtime = await prisma.overtimeRecord.findUnique({
        where: { employeeId_month: { employeeId: emp.id, month } },
      })

      const overtimePay = overtime?.totalPay || 0
      const allowance = allowances[emp.id] || 0
      const deduction = deductions[emp.id] || 0

      let baseSalary = 0
      // 按月份判定是否仍在试用期
      const monthEnd = new Date(`${month}-28T23:59:59`)
      const latestContract = emp.contracts[0]
      if (isInProbation(latestContract, monthEnd) && latestContract?.probationSalary > 0) {
        baseSalary = latestContract.probationSalary
      } else if (emp.monthlySalary) {
        try {
          baseSalary = Number(decrypt(emp.monthlySalary)) || 0
        } catch {
          baseSalary = Number(emp.monthlySalary) || 0
        }
      }

      const totalPay = baseSalary + overtimePay + allowance - deduction

      const payslip = await prisma.payslip.upsert({
        where: { employeeId_month: { employeeId: emp.id, month } },
        update: { baseSalary, overtimePay, allowance, deduction, totalPay },
        create: {
          orgId: req.user!.orgId,
          employeeId: emp.id,
          month,
          baseSalary,
          overtimePay,
          weekdayOvertimePay: overtime?.weekdayPay || 0,
          weekendOvertimePay: overtime?.weekendPay || 0,
          holidayOvertimePay: overtime?.holidayPay || 0,
          allowance,
          deduction,
          totalPay,
        },
      })
      results.push(payslip)
    }

    res.json({ success: true, data: { generated: results.length, payslips: results } })
  } catch (err) {
    next(err)
  }
})

// ========== 加班费计算规则配置 ==========

const overtimeConfigSchema = z.object({
  weekdayRate: z.number().min(1).default(1.5),
  weekendRate: z.number().min(1).default(2.0),
  holidayRate: z.number().min(1).default(3.0),
  monthlyDays: z.number().min(1).default(21.75),
  dailyHours: z.number().min(1).default(8),
})

// 获取加班费计算规则
router.get('/overtime/config', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    let config = await prisma.overtimeConfig.findUnique({ where: { orgId: req.user!.orgId } })
    if (!config) {
      config = await prisma.overtimeConfig.create({ data: { orgId: req.user!.orgId } })
    }
    res.json({ success: true, data: config })
  } catch (err) {
    next(err)
  }
})

// 保存加班费计算规则
router.post('/overtime/config', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const data = overtimeConfigSchema.parse(req.body)
    const config = await prisma.overtimeConfig.upsert({
      where: { orgId: req.user!.orgId },
      update: data,
      create: { orgId: req.user!.orgId, ...data },
    })
    res.json({ success: true, data: config })
  } catch (err) {
    next(err)
  }
})

// ========== 节假日配置 ==========

// 获取节假日列表（支持按年份筛选）
router.get('/holidays', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const orgId = req.user!.orgId
    const year = req.query.year as string | undefined
    const where: any = { orgId }
    if (year) {
      const start = new Date(`${year}-01-01`)
      const end = new Date(`${year}-12-31`)
      end.setDate(end.getDate() + 1)
      where.date = { gte: start, lt: end }
    }
    const holidays = await prisma.holidayConfig.findMany({
      where,
      orderBy: { date: 'asc' },
    })
    res.json({ success: true, data: holidays })
  } catch (err) {
    next(err)
  }
})

// 批量保存节假日（覆盖该年配置）
router.post('/holidays/batch', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const orgId = req.user!.orgId
    const { year, items } = req.body as { year: string; items: { date: string; type: string; name?: string }[] }
    if (!year || !/^\d{4}$/.test(year)) {
      return res.status(400).json({ success: false, message: '请提供有效的年份' })
    }

    // 删除该年旧数据
    const yearStart = new Date(`${year}-01-01`)
    const yearEnd = new Date(`${year}-12-31`)
    yearEnd.setDate(yearEnd.getDate() + 1)
    await prisma.holidayConfig.deleteMany({
      where: { orgId, date: { gte: yearStart, lt: yearEnd } },
    })

    // 批量插入新数据
    if (items && items.length > 0) {
      await prisma.holidayConfig.createMany({
        data: items.map(item => ({
          orgId,
          date: new Date(item.date),
          type: item.type,
          name: item.name || null,
        })),
      })
    }

    res.json({ success: true, data: { count: items?.length || 0 } })
  } catch (err) {
    next(err)
  }
})

// 预置法定节假日（按年份自动填充国务院发布的节假日）
router.post('/holidays/preset', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const orgId = req.user!.orgId
    const { year } = req.body as { year: string }
    if (!year || !/^\d{4}$/.test(year)) {
      return res.status(400).json({ success: false, message: '请提供有效的年份' })
    }

    // 2026年法定节假日配置（国务院发布）
    const presetData: Record<string, { holidays: { date: string; name: string }[]; workdays: { date: string; name: string }[] }> = {
      '2026': {
        holidays: [
          // 元旦
          { date: '2026-01-01', name: '元旦' },
          // 春节
          { date: '2026-02-15', name: '春节' },
          { date: '2026-02-16', name: '春节' },
          { date: '2026-02-17', name: '春节' },
          { date: '2026-02-18', name: '春节' },
          { date: '2026-02-19', name: '春节' },
          { date: '2026-02-20', name: '春节' },
          { date: '2026-02-21', name: '春节' },
          // 清明节
          { date: '2026-04-04', name: '清明节' },
          { date: '2026-04-05', name: '清明节' },
          { date: '2026-04-06', name: '清明节' },
          // 劳动节
          { date: '2026-05-01', name: '劳动节' },
          { date: '2026-05-02', name: '劳动节' },
          { date: '2026-05-03', name: '劳动节' },
          { date: '2026-05-04', name: '劳动节' },
          { date: '2026-05-05', name: '劳动节' },
          // 端午节
          { date: '2026-06-19', name: '端午节' },
          { date: '2026-06-20', name: '端午节' },
          { date: '2026-06-21', name: '端午节' },
          // 中秋节
          { date: '2026-09-25', name: '中秋节' },
          { date: '2026-09-26', name: '中秋节' },
          { date: '2026-09-27', name: '中秋节' },
          // 国庆节
          { date: '2026-10-01', name: '国庆节' },
          { date: '2026-10-02', name: '国庆节' },
          { date: '2026-10-03', name: '国庆节' },
          { date: '2026-10-04', name: '国庆节' },
          { date: '2026-10-05', name: '国庆节' },
          { date: '2026-10-06', name: '国庆节' },
          { date: '2026-10-07', name: '国庆节' },
        ],
        workdays: [
          // 春节调休
          { date: '2026-02-14', name: '春节调休' },
          { date: '2026-02-22', name: '春节调休' },
          // 劳动节调休
          { date: '2026-04-26', name: '劳动节调休' },
          // 国庆节调休
          { date: '2026-09-27', name: '国庆节调休' }, // 注意：9-27也是中秋，需确认
          { date: '2026-10-10', name: '国庆节调休' },
        ],
      },
    }

    const preset = presetData[year]
    if (!preset) {
      return res.status(400).json({ success: false, message: `暂无 ${year} 年预置节假日数据，请手动配置` })
    }

    // 删除该年旧数据
    const yearStart = new Date(`${year}-01-01`)
    const yearEnd = new Date(`${year}-12-31`)
    yearEnd.setDate(yearEnd.getDate() + 1)
    await prisma.holidayConfig.deleteMany({
      where: { orgId, date: { gte: yearStart, lt: yearEnd } },
    })

    // 插入法定节假日
    const holidayData = preset.holidays.map(h => ({
      orgId, date: new Date(h.date), type: 'HOLIDAY', name: h.name,
    }))
    // 插入调休工作日
    const workdayData = preset.workdays.map(w => ({
      orgId, date: new Date(w.date), type: 'WORKDAY', name: w.name,
    }))
    // 去重（同一日期可能既是中秋又是调休）
    const allData = [...holidayData, ...workdayData]
    const seen = new Set<string>()
    const deduped = allData.filter(d => {
      const key = d.date.toISOString().slice(0, 10)
      if (seen.has(key)) return false
      seen.add(key)
      return true
    })

    await prisma.holidayConfig.createMany({ data: deduped })

    res.json({ success: true, data: { holidays: preset.holidays.length, workdays: deduped.length - preset.holidays.length } })
  } catch (err) {
    next(err)
  }
})

// ========== 批量导入加班工时 ==========

const batchOvertimeSchema = z.array(
  z.object({
    employeeId: z.string().min(1),
    month: z.string().regex(/^\d{4}-\d{2}$/),
    weekdayHours: z.number().min(0).default(0),
    weekendHours: z.number().min(0).default(0),
    holidayHours: z.number().min(0).default(0),
  }),
)

router.post('/overtime/batch', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const items = batchOvertimeSchema.parse(req.body)
    const results: any[] = []

    for (const data of items) {
      const record = await prisma.overtimeRecord.upsert({
        where: { employeeId_month: { employeeId: data.employeeId, month: data.month } },
        update: {
          weekdayHours: data.weekdayHours,
          weekendHours: data.weekendHours,
          holidayHours: data.holidayHours,
          weekdayPay: 0, weekendPay: 0, holidayPay: 0, totalPay: 0,
        },
        create: {
          orgId: req.user!.orgId,
          employeeId: data.employeeId,
          month: data.month,
          weekdayHours: data.weekdayHours,
          weekendHours: data.weekendHours,
          holidayHours: data.holidayHours,
        },
      })
      results.push(record)
    }

    res.json({ success: true, data: { imported: results.length } })
  } catch (err) {
    next(err)
  }
})

// ========== 批次导入加班费 ==========

router.post('/overtime/import-to-batch/:batchId', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { batchId } = req.params
    const orgId = req.user!.orgId
    const force = (req.body as any)?.force === true

    const batch = await prisma.payrollBatch.findFirst({ where: { id: batchId, orgId } })
    if (!batch) return res.status(404).json({ success: false, message: '批次不存在' })
    if (batch.status === 'ARCHIVED') return res.status(400).json({ success: false, message: '已归档批次不可操作' })

    // 获取加班费计算规则
    let config = await prisma.overtimeConfig.findUnique({ where: { orgId } })
    if (!config) config = await prisma.overtimeConfig.create({ data: { orgId } })

    // 获取该月未关联批次的加班记录
    const overtimeRecords = await prisma.overtimeRecord.findMany({
      where: { orgId, month: batch.month, batchId: null },
      include: { employee: { select: { id: true, name: true, monthlySalary: true } } },
    })

    if (overtimeRecords.length === 0) {
      return res.json({ success: false, message: '没有可获取的加班记录（所有记录已关联批次或无数据）' })
    }

    // 检查跨批次重复（非 force 模式）
    const toFillEmployeeIds = new Set(overtimeRecords.map(ot => ot.employeeId))
    if (!force && toFillEmployeeIds.size > 0) {
      const otherEntries = await prisma.batchEntry.findMany({
        where: { orgId, batch: { month: batch.month, id: { not: batchId } }, overtimePay: { gt: 0 } },
        select: { employeeId: true },
      })
      const dupIds = new Set(otherEntries.map(e => e.employeeId))
      const overlap = [...toFillEmployeeIds].filter(id => dupIds.has(id))
      if (overlap.length > 0) {
        const overlapNames = await prisma.employee.findMany({ where: { id: { in: overlap } }, select: { name: true } })
        return res.json({
          success: true,
          data: {
            needConfirm: true,
            duplicateCount: overlap.length,
            duplicateNames: overlapNames.map(e => e.name),
            message: `${overlap.length} 人在其他批次中已有加班费（${overlapNames.map(e => e.name).join('、')}），确认是否再次获取？`,
          },
        })
      }
    }

    const { calcBatchEntry } = await import('../services/payroll.service')
    const results: any[] = []
    for (const ot of overtimeRecords) {
      // 获取员工月工资
      let monthlyWage = 0
      try {
        monthlyWage = ot.employee.monthlySalary ? Number(decrypt(ot.employee.monthlySalary)) : 0
      } catch {
        monthlyWage = Number(ot.employee.monthlySalary) || 0
      }
      if (!monthlyWage) continue

      // 根据规则计算加班费
      const hourlyWage = monthlyWage / config.monthlyDays / config.dailyHours
      const weekdayPay = hourlyWage * config.weekdayRate * ot.weekdayHours
      const weekendPay = hourlyWage * config.weekendRate * ot.weekendHours
      const holidayPay = hourlyWage * config.holidayRate * ot.holidayHours
      const totalPay = weekdayPay + weekendPay + holidayPay

      // 更新加班记录：计算金额并锁定到批次
      await prisma.overtimeRecord.update({
        where: { id: ot.id },
        data: { weekdayPay, weekendPay, holidayPay, totalPay, batchId },
      })

      // 更新批次条目的加班费并重算
      const entry = await prisma.batchEntry.findUnique({
        where: { batchId_employeeId: { batchId, employeeId: ot.employeeId } },
      })
      if (entry) {
        const inputs = {
          baseSalary: entry.baseSalary,
          performanceSalary: entry.performanceSalary || undefined,
          overtimePay: totalPay,
          allowance: entry.allowance,
          deduction: entry.deduction,
          bonus: entry.bonus,
          positionSalary: entry.positionSalary || undefined,
          senioritySalary: entry.senioritySalary || undefined,
          transportAllowance: entry.transportAllowance || undefined,
          mealAllowance: entry.mealAllowance || undefined,
          housingAllowance: entry.housingAllowance || undefined,
          communicationAllowance: entry.communicationAllowance || undefined,
          otherDeduction: entry.otherDeduction || undefined,
        }
        const calcResult = await calcBatchEntry(orgId, ot.employeeId, batch.month, inputs, batch.type, undefined, (entry.extraItems as Record<string, number>) || null)
        const { systemSocialEmp, systemSocialOrg, systemHousingEmp, systemHousingOrg, systemSupplementaryHousingEmp, systemSupplementaryHousingOrg, taxBreakdown, extraItems: _ei, ...entryData } = calcResult
        await prisma.batchEntry.update({
          where: { id: entry.id },
          data: { ...entryData, extraItems: calcResult.extraItems && Object.keys(calcResult.extraItems).length > 0 ? calcResult.extraItems : undefined },
        })
      }

      results.push({ employeeId: ot.employeeId, employeeName: ot.employee.name, totalPay })
    }

    // 重算批次汇总
    const allEntries = await prisma.batchEntry.findMany({ where: { batchId } })
    const totals = allEntries.reduce((acc, e) => ({
      totalPay: acc.totalPay + e.totalPay,
      totalNetPay: acc.totalNetPay + e.netPay,
      totalSocialOrg: acc.totalSocialOrg + e.socialOrg,
      totalSocialEmp: acc.totalSocialEmp + e.socialEmp,
      totalHousingOrg: acc.totalHousingOrg + e.housingOrg,
      totalHousingEmp: acc.totalHousingEmp + e.housingEmp,
      totalTax: acc.totalTax + e.tax,
    }), { totalPay: 0, totalNetPay: 0, totalSocialOrg: 0, totalSocialEmp: 0, totalHousingOrg: 0, totalHousingEmp: 0, totalTax: 0 })
    await prisma.payrollBatch.update({
      where: { id: batchId },
      data: {
        totalPay: Math.round(totals.totalPay * 100) / 100,
        totalNetPay: Math.round(totals.totalNetPay * 100) / 100,
        totalSocialOrg: Math.round(totals.totalSocialOrg * 100) / 100,
        totalSocialEmp: Math.round(totals.totalSocialEmp * 100) / 100,
        totalHousingOrg: Math.round(totals.totalHousingOrg * 100) / 100,
        totalHousingEmp: Math.round(totals.totalHousingEmp * 100) / 100,
        totalTax: Math.round(totals.totalTax * 100) / 100,
      },
    })

    res.json({ success: true, data: { imported: results.length, details: results } })
  } catch (err) {
    next(err)
  }
})

// ========== 税率试算 ==========
router.post('/tax-preview', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { employeeId, month, baseSalary, overtimePay, allowance, deduction, bonus, specialDeduction } = req.body
    const orgId = req.user!.orgId

    // 获取员工和配置
    const [employee, socialConfig, housingConfig] = await Promise.all([
      employeeId ? prisma.employee.findFirst({ where: { id: employeeId, orgId }, include: { contracts: { orderBy: { createdAt: 'desc' }, take: 1 } } }) : null,
      prisma.socialInsuranceConfig.findFirst({
        where: { orgId, effectiveFrom: { lte: month }, OR: [{ effectiveTo: null }, { effectiveTo: { gte: month } }] },
        orderBy: { effectiveFrom: 'desc' },
      }),
      prisma.housingFundConfig.findFirst({
        where: { orgId, effectiveFrom: { lte: month }, OR: [{ effectiveTo: null }, { effectiveTo: { gte: month } }] },
        orderBy: { effectiveFrom: 'desc' },
      }),
    ])

    const emp = employee || { socialInsBase: baseSalary, housingFundBase: baseSalary } as any
    // 非劳动合同类型不缴纳社保公积金
    const contractType = (employee as any)?.contracts?.[0]?.contractType
    const isNoSocialContract = contractType && ['LABOR', 'INTERNSHIP', 'PARTTIME', 'OUTSOURCING', 'UNSIGNED'].includes(contractType)
    const socialBase = isNoSocialContract ? 0 : (emp.socialInsBase != null ? emp.socialInsBase : baseSalary)
    const housingBase = isNoSocialContract ? 0 : (emp.housingFundBase != null ? emp.housingFundBase : baseSalary)

    // 计算社保公积金
    let socialEmp = 0, housingEmp = 0
    if (socialConfig) {
      const { calcSocialInsurance } = await import('../services/payroll.service')
      const social = calcSocialInsurance(socialBase, socialConfig)
      socialEmp = social.socialEmp
    }
    if (housingConfig) {
      const { calcHousingFund } = await import('../services/payroll.service')
      const housing = calcHousingFund(housingBase, housingConfig)
      housingEmp = housing.housingEmp
    }

    // 获取 YTD 数据计算累计个税
    const year = month.slice(0, 4)
    const ytdPayslips = employeeId
      ? await prisma.payslip.findMany({
          where: { employeeId, month: { startsWith: year }, status: 'PUBLISHED' },
          orderBy: { month: 'asc' },
        })
      : []

    const ytdTaxableIncome = ytdPayslips.reduce((sum, p) => sum + (p.totalPay - p.deduction - socialEmp - housingEmp - (specialDeduction || 0)), 0)
    const ytdTaxDeducted = ytdPayslips.reduce((sum, p) => sum + (p.tax || 0), 0)

    const { calcCumulativeTax } = await import('../services/payroll.service')
    const totalPay = (baseSalary || 0) + (overtimePay || 0) + (allowance || 0) - (deduction || 0) + (bonus || 0)
    const taxableIncome = totalPay - socialEmp - housingEmp - (specialDeduction || 0)
    const tax = calcCumulativeTax(ytdTaxableIncome + taxableIncome, ytdTaxDeducted)
    const netPay = totalPay - socialEmp - housingEmp - tax

    res.json({
      success: true,
      data: {
        baseSalary: baseSalary || 0,
        overtimePay: overtimePay || 0,
        allowance: allowance || 0,
        deduction: deduction || 0,
        bonus: bonus || 0,
        totalPay,
        socialEmp,
        housingEmp,
        specialDeduction: specialDeduction || 0,
        taxableIncome,
        estimatedTax: tax,
        netPay,
        ytdPayslipCount: ytdPayslips.length,
        breakdown: [
          { label: '应发合计', value: totalPay },
          { label: '个人社保', value: -socialEmp },
          { label: '个人公积金', value: -housingEmp },
          { label: '专项附加扣除', value: -(specialDeduction || 0) },
          { label: '应纳税所得额', value: taxableIncome },
          { label: '当月个税', value: -tax },
          { label: '实发工资', value: netPay },
        ],
      },
    })
  } catch (err) {
    next(err)
  }
})

// ========== 薪资汇总表 & 明细表 ==========

// 薪资汇总表（按部门维度统计）
router.get('/batch/:id/summary', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const batch = await prisma.payrollBatch.findFirst({
      where: { id: req.params.id, orgId: req.user!.orgId },
    })
    if (!batch) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '批次不存在' } })

    const entries = await prisma.batchEntry.findMany({
      where: { batchId: req.params.id },
      include: { employee: { select: { id: true, name: true, department: true } } },
    })

    // 按部门汇总
    const deptMap = new Map<string, any>()
    for (const e of entries) {
      const dept = e.employee.department || '未分配'
      if (!deptMap.has(dept)) {
        deptMap.set(dept, { department: dept, headcount: 0, totalPay: 0, totalNetPay: 0, totalSocialEmp: 0, totalSocialOrg: 0, totalHousingEmp: 0, totalHousingOrg: 0, totalTax: 0 })
      }
      const d = deptMap.get(dept)
      d.headcount++
      d.totalPay += e.totalPay
      d.totalNetPay += e.netPay
      d.totalSocialEmp += e.socialEmp
      d.totalSocialOrg += e.socialOrg
      d.totalHousingEmp += e.housingEmp
      d.totalHousingOrg += e.housingOrg
      d.totalTax += e.tax
    }

    const departments = Array.from(deptMap.values())
    const grandTotal = {
      headcount: entries.length,
      totalPay: entries.reduce((s, e) => s + e.totalPay, 0),
      totalNetPay: entries.reduce((s, e) => s + e.netPay, 0),
      totalSocialEmp: entries.reduce((s, e) => s + e.socialEmp, 0),
      totalSocialOrg: entries.reduce((s, e) => s + e.socialOrg, 0),
      totalHousingEmp: entries.reduce((s, e) => s + e.housingEmp, 0),
      totalHousingOrg: entries.reduce((s, e) => s + e.housingOrg, 0),
      totalTax: entries.reduce((s, e) => s + e.tax, 0),
    }

    res.json({ success: true, data: { batch, departments, grandTotal } })
  } catch (err) { next(err) }
})

// 薪资明细表（全员明细）
router.get('/batch/:id/detail', async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const batch = await prisma.payrollBatch.findFirst({
      where: { id: req.params.id, orgId: req.user!.orgId },
    })
    if (!batch) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '批次不存在' } })

    const entries = await prisma.batchEntry.findMany({
      where: { batchId: req.params.id },
      include: { employee: { select: { id: true, name: true, department: true, phone: true } } },
      orderBy: { employee: { department: 'asc' } },
    })

    const details = entries.map(e => ({
      employeeId: e.employeeId,
      name: e.employee.name,
      department: e.employee.department,
      phone: e.employee.phone,
      baseSalary: e.baseSalary,
      positionSalary: e.positionSalary,
      performanceSalary: e.performanceSalary,
      senioritySalary: e.senioritySalary,
      overtimePay: e.overtimePay,
      transportAllowance: e.transportAllowance,
      mealAllowance: e.mealAllowance,
      housingAllowance: e.housingAllowance,
      communicationAllowance: e.communicationAllowance,
      allowance: e.allowance,
      bonus: e.bonus,
      deduction: e.deduction,
      otherDeduction: e.otherDeduction,
      socialEmp: e.socialEmp,
      housingEmp: e.housingEmp,
      tax: e.tax,
      totalPay: e.totalPay,
      netPay: e.netPay,
    }))

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

export default router
