export const BALANCE_CALCULATION_PARAMS = {
  grasslandCapacityPerMu: 0.06229833103624831,
  muPerYak: 16.051794379822947,
  yakToSheepUnit: 1,
}

export const COUNTY_TARGET = {
  key: "county-513233",
  type: "county",
  name: "红原县",
  areaCode: "513233",
}

export const RISK_LEVELS = [
  {
    key: "healthy",
    label: "合理",
    shortLabel: "合理",
    range: "< 0%",
    description: "承载力覆盖实际载畜量，当前放牧压力处于合理区间。",
    actions: ["保持当前载畜水平与轮牧节奏", "定期复测草地生产力和载畜量", "关注极端天气对牧草生长的影响"],
  },
  {
    key: "watch",
    label: "基本实现草畜平衡",
    shortLabel: "基本平衡",
    range: "0% - 5%",
    description: "实际载畜量与草地承载力基本匹配，草畜平衡总体实现。",
    actions: ["保持当前载畜规模基本稳定", "持续核查草地生产力和牲畜存栏", "结合季节变化做好补饲和轮牧安排"],
  },
  {
    key: "light",
    label: "轻度超载",
    shortLabel: "关注",
    range: "5% - 10%",
    description: "已出现轻度超载迹象，建议提前介入调控。",
    actions: ["适度压减超载畜群规模", "延长冬春舍饲补饲周期", "增加人工草场补饲供应"],
  },
  {
    key: "warning",
    label: "中度超载",
    shortLabel: "预警",
    range: "10% - 20%",
    description: "超载较明显，草地退化风险上升，应启动主动调控。",
    actions: ["压减载畜量至理论承载力以内", "推行划区轮牧与阶段性休牧", "扩大优质人工饲草供给"],
  },
  {
    key: "danger",
    label: "严重超载",
    shortLabel: "高压",
    range: "> 20%",
    description: "超载压力较高，建议纳入重点管控和生态修复范围。",
    actions: ["强制压减载畜量并实施禁牧休牧", "对退化草地实施生态修复", "建立重点区域长效监测与考核机制"],
  },
]

export const fieldMap = {
  areaRange: ["areaRange", "area_range", "arearange", "acreage", "grasslandArea", "grasslandarea", "area"],
  yakNumber: ["yakNumber", "yak_number", "yaknumber", "number", "yakCount", "yakcount", "livestockCount", "livestockcount"],
  bearingCapacity: ["bearingCapacity", "bearing_capacity", "bearingcapacity", "capacity", "theoryCapacity", "theorycapacity"],
  livestockCapacity: ["livestockCapacity", "livestock_capacity", "livestockcapacity", "carryingCapacity", "carryingcapacity", "actualCapacity", "actualcapacity"],
  overloadRate: ["overloadRate", "overload_rate", "overloadrate", "rate"],
  level: ["level", "conclusion"],
  advice: ["advice", "balanceAdvice", "balance_advice", "balanceadvice", "balanceAdivce", "balance_adivce", "balanceadivce"],
  year: ["year"],
  areaName: ["areaName", "area_name", "areaname", "name"],
}

const round = (value, decimals = 2) => {
  const factor = 10 ** decimals
  return Math.round((Number(value) || 0) * factor) / factor
}

const CXPT_BALANCE_ADVICE = "加强人工饲草饲料基地建设；购买饲草饲料，增加饲草饲料供应量；实行舍饲圈养，减轻草原放牧压力；加快牲畜出栏，优化畜群结构。"

export function toNumber(value, fallback = null) {
  if (value === undefined || value === null || value === "") return fallback
  const normalized = typeof value === "string"
    ? value.replace(/,/g, "").replace(/%/g, "").trim()
    : value
  const number = Number(normalized)
  return Number.isFinite(number) ? number : fallback
}

export function pickValue(item = {}, keys = [], fallback = undefined) {
  for (const key of keys) {
    const value = item?.[key]
    if (value !== undefined && value !== null && value !== "") return value
  }
  return fallback
}

export function formatNumber(value, options = {}) {
  const number = toNumber(value)
  if (number === null) return "--"
  return number.toLocaleString("zh-CN", {
    maximumFractionDigits: options.maximumFractionDigits ?? (Number.isInteger(number) ? 0 : 2),
  })
}

export function formatPercent(value) {
  const number = toNumber(value)
  if (number === null) return "--"
  return `${formatNumber(number)}%`
}

