/** 结算方式展示 */
const SETTLEMENT_MODE_LABELS = {
	daily: '日结',
	weekly: '周结',
	week: '周结',
	piece: '计件',
	monthly: '月结',
	month: '月结'
}

/** 结算单位短文案（用于 人均/天） */
const SETTLEMENT_UNIT_LABELS = {
	daily: '天',
	week: '周',
	weekly: '周',
	monthly: '月',
	month: '月',
	piece: '件'
}

const SCHEME_ICONS = {
	SCHEME_A: '⭐',
	SCHEME_B: '💡'
}

export const NEXT_ACTION_SHOW_ORDER_QRCODE = 'show_order_qrcode'

/**
 * 从 SSE 事件 JSON 提取卡片元数据（camelCase / snake_case 兼容）
 * - content_type=card_draft|card_order|card_cost
 * - 或 next_action=show_order_qrcode（对话写入确认文案 + 二维码卡）
 */
export function extractChatCardMeta(data) {
	if (!data || typeof data !== 'object') return null

	const contentType = data.content_type || data.contentType || null
	const nextAction = data.next_action || data.nextAction || null
	const isOrderQrAction = nextAction === NEXT_ACTION_SHOW_ORDER_QRCODE
	const isKnownCardType = contentType === 'card_draft'
		|| contentType === 'card_order'
		|| contentType === 'card_cost'

	if (!isKnownCardType && !isOrderQrAction) return null
	if (contentType === 'text' && !isOrderQrAction) return null

	const rawDraftId = data.related_draft_id != null ? data.related_draft_id : data.relatedDraftId
	const relatedDraftId = rawDraftId != null && rawDraftId !== '' ? Number(rawDraftId) : null
	const cardPayload = data.card_payload || data.cardPayload || null

	return {
		contentType: isKnownCardType ? contentType : (isOrderQrAction ? 'card_order' : contentType),
		relatedDraftId: relatedDraftId != null && !Number.isNaN(relatedDraftId) ? relatedDraftId : null,
		nextAction,
		cardPayload
	}
}

/**
 * 合并流式过程中出现的卡片元数据（后出现的非空字段覆盖）
 */
export function mergeChatCardMeta(prev, next) {
	if (!next) return prev || null
	if (!prev) return next
	return {
		contentType: next.contentType || prev.contentType,
		relatedDraftId: next.relatedDraftId != null ? next.relatedDraftId : prev.relatedDraftId,
		nextAction: next.nextAction || prev.nextAction,
		cardPayload: next.cardPayload || prev.cardPayload
	}
}

/**
 * 会触发拉取用工草稿并展示聊天气泡的 content_type
 * card_draft：待确认草稿；card_order：已确认订单（related_draft_id 仍为草稿 id）
 */
export function isDraftCardContentType(contentType) {
	return contentType === 'card_draft' || contentType === 'card_order'
}

/**
 * 是否应查询用工草稿详情并生成草稿卡片
 */
export function shouldFetchDraftCard(meta) {
	return !!(
		meta &&
		isDraftCardContentType(meta.contentType) &&
		meta.relatedDraftId != null &&
		!Number.isNaN(Number(meta.relatedDraftId))
	)
}

/**
 * AI 对话：下一步为展示订单二维码（对话内确认文案 + 二维码卡）
 */
export function shouldShowOrderQrcode(meta) {
	if (!meta) return false
	const action = meta.nextAction || meta.next_action || ''
	return action === NEXT_ACTION_SHOW_ORDER_QRCODE
}

/**
 * 解析 SSE / 消息中的 card_payload（对象或 JSON 字符串）
 */
export function parseChatCardPayload(raw) {
	if (!raw) return null
	if (typeof raw === 'object') return raw
	if (typeof raw !== 'string') return null
	const text = raw.trim()
	if (!text) return null
	try {
		const parsed = JSON.parse(text)
		return parsed && typeof parsed === 'object' ? parsed : null
	} catch (e) {
		return null
	}
}

/**
 * 草稿状态
 */
export function getDraftStatus(draft) {
	if (!draft) return 'pending'
	return draft.status || (draft.detail && draft.detail.status) || 'pending'
}

/**
 * 草稿是否已补全，可调用成本测算（仅 pending）
 */
export function isDraftReadyForCost(draft) {
	if (!draft) return false
	if (getDraftStatus(draft) !== 'pending') return false
	const missing = draft.missingFields || (draft.detail && draft.detail.missingFields) || []
	return Array.isArray(missing) && missing.length === 0
}

/**
 * pending 但必填未补全
 */
export function isDraftIncomplete(draft) {
	if (!draft) return false
	if (getDraftStatus(draft) !== 'pending') return false
	const missing = draft.missingFields || (draft.detail && draft.detail.missingFields) || []
	return Array.isArray(missing) && missing.length > 0
}

/**
 * 已确认草稿 → 用明细/缓存拼一版成本卡片（不可再调 cost-comparison）
 */
