// Paleta heatmap: verde → amarillo → rojo
// INVARIANTE: estos valores DEBEN coincidir con tailwind.config.js heatmap.*
const HEATMAP_LOW = { r: 16, g: 185, b: 129 }   // #10b981
const HEATMAP_MID = { r: 245, g: 158, b: 11 }   // #f59e0b
const HEATMAP_HIGH = { r: 239, g: 68, b: 68 }   // #ef4444

export const HEATMAP_LOW_HEX = '#10b981'
export const HEATMAP_MID_HEX = '#f59e0b'
export const HEATMAP_HIGH_HEX = '#ef4444'

function lerp(a: number, b: number, t: number): number {
  return Math.round(a + (b - a) * t)
}

// t en [0, 1]
export function heatmapColor(t: number): string {
  const clamped = Math.max(0, Math.min(1, t))
  let r: number, g: number, b: number

  if (clamped <= 0.5) {
    const localT = clamped * 2
    r = lerp(HEATMAP_LOW.r, HEATMAP_MID.r, localT)
    g = lerp(HEATMAP_LOW.g, HEATMAP_MID.g, localT)
    b = lerp(HEATMAP_LOW.b, HEATMAP_MID.b, localT)
  } else {
    const localT = (clamped - 0.5) * 2
    r = lerp(HEATMAP_MID.r, HEATMAP_HIGH.r, localT)
    g = lerp(HEATMAP_MID.g, HEATMAP_HIGH.g, localT)
    b = lerp(HEATMAP_MID.b, HEATMAP_HIGH.b, localT)
  }

  return `rgb(${r}, ${g}, ${b})`
}

export function heatmapColorHex(t: number): string {
  const clamped = Math.max(0, Math.min(1, t))
  let r: number, g: number, b: number

  if (clamped <= 0.5) {
    const localT = clamped * 2
    r = lerp(HEATMAP_LOW.r, HEATMAP_MID.r, localT)
    g = lerp(HEATMAP_LOW.g, HEATMAP_MID.g, localT)
    b = lerp(HEATMAP_LOW.b, HEATMAP_MID.b, localT)
  } else {
    const localT = (clamped - 0.5) * 2
    r = lerp(HEATMAP_MID.r, HEATMAP_HIGH.r, localT)
    g = lerp(HEATMAP_MID.g, HEATMAP_HIGH.g, localT)
    b = lerp(HEATMAP_MID.b, HEATMAP_HIGH.b, localT)
  }

  return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
}

// Retorna opacidad para colores con alpha (útil para overlays sobre bpmn-js)
export function heatmapColorWithAlpha(t: number, alpha = 0.75): string {
  const clamped = Math.max(0, Math.min(1, t))
  let r: number, g: number, b: number

  if (clamped <= 0.5) {
    const localT = clamped * 2
    r = lerp(HEATMAP_LOW.r, HEATMAP_MID.r, localT)
    g = lerp(HEATMAP_LOW.g, HEATMAP_MID.g, localT)
    b = lerp(HEATMAP_LOW.b, HEATMAP_MID.b, localT)
  } else {
    const localT = (clamped - 0.5) * 2
    r = lerp(HEATMAP_MID.r, HEATMAP_HIGH.r, localT)
    g = lerp(HEATMAP_MID.g, HEATMAP_HIGH.g, localT)
    b = lerp(HEATMAP_MID.b, HEATMAP_HIGH.b, localT)
  }

  return `rgba(${r}, ${g}, ${b}, ${alpha})`
}

// Determina si el texto sobre el color debe ser claro u oscuro (WCAG contrast)
export function getContrastText(t: number): 'white' | 'black' {
  return t > 0.5 ? 'white' : 'black'
}

// ─── Helpers para el heatmap del reporte ──────────────────────────────────────

export type HeatmapMode = 'relative' | 'absolute'

export interface ActivityCostData {
  expectedTotalCost: number
  percentOfTotal: number
}

// Color neutro (gris claro) cuando no hay varianza significativa entre actividades.
// Evita comunicar una falsa diferenciación cuando todos los costos son similares.
export const NEUTRAL_HEATMAP_COLOR = '#cbd5e1' // slate-300

// Umbral: si el rango relativo (max-min)/max < 5%, la varianza no es significativa.
export const VARIANCE_THRESHOLD = 0.05

export function hasSignificantCostVariance(activities: ActivityCostData[]): boolean {
  if (activities.length < 2) return false
  const costs = activities.map((a) => a.expectedTotalCost)
  const max = Math.max(...costs)
  const min = Math.min(...costs)
  if (max <= 0) return false
  return (max - min) / max > VARIANCE_THRESHOLD
}

// Calcula t ∈ [0,1] para una actividad dada la lista completa y el modo.
// Modo relativo: normaliza sobre la actividad más costosa (t=1 = la que más pesa).
// Modo absoluto: normaliza sobre el rango min-max del proceso.
// Pre-condición: llamar solo cuando hasSignificantCostVariance = true.
export function computeActivityT(
  activity: ActivityCostData,
  allActivities: ActivityCostData[],
  mode: HeatmapMode
): number {
  if (allActivities.length === 0) return 0

  if (mode === 'relative') {
    const maxPercent = Math.max(...allActivities.map((a) => a.percentOfTotal), 0.001)
    return Math.max(0, Math.min(1, activity.percentOfTotal / maxPercent))
  }

  const costs = allActivities.map((a) => a.expectedTotalCost)
  const minCost = Math.min(...costs)
  const maxCost = Math.max(...costs)
  if (maxCost <= minCost) return 0.5
  return Math.max(0, Math.min(1, (activity.expectedTotalCost - minCost) / (maxCost - minCost)))
}

// Función unificada: devuelve el color correcto considerando varianza.
// Usar en HeatmapCanvas, ActivitiesTable y los gráficos para consistencia.
export function activityColor(
  activity: ActivityCostData,
  allActivities: ActivityCostData[],
  mode: HeatmapMode
): string {
  if (!hasSignificantCostVariance(allActivities)) return NEUTRAL_HEATMAP_COLOR
  return heatmapColorHex(computeActivityT(activity, allActivities, mode))
}

// Valores de los extremos para la leyenda del heatmap
export function heatmapLegendBounds(
  allActivities: ActivityCostData[],
  mode: HeatmapMode
): { min: number; mid: number; max: number; unit: 'currency' | 'percent' } {
  if (allActivities.length === 0) return { min: 0, mid: 50, max: 100, unit: 'percent' }

  if (mode === 'relative') {
    const maxPercent = Math.max(...allActivities.map((a) => a.percentOfTotal))
    return { min: 0, mid: maxPercent / 2, max: maxPercent, unit: 'percent' }
  }

  const costs = allActivities.map((a) => a.expectedTotalCost)
  const minCost = Math.min(...costs)
  const maxCost = Math.max(...costs)
  return { min: minCost, mid: (minCost + maxCost) / 2, max: maxCost, unit: 'currency' }
}