export function getRiskLevel(value) {
  const rate = toNumber(value)
  if (rate === null || rate < 0) return RISK_LEVELS[0]
  if (rate <= 5) return RISK_LEVELS[1]
  if (rate <= 10) return RISK_LEVELS[2]
  if (rate <= 20) return RISK_LEVELS[3]
  return RISK_LEVELS[4]
}

function calculateLivestockCapacity(yakCount) {
  return Math.round(Number(yakCount) || 0)
}

function calculateBearingCapacity(areaRange) {
  return Math.round((Number(areaRange) || 0) * BALANCE_CALCULATION_PARAMS.grasslandCapacityPerMu)
}

export function buildBalanceRow({
  key,
  type,
  name,
  areaCode,
  areaRange,
  yakNumber,
  location,
  township,
  hasBoundary = false,
  boundaryCount = 0,
  grasslands = [],
  source,
  pressureFactor = 1,
}) {
  const bearingCapacity = calculateBearingCapacity(areaRange)
  const livestockCapacity = Math.round(calculateLivestockCapacity(yakNumber) * pressureFactor)
  const overloadRate = bearingCapacity ? round(((livestockCapacity - bearingCapacity) / bearingCapacity) * 100, 1) : 0
  const risk = getRiskLevel(overloadRate)
  return {
    key,
    type,
    name,
    areaCode,
    areaRange: round(areaRange, 0),
    yakNumber: round(yakNumber, 0),
    bearingCapacity,
    livestockCapacity,
    overloadRate,
    level: risk.label,
    advice: risk.actions.join("；"),
    year: "2026",
    location,
    township,
    hasBoundary: Boolean(hasBoundary),
    boundaryCount: Number(boundaryCount) || 0,
    grasslands,
    source,
  }
}

export const countyBalanceRow = {
  ...COUNTY_TARGET,
  areaRange: 7568515.06,
  yakNumber: 458230,
  bearingCapacity: 454864,
  livestockCapacity: 458230,
  overloadRate: 0.74,
  level: "基本实现草畜平衡",
  advice: CXPT_BALANCE_ADVICE,
  year: "2026",
}