export function buildConfirmedCostPlans(draft) {
	if (!draft) return []
	if (Array.isArray(draft.costPlans) && draft.costPlans.length) {
		return draft.costPlans.map((plan) => ({ ...plan }))
	}
	if (draft.confirmedPlan && typeof draft.confirmedPlan === 'object') {
		return [{ ...draft.confirmedPlan, recommended: true }]
	}

	const detail = draft.detail || {}
	const code = draft.selectedSchemeCode || detail.selectedSchemeCode || 'SCHEME_A'
	const workerCount = draft.workerCount != null ? draft.workerCount : detail.workerCount
	const total = draft.estimatedTotal != null ? draft.estimatedTotal : detail.estimatedTotal
	const perCapita = draft.estimatedPerCapita != null
		? draft.estimatedPerCapita
		: detail.estimatedPerCapita
	const title = draft.confirmedPlanTitle || (code === 'SCHEME_B' ? '劳务报酬模式' : '灵活用工模式（推荐）')

	let avgCostText = '—'
	if (perCapita != null && perCapita !== '') {
		avgCostText = `${formatDraftMoney(perCapita)}/人`
	} else if (total != null && workerCount > 0) {
		avgCostText = `${formatDraftMoney(Number(total) / Number(workerCount))}/人`
	}

	return [{
		id: code,
		code,
		recommended: true,
		icon: SCHEME_ICONS[code] || '⭐',
		title,
		total: formatDraftMoney(total),
		avgCost: avgCostText,
		rows: [],
		breakdown: [],
		compliance: ['已确认']
	}]
}

export function formatSettlementMode(mode) {
	if (!mode) return '待补充'
	return SETTLEMENT_MODE_LABELS[mode] || mode
}

export function formatDraftMoney(val) {
	if (val == null || val === '') return '—'
	const n = Number(val)
	if (Number.isNaN(n)) return String(val)
	return `¥${n.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}`
}

function pickField(obj, ...keys) {
	if (!obj || typeof obj !== 'object') return null
	for (let i = 0; i < keys.length; i++) {
		const key = keys[i]
		if (obj[key] != null && obj[key] !== '') return obj[key]
	}
	return null
}

function normalizeCycleKey(cycle) {
	const key = String(cycle || 'daily').toLowerCase()
	if (key === 'month') return 'monthly'
	if (key === 'week') return 'weekly'
	return key || 'daily'
}

function settlementUnitLabel(cycle) {
	const key = normalizeCycleKey(cycle)
	return SETTLEMENT_UNIT_LABELS[key] || '天'
}

/**
 * 取方案下主结算周期（优先日结），用于汇总人均/到手
 */
export function pickPrimarySettlementCycle(scheme) {
	if (!scheme) return null
	const cycles = scheme.bySettlementCycle || scheme.by_settlement_cycle || []
	if (!Array.isArray(cycles) || !cycles.length) return null
	const daily = cycles.find((c) => normalizeCycleKey(pickField(c, 'settlementCycle', 'settlement_cycle')) === 'daily')
	return daily || cycles[0]
}

/**
 * 从费用对象拼展示行（劳务费/服务费/保险/税费等）
 * @param {object} source cost 或 by_settlement_cycle 项
 * @param {{ ratio?: number|null, includeWorkerTax?: object|null, unitGross?: *, unitLabel?: string }} [opt]
 */
function buildFeeDetailRows(source, opt = {}) {
	const rows = []
	if (!source || typeof source !== 'object') return rows
	const ratio = opt.ratio != null && !Number.isNaN(Number(opt.ratio)) ? Number(opt.ratio) : null
	const pushMoney = (label, raw) => {
		if (raw == null || raw === '') return
		const num = Number(raw)
		if (Number.isNaN(num)) return
		// 分摊后仍为 0 的不展示
		const val = ratio != null ? num * ratio : num
		if (!val && val !== 0) return
		if (Number(val) === 0) return
		rows.push({ label, value: formatDraftMoney(val) })
	}
	pushMoney('劳务费', pickField(source, 'laborFee', 'labor_fee', 'companyPay', 'company_pay'))
	pushMoney('服务费', pickField(source, 'serviceFee', 'service_fee'))
	pushMoney('保险/社保', pickField(source, 'insuranceFee', 'insurance_fee'))
	const taxFee = pickField(source, 'taxFee', 'tax_fee')
	if (taxFee != null) pushMoney('代征税费', taxFee)
	const income = opt.includeWorkerTax
	if (income && taxFee == null) {
		const personalTax = pickField(income, 'tax')
		if (personalTax != null && Number(personalTax) > 0) {
			pushMoney('代扣税费', personalTax)
		}
	}
	if (opt.unitGross != null && opt.unitGross !== '') {
		const unit = opt.unitLabel || '天'
		rows.push({ label: `税前/${unit}`, value: formatDraftMoney(opt.unitGross) })
	}
	return rows
}

