/**
 * 工时法计算模块
 *
 * 提供工时法的行构建、合并、费用计算等纯函数，
 * 供 HourlyPricingPane/HourlyFeeGrid 和 pricingMethodTotals.ts 共用。
 */

import { expertList } from '@/sql'
import { roundTo, toDecimal, toFiniteNumberOrNull } from '@/lib/decimal'
import type { HourlyDetailRow, ExpertLite } from '@/types/pricing'

/* ----------------------------------------------------------------
 * 专家字典查询
 * ---------------------------------------------------------------- */

/** 获取专家条目列表（按 ID 排序） */
export const getExpertEntries = (): [string, ExpertLite][] =>
  Object.entries(expertList as Record<string, ExpertLite>)
    .sort((a, b) => Number(a[0]) - Number(b[0]))

/** 计算专家默认采用单价 = 基准单价 × 管理系数 */
const getDefaultHourlyAdoptedPrice = (expert: ExpertLite): number | null => {
  if (expert.defPrice == null || expert.manageCoe == null) return null
  return roundTo(toDecimal(expert.defPrice).mul(expert.manageCoe), 2)
}

/* ----------------------------------------------------------------
 * 行构建与合并
 * ---------------------------------------------------------------- */

/** 构建工时法默认行 */
export const buildDefaultHourlyRows = (): HourlyDetailRow[] =>
  getExpertEntries().map(([expertId, expert]) => ({
    id: `expert-${expertId}`,
    adoptedBudgetUnitPrice: getDefaultHourlyAdoptedPrice(expert),
    personnelCount: null,
    workdayCount: null
  }))

/** 合并持久化行与默认行 */
export const mergeHourlyRows = (
  rowsFromDb: Array<Partial<HourlyDetailRow> & Pick<HourlyDetailRow, 'id'>> | undefined
): HourlyDetailRow[] => {
  const dbMap = new Map<string, Partial<HourlyDetailRow> & Pick<HourlyDetailRow, 'id'>>()
  for (const row of rowsFromDb || []) dbMap.set(row.id, row)

  return buildDefaultHourlyRows().map(row => {
    const fromDb = dbMap.get(row.id)
    if (!fromDb) return row
    return {
      ...row,
      adoptedBudgetUnitPrice: toFiniteNumberOrNull(fromDb.adoptedBudgetUnitPrice),
      personnelCount: toFiniteNumberOrNull(fromDb.personnelCount),
      workdayCount: toFiniteNumberOrNull(fromDb.workdayCount)
    }
  })
}

/* ----------------------------------------------------------------
 * 费用计算
 * ---------------------------------------------------------------- */

/** 计算工时法单行费用 = 采用单价 × 人数 × 工日数 */
export const calcHourlyServiceBudget = (row: HourlyDetailRow): number | null => {
  const { adoptedBudgetUnitPrice, personnelCount, workdayCount } = row
  if (adoptedBudgetUnitPrice == null || personnelCount == null || workdayCount == null) return null
  return roundTo(toDecimal(adoptedBudgetUnitPrice).mul(personnelCount).mul(workdayCount), 2)
}
