export interface TelemetryConfig {
  heartRateAge: number
  restingHeartRateBpm: number
  userWeightKg: number
}

export type HeartRateTone = 'blue' | 'purple' | 'green' | 'yellow' | 'orange' | 'red'

type HeartRateToneMeta = {
  label: string
  heartRateRangeText: string
  speedRangeText: string
}

const HEART_RATE_TONE_META: Record<HeartRateTone, HeartRateToneMeta> = {
  blue: {
    label: '激活放松',
    heartRateRangeText: '<=39%',
    speedRangeText: '<3.2 km/h',
  },
  purple: {
    label: '动态热身',
    heartRateRangeText: '40~54%',
    speedRangeText: '3.2~4.0 km/h',
  },
  green: {
    label: '脂肪燃烧',
    heartRateRangeText: '55~69%',
    speedRangeText: '4.1~5.5 km/h',
  },
  yellow: {
    label: '糖分消耗',
    heartRateRangeText: '70~79%',
    speedRangeText: '5.6~7.1 km/h',
  },
  orange: {
    label: '心肺训练',
    heartRateRangeText: '80~89%',
    speedRangeText: '7.2~8.8 km/h',
  },
  red: {
    label: '峰值锻炼',
    heartRateRangeText: '>=90%',
    speedRangeText: '>=8.9 km/h',
  },
}

export function clampTelemetryAge(age: number): number {
  if (!Number.isFinite(age)) {
    return 30
  }

  return Math.max(10, Math.min(85, Math.round(age)))
}

export function estimateRestingHeartRateBpm(age: number): number {
  const safeAge = clampTelemetryAge(age)
  const estimated = 68 + (safeAge - 30) * 0.12
  return Math.max(56, Math.min(76, Math.round(estimated)))
}

export function normalizeRestingHeartRateBpm(restingHeartRateBpm: number, age: number): number {
  if (!Number.isFinite(restingHeartRateBpm) || restingHeartRateBpm <= 0) {
    return estimateRestingHeartRateBpm(age)
  }

  return Math.max(40, Math.min(95, Math.round(restingHeartRateBpm)))
}

export function normalizeUserWeightKg(userWeightKg: number): number {
  if (!Number.isFinite(userWeightKg) || userWeightKg <= 0) {
    return 65
  }

  return Math.max(35, Math.min(180, Math.round(userWeightKg)))
}

export const DEFAULT_TELEMETRY_CONFIG: TelemetryConfig = {
  heartRateAge: 30,
  restingHeartRateBpm: estimateRestingHeartRateBpm(30),
  userWeightKg: 65,
}

export function mergeTelemetryConfig(overrides?: Partial<TelemetryConfig> | null): TelemetryConfig {
  const heartRateAge = overrides && overrides.heartRateAge !== undefined
    ? clampTelemetryAge(overrides.heartRateAge)
    : DEFAULT_TELEMETRY_CONFIG.heartRateAge

  const restingHeartRateBpm = overrides && overrides.restingHeartRateBpm !== undefined
    ? normalizeRestingHeartRateBpm(overrides.restingHeartRateBpm, heartRateAge)
    : estimateRestingHeartRateBpm(heartRateAge)
  const userWeightKg = overrides && overrides.userWeightKg !== undefined
    ? normalizeUserWeightKg(overrides.userWeightKg)
    : DEFAULT_TELEMETRY_CONFIG.userWeightKg

  return {
    heartRateAge,
    restingHeartRateBpm,
    userWeightKg,
  }
}

export function getHeartRateToneSampleBpm(tone: HeartRateTone, config: TelemetryConfig): number {
  const maxHeartRate = Math.max(120, 220 - config.heartRateAge)
  const restingHeartRate = Math.min(maxHeartRate - 15, config.restingHeartRateBpm)
  const reserve = Math.max(20, maxHeartRate - restingHeartRate)

  if (tone === 'blue') {
    return Math.round(restingHeartRate + reserve * 0.3)
  }

  if (tone === 'purple') {
    return Math.round(restingHeartRate + reserve * 0.47)
  }

  if (tone === 'green') {
    return Math.round(restingHeartRate + reserve * 0.62)
  }

  if (tone === 'yellow') {
    return Math.round(restingHeartRate + reserve * 0.745)
  }

  if (tone === 'orange') {
    return Math.round(restingHeartRate + reserve * 0.845)
  }

  return Math.round(restingHeartRate + reserve * 0.93)
}

export function getHeartRateToneLabel(tone: HeartRateTone): string {
  return HEART_RATE_TONE_META[tone].label
}

export function getHeartRateToneRangeText(tone: HeartRateTone): string {
  return HEART_RATE_TONE_META[tone].heartRateRangeText
}

export function getSpeedToneRangeText(tone: HeartRateTone): string {
  return HEART_RATE_TONE_META[tone].speedRangeText
}