/**
 * group_breakdown → 按工种展示行（人均成本 / 到手按结算单位）
 * @param {object} scheme
 * @param {{ workerGroups?: Array }} [ctx]
 */
export function mapGroupBreakdownRows(scheme, ctx = {}) {
	const groups = (scheme && (scheme.groupBreakdown || scheme.group_breakdown)) || []
	if (!Array.isArray(groups) || !groups.length) return []
	const draftGroups = Array.isArray(ctx.workerGroups) ? ctx.workerGroups : []
	const cycles = (scheme && (scheme.bySettlementCycle || scheme.by_settlement_cycle)) || []
	const schemeCost = (scheme && scheme.cost) || {}
	const schemeIncome = (scheme && (scheme.workerIncome || scheme.worker_income)) || {}
	const totalCostNum = Number(pickField(schemeCost, 'totalCost', 'total_cost'))

	return groups.map((g, idx) => {
		const jobType = pickField(g, 'jobType', 'job_type') || `工种${idx + 1}`
		const countRaw = pickField(g, 'count')
		const count = countRaw != null && countRaw !== '' ? Number(countRaw) : 0
		const cycle = normalizeCycleKey(pickField(g, 'settlementCycle', 'settlement_cycle') || 'daily')
		const cost = pickField(g, 'cost')
		const netIncome = pickField(g, 'netIncome', 'net_income')
		const unit = settlementUnitLabel(cycle)

		let workDays = null
		const matched = draftGroups.find((d) => d && String(d.workType || '') === String(jobType))
			|| draftGroups[idx]
			|| null
		if (matched && matched.workDays != null && !Number.isNaN(Number(matched.workDays))) {
			workDays = Number(matched.workDays)
		}

		const periodUnits = (count > 0 && workDays != null && workDays > 0)
			? count * workDays
			: null

		let avgCost = null
		let unitNet = null
		let unitGross = null
		const costNum = cost != null && cost !== '' ? Number(cost) : NaN
		const netNum = netIncome != null && netIncome !== '' ? Number(netIncome) : NaN
		if (periodUnits && !Number.isNaN(costNum)) avgCost = costNum / periodUnits
		if (periodUnits && !Number.isNaN(netNum)) unitNet = netNum / periodUnits

		const cycleRow = cycles.find(
			(c) => normalizeCycleKey(pickField(c, 'settlementCycle', 'settlement_cycle')) === cycle
		) || null

		// 缺工期时回退：同结算方式的 by_settlement_cycle；再不行用 组合计/人数
		if (avgCost == null || unitNet == null || unitGross == null) {
			if (cycleRow) {
				if (avgCost == null) {
					const v = pickField(cycleRow, 'avgCost', 'avg_cost')
					if (v != null) avgCost = Number(v)
				}
				if (unitNet == null) {
					const v = pickField(cycleRow, 'unitNet', 'unit_net')
					if (v != null) unitNet = Number(v)
				}
				if (unitGross == null) {
					const v = pickField(cycleRow, 'unitGross', 'unit_gross')
					if (v != null) unitGross = Number(v)
				}
			}
		}
		if ((avgCost == null || Number.isNaN(avgCost)) && count > 0 && !Number.isNaN(costNum)) {
			avgCost = costNum / count
		}
		if ((unitNet == null || Number.isNaN(unitNet)) && count > 0 && !Number.isNaN(netNum)) {
			unitNet = netNum / count
		}

		// 其他支出：优先按同结算周期分项 × 工种成本占比；否则用方案合计分摊
		const groupCostRatio = (!Number.isNaN(costNum) && totalCostNum > 0)
			? costNum / totalCostNum
			: null
		let feeRows = []
		if (cycleRow) {
			const cycleTotal = Number(pickField(cycleRow, 'totalCost', 'total_cost'))
			const cycleRatio = (!Number.isNaN(costNum) && cycleTotal > 0)
				? costNum / cycleTotal
				: groupCostRatio
			feeRows = buildFeeDetailRows(cycleRow, {
				ratio: cycleRatio,
				unitGross: unitGross,
				unitLabel: unit
			})
		}
		if (!feeRows.length) {
			feeRows = buildFeeDetailRows(schemeCost, {
				ratio: groupCostRatio,
				includeWorkerTax: schemeIncome,
				unitGross: unitGross,
				unitLabel: unit
			})
		} else if (unitGross != null && !feeRows.some((r) => String(r.label).indexOf('税前') === 0)) {
			feeRows.push({ label: `税前/${unit}`, value: formatDraftMoney(unitGross) })
		}

		return {
			rowKey: idx,
			title: `工种 ${idx + 1}`,
			jobType,
			countText: count > 0 ? `${count}人` : '—',
			settlementLabel: formatSettlementMode(cycle),
			costText: formatDraftMoney(cost),
			netText: formatDraftMoney(netIncome),
			avgCostText: avgCost != null && !Number.isNaN(avgCost) ? formatDraftMoney(avgCost) : '—',
			unitNetText: unitNet != null && !Number.isNaN(unitNet) ? formatDraftMoney(unitNet) : '—',
			avgCostLabel: `人均/${unit}`,
			unitNetLabel: `到手/${unit}`,
			feeRows,
			// 小程序模板预计算：默认折叠
			expanded: false,
			chevronClass: ''
		}
	})
}

