import {
  AbstractMesh,
  HighlightLayer,
  Mesh,
  InstancedMesh,
  Color3,
} from '@babylonjs/core'
import * as statusColors from '../../lib/statusColors'

export const SENSOR_HIGHLIGHT_COLOR = new Color3(1, 1, 0)

const CRITICAL_COLOR3 = Color3.FromHexString(statusColors.STATUS_COLOR_CRITICAL)
const WARNING_COLOR3 = Color3.FromHexString(statusColors.STATUS_COLOR_WARNING)
const NORMAL_COLOR3 = Color3.FromHexString(statusColors.STATUS_COLOR_NORMAL)

export const statusToColor3 = (status?: string | null): Color3 => {
  if (!status) return SENSOR_HIGHLIGHT_COLOR
  const lower = status.toLowerCase()
  if (lower === 'critical') {
    return CRITICAL_COLOR3
  }
  if (lower === 'warning') {
    return WARNING_COLOR3
  }
  if (lower === 'info' || lower === 'normal' || lower === 'ok') {
    return NORMAL_COLOR3
  }
  if (status === statusColors.STATUS_COLOR_CRITICAL) return CRITICAL_COLOR3
  if (status === statusColors.STATUS_COLOR_WARNING) return WARNING_COLOR3
  if (status === statusColors.STATUS_COLOR_NORMAL) return NORMAL_COLOR3
  return SENSOR_HIGHLIGHT_COLOR
}

export const getSensorIdFromMesh = (m: AbstractMesh | null): string | null => {
  if (!m) return null
  try {
    const meta: any = (m as any)?.metadata
    const extras: any = meta?.gltf?.extras ?? meta?.extras ?? (m as any)?.extras
    const sid =
      extras?.Sensor_ID ??
      extras?.sensor_id ??
      extras?.SERIAL_NUMBER ??
      extras?.serial_number ??
      extras?.detector_id
    if (sid != null) return String(sid).trim()
    const monitoringSensorInstance = extras?.bonsaiPset_ARBM_PSet_MonitoringSensor_Instance
    if (monitoringSensorInstance && typeof monitoringSensorInstance === 'string') {
      try {
        const parsedInstance = JSON.parse(monitoringSensorInstance)
        const instanceSensorId = parsedInstance?.Sensor_ID
        if (instanceSensorId != null) return String(instanceSensorId).trim()
      } catch {
        return null
      }
    }
  } catch {
    return null
  }
  return null
}

export const collectSensorMeshes = (meshes: AbstractMesh[]): AbstractMesh[] => {
  const result: AbstractMesh[] = []
  for (const m of meshes) {
    const sid = getSensorIdFromMesh(m)
    if (sid) result.push(m)
  }
  return result
}

export const applyHighlightToMeshes = (
  layer: HighlightLayer | null,
  highlightedRef: { current: AbstractMesh[] },
  meshesToHighlight: AbstractMesh[],
  getColor?: (mesh: AbstractMesh) => Color3 | null,
) => {
  if (!layer) return
  for (const m of highlightedRef.current) {
    m.renderingGroupId = 0
  }
  highlightedRef.current = []
  layer.removeAllMeshes()

  meshesToHighlight.forEach(mesh => {
    const color = getColor ? getColor(mesh) ?? SENSOR_HIGHLIGHT_COLOR : SENSOR_HIGHLIGHT_COLOR
    if (mesh instanceof Mesh) {
      mesh.renderingGroupId = 1
      highlightedRef.current.push(mesh)
      layer.addMesh(mesh, color)
    } else if (mesh instanceof InstancedMesh) {
      mesh.sourceMesh.renderingGroupId = 1
      highlightedRef.current.push(mesh.sourceMesh)
      layer.addMesh(mesh.sourceMesh, color)
    }
  })
}