export const balanceTownRows = [
  { key: "town-邛溪镇", type: "town", name: "邛溪镇", areaCode: "513233100", areaRange: 930604.2, yakNumber: 49140, bearingCapacity: 47723, livestockCapacity: 49140, overloadRate: 2.97, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-刷经寺镇", type: "town", name: "刷经寺镇", areaCode: "513233101", areaRange: 743557.5, yakNumber: 18283, bearingCapacity: 18002, livestockCapacity: 18283, overloadRate: 1.56, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-安曲镇", type: "town", name: "安曲镇", areaCode: "513233103", areaRange: 900696.75, yakNumber: 59725, bearingCapacity: 58479, livestockCapacity: 59725, overloadRate: 2.13, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-龙日镇", type: "town", name: "龙日镇", areaCode: "513233105", areaRange: 628303.8, yakNumber: 40192, bearingCapacity: 39462, livestockCapacity: 40192, overloadRate: 1.85, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-江茸乡", type: "town", name: "江茸乡", areaCode: "513233202", areaRange: 496888.95, yakNumber: 20789, bearingCapacity: 20563, livestockCapacity: 20789, overloadRate: 1.1, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-查尔玛乡", type: "town", name: "查尔玛乡", areaCode: "513233203", areaRange: 808628.4, yakNumber: 28836, bearingCapacity: 28312, livestockCapacity: 28836, overloadRate: 1.85, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-瓦切镇", type: "town", name: "瓦切镇", areaCode: "513233204", areaRange: 747837.6, yakNumber: 76127, bearingCapacity: 74598, livestockCapacity: 76127, overloadRate: 2.05, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-阿木乡", type: "town", name: "阿木乡", areaCode: "513233205", areaRange: 863346, yakNumber: 38587, bearingCapacity: 37554, livestockCapacity: 38587, overloadRate: 2.75, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-麦洼乡", type: "town", name: "麦洼乡", areaCode: "513233207", areaRange: 458338.35, yakNumber: 47193, bearingCapacity: 46643, livestockCapacity: 47193, overloadRate: 1.18, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
  { key: "town-色地镇", type: "town", name: "色地镇", areaCode: "513233208", areaRange: 991265.25, yakNumber: 79358, bearingCapacity: 77695, livestockCapacity: 79358, overloadRate: 2.14, level: "基本实现草畜平衡", advice: CXPT_BALANCE_ADVICE, year: "2026" },
]

export const balanceFallbackRows = [
  countyBalanceRow,
  ...balanceTownRows,
]

export function normalizeBalanceResult(source = {}, fallback = {}) {
  const hasSourceResult = source && typeof source === "object" && Object.keys(source).length > 0
  const rawAreaRange = pickValue(source, fieldMap.areaRange, fallback.areaRange)
  const rawYakNumber = pickValue(source, fieldMap.yakNumber, fallback.yakNumber)
  const rawBearingCapacity = pickValue(source, fieldMap.bearingCapacity, fallback.bearingCapacity)
  const rawLivestockCapacity = pickValue(source, fieldMap.livestockCapacity, fallback.livestockCapacity)
  const directRate = toNumber(pickValue(source, fieldMap.overloadRate, fallback.overloadRate))
  const fallbackYakNumber = toNumber(fallback.yakNumber)
  const legacyLivestockCapacity = getLegacyLivestockCapacity(source, rawLivestockCapacity, fallbackYakNumber)
  const areaRange = toNumber(rawAreaRange, fallback.areaRange ?? 0)
  const yakNumber = legacyLivestockCapacity !== null && rawYakNumber === source?.yak_number
    ? toNumber(pickValue(source, ["number", "yakCount", "yak_count", "livestockCount", "livestock_count"]), fallbackYakNumber ?? Math.round(legacyLivestockCapacity / BALANCE_CALCULATION_PARAMS.yakToSheepUnit))
    : toNumber(rawYakNumber, fallback.yakNumber ?? 0)
  const fallbackBearing = toNumber(fallback.bearingCapacity)
  const fallbackLivestock = toNumber(fallback.livestockCapacity)
  const sourceHasArea = rawAreaRange !== undefined && rawAreaRange !== null && rawAreaRange !== ""
  const sourceHasYakNumber = rawYakNumber !== undefined && rawYakNumber !== null && rawYakNumber !== ""
  const sourceLivestock = toNumber(rawLivestockCapacity) ?? legacyLivestockCapacity
  const sourceBearingCandidate = toNumber(rawBearingCapacity)
  const inferredSourceBearing = inferBearingCapacity(sourceLivestock, directRate)
  const sourceBearing = resolveBearingCapacity(sourceBearingCandidate, inferredSourceBearing)
  const livestockCapacity = hasSourceResult
    ? sourceLivestock
      ?? inferLivestockCapacity(sourceBearing, directRate)
      ?? fallbackLivestock
      ?? inferLivestockCapacity(fallbackBearing, directRate)
      ?? (sourceHasYakNumber ? calculateLivestockCapacity(yakNumber) : null)
    : fallbackLivestock ?? inferLivestockCapacity(fallbackBearing, directRate) ?? (sourceHasYakNumber ? calculateLivestockCapacity(yakNumber) : null)
  const bearingCapacity = hasSourceResult
    ? sourceBearing
      ?? inferBearingCapacity(livestockCapacity, directRate)
      ?? fallbackBearing
      ?? (sourceHasArea ? calculateBearingCapacity(areaRange) : null)
    : fallbackBearing ?? inferBearingCapacity(livestockCapacity, directRate) ?? (sourceHasArea ? calculateBearingCapacity(areaRange) : null)
  const overloadRate = directRate !== null
    ? round(directRate, 2)
    : bearingCapacity
      && livestockCapacity !== null
      ? round(((livestockCapacity - bearingCapacity) / bearingCapacity) * 100, 1)
      : null
  const risk = getRiskLevel(overloadRate)
  return {
    ...fallback,
    ...source,
    key: fallback.key || source.key || source.id || source.areaCode || fallback.name,
    type: fallback.type || source.type || "town",
    name: pickValue(source, fieldMap.areaName, fallback.name || "核算对象"),
    areaCode: source.areaCode || source.area_code || source.areacode || fallback.areaCode,
    areaRange,
    yakNumber,
    bearingCapacity,
    livestockCapacity,
    overloadRate,
    level: overloadRate === null ? pickValue(source, fieldMap.level, risk.label) : risk.label,
    advice: pickValue(source, fieldMap.advice, fallback.advice || risk.actions.join("；")),
    year: pickValue(source, fieldMap.year, fallback.year || "当前年度"),
    source: source.raw || source.source || fallback.source,
  }
}

function getLegacyLivestockCapacity(source = {}, rawLivestockCapacity, fallbackYakNumber = null) {
  if (!source || typeof source !== "object") return null
  if (rawLivestockCapacity !== undefined && rawLivestockCapacity !== null && rawLivestockCapacity !== "") return null
  const hasLegacyAlias = Object.prototype.hasOwnProperty.call(source, "yak_number")
  const hasBalanceMarker = ["overload_rate", "overloadRate", "overloadrate", "advice", "balanceAdvice", "balanceadvice", "level", "conclusion"]
    .some((key) => source[key] !== undefined && source[key] !== null && source[key] !== "")
  const aliasValue = toNumber(source.yak_number)
  if (!hasLegacyAlias || !hasBalanceMarker || aliasValue === null) return null
  const fallbackYak = toNumber(fallbackYakNumber)
  if (fallbackYak !== null && fallbackYak > 0) {
    return aliasValue > fallbackYak * 1.5 ? aliasValue : null
  }
  return aliasValue
}

function inferBearingCapacity(livestockCapacity, overloadRate) {
  const livestock = toNumber(livestockCapacity)
  const rate = toNumber(overloadRate)
  if (livestock === null || rate === null || rate <= -100) return null
  return Math.round(livestock / (1 + rate / 100))
}

function resolveBearingCapacity(sourceBearing, inferredBearing) {
  if (sourceBearing === null) return inferredBearing
  if (inferredBearing === null) return sourceBearing
  const diffRatio = Math.abs(sourceBearing - inferredBearing) / Math.max(Math.abs(inferredBearing), 1)
  return diffRatio > 0.25 ? inferredBearing : sourceBearing
}

function inferLivestockCapacity(bearingCapacity, overloadRate) {
  const bearing = toNumber(bearingCapacity)
  const rate = toNumber(overloadRate)
  if (bearing === null || rate === null || rate <= -100) return null
  return Math.round(bearing * (1 + rate / 100))
}

export function deriveBalance(row = {}) {
  const bearing = toNumber(row.bearingCapacity)
  const livestock = toNumber(row.livestockCapacity)
  const areaRange = toNumber(row.areaRange, 0)
  const yakNumber = toNumber(row.yakNumber, 0)
  const overloadRate = toNumber(
    row.overloadRate,
    bearing && livestock !== null ? ((livestock - bearing) / bearing) * 100 : null
  )
  const delta = bearing !== null && livestock !== null ? livestock - bearing : null
  const usageRate = bearing && livestock !== null ? round((livestock / bearing) * 100, 1) : null
  const risk = getRiskLevel(overloadRate)
  const yakSheepUnit = Math.round(yakNumber * BALANCE_CALCULATION_PARAMS.yakToSheepUnit)
  const pressureFactor = yakSheepUnit && livestock !== null ? round(livestock / yakSheepUnit, 2) : null
  const bearingCoefficient = areaRange && bearing !== null ? round(bearing / areaRange, 4) : null
  const maxCapacity = Math.max(bearing || 0, livestock || 0, 1)
  return {
    bearing,
    livestock,
    areaRange,
    yakNumber,
    yakSheepUnit,
    pressureFactor,
    bearingCoefficient,
    overloadRate: overloadRate === null ? null : round(overloadRate, 2),
    delta,
    usageRate,
    risk,
    bearingPercent: bearing === null ? 4 : Math.max(4, Math.min(100, round((bearing / maxCapacity) * 100, 1))),
    livestockPercent: livestock === null ? 4 : Math.max(4, Math.min(100, round((livestock / maxCapacity) * 100, 1))),
  }
}

export function splitAdvice(row = {}, risk = getRiskLevel(row.overloadRate)) {
  const text = String(row.advice || "").trim()
  const apiPoints = text
    ? text.split(/[。；;\n]/).map((item) => item.trim()).filter(Boolean)
    : []
  const unsuitableWhenOverloaded = ["提高放牧畜禽的密度", "增加草地的利用率", "密度不能过高"]
  const outdatedSafeAdvice = ["轻度超载", "已出现超载", "超载迹象", "压减超载畜群规模"]
  const safeRisk = ["healthy", "watch"].includes(risk.key)
  const cleanedApiPoints = apiPoints.filter((item) => {
    if (unsuitableWhenOverloaded.some((keyword) => item.includes(keyword))) return false
    if (safeRisk && outdatedSafeAdvice.some((keyword) => item.includes(keyword))) return false
    if (safeRisk) return true
    return !unsuitableWhenOverloaded.some((keyword) => item.includes(keyword))
  })
  return [...(risk.actions || []), ...cleanedApiPoints]
    .filter((item, index, array) => array.indexOf(item) === index)
    .slice(0, 4)
}