/**
 * by_settlement_cycle → 无工种拆分时的兜底行
 */
function mapSettlementCycleRows(scheme) {
	const cycles = (scheme && (scheme.bySettlementCycle || scheme.by_settlement_cycle)) || []
	if (!Array.isArray(cycles) || !cycles.length) return []
	return cycles.map((c, idx) => {
		const cycle = normalizeCycleKey(pickField(c, 'settlementCycle', 'settlement_cycle') || 'daily')
		const unit = settlementUnitLabel(cycle)
		const workerCount = pickField(c, 'workerCount', 'worker_count')
		const unitGross = pickField(c, 'unitGross', 'unit_gross')
		const feeRows = buildFeeDetailRows(c, {
			ratio: null,
			unitGross,
			unitLabel: unit
		})
		return {
			rowKey: `cycle_${idx}`,
			title: formatSettlementMode(cycle),
			jobType: formatSettlementMode(cycle),
			countText: workerCount != null ? `${workerCount}人` : '—',
			settlementLabel: formatSettlementMode(cycle),
			costText: formatDraftMoney(pickField(c, 'totalCost', 'total_cost')),
			netText: formatDraftMoney(pickField(c, 'net')),
			avgCostText: formatDraftMoney(pickField(c, 'avgCost', 'avg_cost')),
			unitNetText: formatDraftMoney(pickField(c, 'unitNet', 'unit_net')),
			avgCostLabel: `人均/${unit}`,
			unitNetLabel: `到手/${unit}`,
			feeRows,
			expanded: false,
			chevronClass: ''
		}
	})
}

/**
 * 接口方案 → 成本卡片展示结构（对齐 v4：group_breakdown / by_settlement_cycle）
 * @param {Array} schemes McpDraftSchemeResponse[]
 * @param {{ workerCount?: number, workerGroups?: Array }} [ctx]
 */
export function mapCostSchemesToPlans(schemes = [], ctx = {}) {
	const workerCount = ctx.workerCount != null && ctx.workerCount > 0 ? Number(ctx.workerCount) : 1
	const list = Array.isArray(schemes) ? schemes : []

	return list.map((scheme, index) => {
		const code = scheme.code || `SCHEME_${index}`
		const title = scheme.title || code
		const tags = Array.isArray(scheme.tags) ? scheme.tags : []
		const cost = scheme.cost || {}
		const income = scheme.workerIncome || scheme.worker_income || {}

		const totalCost = pickField(cost, 'totalCost', 'total_cost')
		const laborFee = pickField(cost, 'laborFee', 'labor_fee', 'companyPay', 'company_pay')
		const serviceFee = pickField(cost, 'serviceFee', 'service_fee')
		const insuranceFee = pickField(cost, 'insuranceFee', 'insurance_fee')
		const taxFee = pickField(cost, 'taxFee', 'tax_fee')
		const tax = pickField(income, 'tax')
		const net = pickField(income, 'net')

		const primaryCycle = pickPrimarySettlementCycle(scheme)
		const cycleAvg = primaryCycle ? pickField(primaryCycle, 'avgCost', 'avg_cost') : null
		const cycleUnitNet = primaryCycle ? pickField(primaryCycle, 'unitNet', 'unit_net') : null
		const cycleKey = primaryCycle
			? normalizeCycleKey(pickField(primaryCycle, 'settlementCycle', 'settlement_cycle'))
			: 'daily'
		const unit = settlementUnitLabel(cycleKey)

		let avgCostText = '—'
		if (cycleAvg != null) {
			avgCostText = `${formatDraftMoney(cycleAvg)}/${unit}`
		} else {
			const totalNum = Number(totalCost)
			if (!Number.isNaN(totalNum) && workerCount > 0) {
				avgCostText = `${formatDraftMoney(totalNum / workerCount)}/人`
			}
		}

		const recommended =
			!!scheme.recommended ||
			code === 'SCHEME_A' ||
			String(title).indexOf('推荐') >= 0 ||
			tags.indexOf('推荐') >= 0

		const breakdown = []
		if (laborFee != null) breakdown.push({ label: '劳务费', value: formatDraftMoney(laborFee) })
		if (serviceFee != null) breakdown.push({ label: '服务费', value: formatDraftMoney(serviceFee) })
		if (insuranceFee != null) breakdown.push({ label: '保险/社保', value: formatDraftMoney(insuranceFee) })
		if (taxFee != null) breakdown.push({ label: '代征税费', value: formatDraftMoney(taxFee) })
		else if (tax != null && Number(tax) > 0) breakdown.push({ label: '代扣税费', value: formatDraftMoney(tax) })

		const rows = []
		if (net != null) rows.push({ label: '工人到手合计', value: formatDraftMoney(net) })
		if (cycleUnitNet != null) rows.push({ label: `到手/${unit}`, value: formatDraftMoney(cycleUnitNet) })

		const groupRows = mapGroupBreakdownRows(scheme, ctx)
		const displayRows = groupRows.length ? groupRows : mapSettlementCycleRows(scheme)

		return {
			id: code,
			code,
			recommended,
			icon: SCHEME_ICONS[code] || (recommended ? '⭐' : '💡'),
			title,
			total: formatDraftMoney(totalCost),
			avgCost: avgCostText,
			groupRows: displayRows,
			rows,
			breakdown,
			compliance: tags,
			raw: scheme
		}
	})
}

/**
 * 从草稿详情 / 卡片结构读取登记小程序码 URL（优先小驼峰 qrCodeUrl）
 */
export function pickDraftQrCodeUrl(source) {
	if (!source || typeof source !== 'object') return ''
	const nested = source.detail && typeof source.detail === 'object' ? source.detail : null
	return source.qrCodeUrl
		|| source.qr_code_url
		|| (nested && (nested.qrCodeUrl || nested.qr_code_url))
		|| ''
}

/**
 * 从草稿详情 / 确认响应读取登记 token（优先小驼峰 qrToken）
 * 与公开查询 / 小程序码 scene 值一致
 */
export function pickDraftQrToken(source) {
	if (!source || typeof source !== 'object') return ''
	const nested = source.detail && typeof source.detail === 'object' ? source.detail : null
	const raw = source.qrToken
		|| source.qr_token
		|| (nested && (nested.qrToken || nested.qr_token))
		|| ''
	return raw == null ? '' : String(raw).trim()
}

/**
 * 解析草稿详情中的用工组（兼容 camelCase / snake_case）
 * @returns {Array<{
 *   groupId: string,
 *   workType: string,
 *   workerCount: number|null,
 *   workDays: number|null,
 *   workLocation: string,
 *   settlementMode: string,
 *   unitAmount: number|null,
 *   totalAmount: number|null
 * }>}
 */
function pickDateTimeRaw(g, camel, snake) {
	if (!g || typeof g !== 'object') return ''
	const v = g[camel] != null && g[camel] !== '' ? g[camel] : g[snake]
	return v == null ? '' : String(v)
}

/** 解析接口日期时间为 date(YYYY-MM-DD) + time(HH:mm) */
export function splitDateTimeParts(raw) {
	if (raw == null || raw === '') {
		return { date: '', time: '' }
	}
	let s = String(raw).trim().replace('T', ' ').replace(/\//g, '-')
	const m = s.match(/^(\d{4}-\d{2}-\d{2})(?:\s+(\d{2}:\d{2})(?::\d{2})?)?/)
	if (!m) return { date: '', time: '' }
	return { date: m[1], time: m[2] || '08:00' }
}

/** 统一为 YYYY-MM-DD（去掉 /） */
export function normalizeDateYmd(dateStr) {
	if (dateStr == null || dateStr === '') return ''
	const s = String(dateStr).trim().replace(/\//g, '-')
	const m = s.match(/^(\d{4}-\d{2}-\d{2})/)
	return m ? m[1] : ''
}

/** 展示：2025-07-09 08:00 */
export function formatDateTimeDisplay(dateStr, timeStr) {
	const d = normalizeDateYmd(dateStr)
	const t = timeStr ? String(timeStr).slice(0, 5) : ''
	if (d && t) return `${d} ${t}`
	if (d) return d
	return '请选择'
}

export function normalizeWorkerGroups(detail = {}) {
	const raw = detail.workerGroups || detail.worker_groups || []
	if (!Array.isArray(raw) || !raw.length) return []
	return raw.map((g, idx) => {
		if (!g || typeof g !== 'object') {
			return {
				groupId: `g_${idx}`,
				workType: '',
				workerCount: null,
				workDays: null,
				workLocation: '',
				settlementMode: '',
				unitAmount: null,
				totalAmount: null,
				workStartDate: '',
				workEndDate: ''
			}
		}
		const workerCount = g.workerCount != null ? g.workerCount : g.worker_count
		const workDays = g.workDays != null ? g.workDays : g.work_days
		const unitAmount = g.unitAmount != null ? g.unitAmount : g.unit_amount
		const totalAmount = g.totalAmount != null ? g.totalAmount : g.total_amount
		const rawId = g.id != null ? g.id : (g.workItemId != null ? g.workItemId : g.work_item_id)
		return {
			id: rawId != null && rawId !== '' && !Number.isNaN(Number(rawId)) ? Number(rawId) : null,
			groupId: String(g.groupId || g.group_id || g.groupNo || g.group_no || `g_${idx}`),
			workType: g.workType || g.work_type || g.jobType || g.job_type || '',
			workerCount: workerCount != null && workerCount !== '' ? Number(workerCount) : null,
			workDays: workDays != null && workDays !== '' ? Number(workDays) : null,
			workLocation: g.workLocation || g.work_location || g.region || '',
			settlementMode: String(
				g.settlementMode || g.settlement_mode || g.settlementCycle || g.settlement_cycle || ''
			).toLowerCase(),
			unitAmount: unitAmount != null && unitAmount !== '' ? Number(unitAmount) : null,
			totalAmount: totalAmount != null && totalAmount !== '' ? Number(totalAmount) : null,
			workStartDate: pickDateTimeRaw(g, 'workStartDate', 'work_start_date'),
			workEndDate: pickDateTimeRaw(g, 'workEndDate', 'work_end_date')
		}
	})
}

/**
 * settlement_mode → 工期单位：月结用「月」，其余用「天」
 */
export function formatWorkDurationUnit(settlementMode) {
	const mode = String(settlementMode || '').toLowerCase()
	if (mode === 'monthly' || mode === 'month') return '月'
	return '天'
}

/**
 * 单组用工人数展示：如 10人 × 2天 / 5人 × 1月
 */
export function formatWorkerGroupHeadcount(group = {}) {
	const count = group.workerCount
	const days = group.workDays
	const unit = formatWorkDurationUnit(group.settlementMode)
	const hasCount = count != null && !Number.isNaN(Number(count))
	const hasDays = days != null && !Number.isNaN(Number(days))
	if (hasCount && hasDays) return `${count}人 × ${days}${unit}`
	if (hasCount) return `${count}人`
	if (hasDays) return `${days}${unit}`
	return ''
}

/**
 * 统一解析工种列表行（卡片 / 弹框基础信息共用）
 * 优先 workerGroupRows → workerGroups / detail.worker_groups → 扁平字段合成 1 行
 */
export function resolveWorkerGroupRows(draft) {
	if (!draft || typeof draft !== 'object') return []
	if (Array.isArray(draft.workerGroupRows) && draft.workerGroupRows.length) {
		return draft.workerGroupRows
	}
	const detail = draft.detail && typeof draft.detail === 'object' ? draft.detail : draft
	let groups = Array.isArray(draft.workerGroups) && draft.workerGroups.length
		? draft.workerGroups
		: normalizeWorkerGroups(detail)
	if (groups.length) {
		return groups.map((g, idx) => ({
			rowKey: (g && (g.groupId || g.rowKey)) || idx,
			workType: (g && g.workType) || '待补充',
			workLocation: (g && g.workLocation) || '待补充',
			headcountText: formatWorkerGroupHeadcount(g || {}) || '待补充',
			settlementMode: g && g.settlementMode,
			workerCount: g && g.workerCount,
			workDays: g && g.workDays
		}))
	}
	const workType = draft.workType && draft.workType !== '待补充' ? draft.workType : (detail.workType || detail.work_type || '')
	const workLocation = draft.workLocation && draft.workLocation !== '待补充'
		? draft.workLocation
		: (detail.workLocation || detail.work_location || '')
	const headcountText = draft.headcountText && draft.headcountText !== '待补充'
		? draft.headcountText
		: formatWorkerGroupHeadcount({
			workerCount: draft.workerCount != null ? draft.workerCount : detail.workerCount,
			workDays: draft.workDays != null ? draft.workDays : detail.workDays,
			settlementMode: draft.settlementMode || detail.settlementMode || detail.settlement_mode
		})
	if (!workType && !workLocation && !headcountText) return []
	return [{
		rowKey: 'flat_0',
		workType: workType || '待补充',
		workLocation: workLocation || '待补充',
		headcountText: headcountText || '待补充'
	}]
}

/**
 * 草稿详情 → 聊天气泡展示结构
 */
export function mapDraftDetailToCard(detail = {}) {
	const groups = normalizeWorkerGroups(detail)
	let workType = detail.workType || detail.work_type || '待补充'
	let workLocation = detail.workLocation || detail.work_location || '待补充'
	let workerCount = detail.workerCount != null ? detail.workerCount : detail.worker_count
	let workDays = detail.workDays != null ? detail.workDays : detail.work_days
	let settlementMode = detail.settlementMode || detail.settlement_mode || ''
	let headcountText = '待补充'
	let estimatedTotal = detail.estimatedTotal != null
		? detail.estimatedTotal
		: (detail.estimated_total != null ? detail.estimated_total : null)

	const workerGroupRows = groups.map((g, idx) => ({
		rowKey: g.groupId || idx,
		workType: g.workType || '待补充',
		workLocation: g.workLocation || '待补充',
		headcountText: formatWorkerGroupHeadcount(g) || '待补充',
		settlementMode: g.settlementMode,
		settlementModeLabel: formatSettlementMode(g.settlementMode),
		workerCount: g.workerCount,
		workDays: g.workDays
	}))

	if (groups.length) {
		const types = groups.map((g) => g.workType).filter(Boolean)
		workType = types.length ? types.join('、') : '待补充'
		const locs = []
		groups.forEach((g) => {
			if (g.workLocation && locs.indexOf(g.workLocation) < 0) locs.push(g.workLocation)
		})
		workLocation = locs.length ? locs.join('、') : '待补充'

		const headParts = groups.map((g) => formatWorkerGroupHeadcount(g)).filter(Boolean)
		headcountText = headParts.length ? headParts.join('；') : '待补充'

		let sumCount = 0
		let hasCount = false
		groups.forEach((g) => {
			if (g.workerCount != null && !Number.isNaN(g.workerCount)) {
				sumCount += Number(g.workerCount)
				hasCount = true
			}
		})
		workerCount = hasCount ? sumCount : null
		workDays = groups[0].workDays
		settlementMode = groups[0].settlementMode || settlementMode

		if (estimatedTotal == null) {
			let sum = 0
			let hasTotal = false
			groups.forEach((g) => {
				if (g.totalAmount != null && !Number.isNaN(g.totalAmount)) {
					sum += Number(g.totalAmount)
					hasTotal = true
				}
			})
			if (hasTotal) estimatedTotal = sum
		}
	} else {
		if (workerCount != null && workDays != null) {
			headcountText = `${workerCount}人 × ${workDays}${formatWorkDurationUnit(settlementMode)}`
		} else if (workerCount != null) {
			headcountText = `${workerCount}人`
		} else if (workDays != null) {
			headcountText = `${workDays}${formatWorkDurationUnit(settlementMode)}`
		}
	}

	return {
		draftId: detail.id,
		draftNo: detail.draftNo || detail.draft_no,
		title: detail.title || '用工草稿',
		workType: workType || '待补充',
		workLocation: workLocation || '待补充',
		workerCount,
		workDays,
		headcountText,
		workerGroups: groups,
		workerGroupRows,
		settlementMode,
		settlementModeLabel: formatSettlementMode(settlementMode),
		dailyWage: detail.dailyWage != null ? detail.dailyWage : detail.daily_wage,
		estimatedTotal,
		estimatedTotalText: formatDraftMoney(estimatedTotal),
		estimatedPerCapita: detail.estimatedPerCapita != null
			? detail.estimatedPerCapita
			: detail.estimated_per_capita,
		selectedPlanId: detail.selectedPlanId,
		selectedSchemeCode: detail.selectedSchemeCode
			|| detail.selected_scheme_code
			|| null,
		status: detail.status,
		orderId: detail.orderId || detail.order_id || '',
		missingFields: detail.missingFields || detail.missing_fields || [],
		qrCodeUrl: pickDraftQrCodeUrl(detail),
		qrToken: pickDraftQrToken(detail),
		detail
	}
}

/**
 * 从 cost-comparison 响应中取推荐方案（recommended / SCHEME_A / 标题含「推荐」）
 * @param {object} costComparison McpDraftCalculateResponse
 */
export function pickRecommendedSchemeFromComparison(costComparison) {
	const schemes = (costComparison && (costComparison.schemes || costComparison.Schemes)) || []
	if (!Array.isArray(schemes) || !schemes.length) return null
	let recommended = schemes.find((s) => s && s.recommended)
	if (!recommended) {
		recommended = schemes.find((s) => s && (s.code === 'SCHEME_A' || String(s.title || '').indexOf('推荐') >= 0))
	}
	return recommended || schemes[0] || null
}

/**
 * 推荐方案 → 草稿卡「方案推荐」三列指标
 * 企业总支出 cost.total_cost；
 * 人均/到手优先 by_settlement_cycle（日结优先）的 avg_cost / unit_net；
 * 兼容旧字段 avg_cost_per_unit / unit_net
 */
export function mapRecommendMetricsFromScheme(scheme) {
	if (!scheme) {
		return {
			showRecommendMetrics: false,
			recommendSchemeTitle: '方案推荐',
			companyTotalText: '—',
			avgPerDayText: '—',
			netPerDayText: '—'
		}
	}
	const cost = scheme.cost || {}
	const income = scheme.workerIncome || scheme.worker_income || {}
	const totalCost = pickField(cost, 'totalCost', 'total_cost')
	const primaryCycle = pickPrimarySettlementCycle(scheme)
	let avgPerUnit = primaryCycle
		? pickField(primaryCycle, 'avgCost', 'avg_cost')
		: null
	let unitNet = primaryCycle
		? pickField(primaryCycle, 'unitNet', 'unit_net')
		: null
	if (avgPerUnit == null) avgPerUnit = pickField(cost, 'avgCostPerUnit', 'avg_cost_per_unit')
	if (unitNet == null) unitNet = pickField(income, 'unitNet', 'unit_net')
	// 仅有 group_breakdown 时：取首组 cost/count、net_income/count 兜底
	if (avgPerUnit == null || unitNet == null) {
		const groups = scheme.groupBreakdown || scheme.group_breakdown || []
		const g0 = Array.isArray(groups) && groups.length ? groups[0] : null
		if (g0) {
			const count = Number(pickField(g0, 'count') || 0)
			const gCost = Number(pickField(g0, 'cost'))
			const gNet = Number(pickField(g0, 'netIncome', 'net_income'))
			if (avgPerUnit == null && count > 0 && !Number.isNaN(gCost)) avgPerUnit = gCost / count
			if (unitNet == null && count > 0 && !Number.isNaN(gNet)) unitNet = gNet / count
		}
	}
	// 草稿卡片方案区仅展示企业总支出
	const hasAny = totalCost != null
	const title = String(scheme.title || '').trim()
	return {
		showRecommendMetrics: hasAny,
		recommendSchemeTitle: title || '方案推荐',
		companyTotalText: formatDraftMoney(totalCost),
		avgPerDayText: formatDraftMoney(avgPerUnit),
		netPerDayText: formatDraftMoney(unitNet)
	}
}

/**
 * 将 cost-comparison 结果写入草稿卡展示字段
 */
export function applyRecommendMetricsToDraftCard(draftCard, costComparison) {
	if (!draftCard) return draftCard
	const scheme = pickRecommendedSchemeFromComparison(costComparison)
	Object.assign(draftCard, mapRecommendMetricsFromScheme(scheme))
	return draftCard
}

/**
 * 从已挂载的 confirmedPlan / costPlans.raw 回填方案推荐三列（确认后无法再调 cost-comparison）
 */
export function applyRecommendMetricsFromDraftPlans(draftCard) {
	if (!draftCard) return draftCard
	if (draftCard.showRecommendMetrics) {
		if (!draftCard.recommendSchemeTitle) {
			const confirmed = draftCard.confirmedPlan
			const fromConfirmed = (confirmed && (confirmed.title || (confirmed.raw && confirmed.raw.title))) || ''
			const plans = draftCard.costPlans
			const rec = Array.isArray(plans) ? (plans.find((p) => p && p.recommended) || plans[0]) : null
			const fromPlan = (rec && (rec.title || (rec.raw && rec.raw.title))) || ''
			draftCard.recommendSchemeTitle = String(fromConfirmed || fromPlan || '方案推荐').trim() || '方案推荐'
		}
		return draftCard
	}
	const confirmed = draftCard.confirmedPlan
	if (confirmed && confirmed.raw) {
		Object.assign(draftCard, mapRecommendMetricsFromScheme(confirmed.raw))
		if (draftCard.showRecommendMetrics) return draftCard
	}
	if (confirmed && confirmed.title && !draftCard.recommendSchemeTitle) {
		draftCard.recommendSchemeTitle = String(confirmed.title).trim() || '方案推荐'
	}
	const plans = draftCard.costPlans
	if (Array.isArray(plans) && plans.length) {
		const rec = plans.find((p) => p && p.recommended) || plans[0]
		if (rec && rec.raw) {
			Object.assign(draftCard, mapRecommendMetricsFromScheme(rec.raw))
		} else if (rec && rec.title && !draftCard.recommendSchemeTitle) {
			draftCard.recommendSchemeTitle = String(rec.title).trim() || '方案推荐'
		}
	}
	return draftCard
}

/**
 * 构造聊天气泡：用工草稿卡片
 * @param {object} detail
 * @param {number|string} msgKey
 * @param {{ costComparison?: object }} [options]
 */
export function buildDraftCardMessage(detail, msgKey, options = {}) {
	const draft = mapDraftDetailToCard(detail)
	if (options && options.costComparison) {
		applyRecommendMetricsToDraftCard(draft, options.costComparison)
	} else {
		Object.assign(draft, mapRecommendMetricsFromScheme(null))
	}
	const msg = {
		type: 'draft',
		role: 'ai',
		msgKey,
		draftId: detail.id,
		voided: false,
		draft
	}
	return syncDraftCardViewMeta(msg)
}

/**
 * 同步草稿卡展示字段（供小程序模板直接绑定，避免 :class 调方法）
 */
export function syncDraftCardViewMeta(msg) {
	if (!msg || msg.type !== 'draft') return msg
	const voided = !!msg.voided
	const confirmed = !voided && !!msg.draft && getDraftStatus(msg.draft) === 'confirmed'
	msg.draftRootClass = voided
		? 'fe-biz-card--draft-voided'
		: (confirmed ? 'fe-biz-card--draft-confirmed' : '')
	msg.draftStatusClass = voided
		? 'fe-draft-card-status--cancelled'
		: (confirmed ? 'fe-draft-card-status--confirmed' : 'fe-draft-card-status--pending')
	msg.draftStatusLabel = voided ? '已作废' : (confirmed ? '已确认' : '未确认')
	return msg
}
