import type { Car, CarState } from '@/types/car'
import { extractSocFromKv, normalizeSocRatio, parseSocNumber } from '@/utils/batterySoc'

type Kv = { key?: string | null; value?: string | null }

function kv(rows: Kv[] | null | undefined, ...keys: string[]): string {
  if (!rows?.length) return ''
  for (const key of keys) {
    const hit = rows.find((r) => r.key === key)
    if (hit?.value != null && hit.value !== '') return String(hit.value)
  }
  return ''
}

function isEmptyStatus(v: string): boolean {
  const s = v.trim()
  return !s || s === '/' || s === '-' || s === '[]' || s === '(0, 0)' || s === '(0,0)' || /^none$/i.test(s)
}

function compactJsonList(raw: string, maxItems = 3): string {
  if (isEmptyStatus(raw)) return ''
  try {
    const arr = JSON.parse(raw) as unknown
    if (!Array.isArray(arr) || arr.length === 0) return ''
    const items = arr.slice(0, maxItems).map((x) => {
      if (x == null) return ''
      if (typeof x === 'number' || typeof x === 'string') return String(x)
      if (typeof x === 'object') {
        const o = x as Record<string, unknown>
        if (o.siteId != null) return `#${o.siteId}`
        if (o.siteID != null) return `#${o.siteID}`
        if (o.id != null) return `#${o.id}`
        if (o.carid != null) return `车${o.carid}`
      }
      return ''
    }).filter(Boolean)
    if (!items.length) return ''
    const more = arr.length > maxItems ? `+${arr.length - maxItems}` : ''
    return items.join(',') + more
  } catch {
    return raw.length > 24 ? `${raw.slice(0, 24)}…` : raw
  }
}

/**
 * Simple3 /projection/cars 会把「正常但未初始化」「导航失联」等一律标成 fault，
 * 与地图标签/车体 AlarmLevel 不一致。这里用 lstatus + 车体 status 重新推导。
 */
export function deriveCarState(car: Pick<Car, 'state' | 'lstatus'>, statusRows?: Kv[] | null): CarState {
  const lstatus = (car.lstatus ?? '').trim()
  const alarmLevelRaw = kv(statusRows, '车体_AlarmLevel', 'AlarmLevel')
  const alarmInfo = kv(statusRows, '车体_AlarmInfo', 'AlarmInfo').trim()
  const riskAlarm = kv(statusRows, '车体_RiskPositionAlarm', 'RiskPositionAlarm')
  const drive = kv(statusRows, '车体_driveStatus', 'driveStatus')
  const openCharge = kv(statusRows, '车体_OpenChargeByClumsy', 'OpenChargeByClumsy')

  const alarmLevel = Number(alarmLevelRaw)
  const hasAlarm =
    (Number.isFinite(alarmLevel) && alarmLevel > 0) ||
    (/true/i.test(riskAlarm)) ||
    (alarmInfo.length > 0 && !isEmptyStatus(alarmInfo))

  // 明确健康：以「正常」开头（含「正常但未初始化」）→ 绝不是故障
  if (/^正常/.test(lstatus)) {
    if (/充电/.test(lstatus)) return 'charging'
    if (/暂停|挂起/.test(lstatus)) return 'paused'
    if (/离线/.test(lstatus)) return 'offline'
    if (hasAlarm) return 'fault'
    if (/charg|充电/i.test(openCharge) && /true/i.test(openCharge)) return 'charging'
    if (/Drive(Run|Move|Busy)|Running|运行/i.test(drive)) return 'running'
    if (/DriveStop|Idle|空闲|停止/i.test(drive)) return 'idle'
    // 未初始化但仍「正常」：视为空闲，而不是故障
    return 'idle'
  }

  if (/离线|失联/.test(lstatus)) return 'offline'
  if (/充电/.test(lstatus)) return 'charging'
  if (/暂停|挂起/.test(lstatus)) return 'paused'
  if (hasAlarm || (/故障|异常|检修/.test(lstatus) && !/正常/.test(lstatus))) return 'fault'
  if (/运行|工作|执行|忙/.test(lstatus)) return 'running'
  if (/空闲|待机/.test(lstatus)) return 'idle'

  // 有车体 status 时，别盲信投影里的 fault
  if (statusRows?.length) {
    if (hasAlarm) return 'fault'
    if (/Drive(Run|Move|Busy)|Running/i.test(drive)) return 'running'
    if (/DriveStop|Idle/i.test(drive)) return 'idle'
  }

  // 投影已给非 fault 时保留；fault 且无佐证则降为 idle，避免「全员故障」误报
  if (car.state && car.state !== 'fault') return car.state
  return 'idle'
}

/**
 * 与 Simple3 车体浮窗 CarVisual.FormatTrafficStatus 对齐：
 * 1) TCStat 含 BeforeLock → 互锁
 * 2) blockedBy 有车 →「被 X、Y 车阻塞」；仅非车阻塞 →「阻塞中」
 * 3) 有 holdingLocks → 正常拿锁；否则 → 畅通
 */
export function formatTrafficStatus(statusRows?: Kv[] | null): string {
  if (!statusRows?.length) return '—'

  const tc = kv(statusRows, 'TCStat')
  if (tc && /BeforeLock/i.test(tc)) return '互锁（interlock）'

  const blockedIds = parseBlockedByCarIds(kv(statusRows, 'blockedBy'))
  if (blockedIds != null) {
    return blockedIds.length > 0
      ? `被 ${blockedIds.join('、')} 车阻塞`
      : '阻塞中'
  }

  const holding = kv(statusRows, 'holdingLocks')
  if (holding && !isEmptyStatus(holding) && holding !== '[]') return '正常拿锁'
  return '畅通'
}

/** @returns null=无阻塞；[]=阻塞但无车 id；number[]=阻塞车 id */
function parseBlockedByCarIds(raw: string): number[] | null {
  if (!raw || isEmptyStatus(raw)) return null

  try {
    const arr = JSON.parse(raw) as unknown
    if (!Array.isArray(arr) || arr.length === 0) return null
    const ids = arr
      .map((item) => {
        if (item == null) return null
        if (typeof item === 'number') return item
        if (typeof item === 'object') {
          const o = item as Record<string, unknown>
          const n = Number(o.carid ?? o.Item1 ?? o.item1)
          return Number.isFinite(n) ? n : null
        }
        return null
      })
      .filter((n): n is number => n != null && n !== -1)
    return [...new Set(ids)]
  } catch {
    // 兼容 ToString 形态：[(11, 2), (12, 3)]
    const ids = [...raw.matchAll(/\(\s*(-?\d+)\s*,\s*-?\d+\s*\)/g)]
      .map((m) => Number(m[1]))
      .filter((n) => Number.isFinite(n) && n !== -1)
    if (!ids.length && /\[\s*\]/.test(raw)) return null
    if (raw.includes('(') || raw.includes('[')) return [...new Set(ids)]
    return null
  }
}

export function isTrafficCongested(status: string | undefined | null): boolean {
  return !!status && /阻塞|互锁|拥堵/.test(status)
}

export function formatLockPoint(statusRows?: Kv[] | null, fields?: { siteId?: string }): string {
  const holding = compactJsonList(kv(statusRows, 'holdingLocks'))
  if (holding) return holding
  const pending = compactJsonList(kv(statusRows, 'pendingLocks'))
  if (pending) return `待 ${pending}`

  const siteRaw = fields?.siteId || kv(statusRows, 'siteID', 'siteId')
  const siteId = Number(siteRaw)
  if (Number.isFinite(siteId) && siteId > 0) return `#${siteId}`
  return '—'
}

export function formatAlarmInfo(statusRows?: Kv[] | null, lstatus?: string): { text: string; level: number } {
  const levelRaw = Number(kv(statusRows, '车体_AlarmLevel', 'AlarmLevel'))
  const level = Number.isFinite(levelRaw) ? levelRaw : 0
  const info = kv(statusRows, '车体_AlarmInfo', 'AlarmInfo').trim()
  if (info && !isEmptyStatus(info) && info !== '0') {
    return { text: info, level: level > 0 ? level : 1 }
  }
  if (lstatus && /故障|报警|异常|失联|超时|检修/i.test(lstatus)) {
    return { text: lstatus, level: Math.max(level, 1) }
  }
  return { text: '', level }
}

export function applyRuntimeEnrichment(car: Car, statusRows?: Kv[] | null): Car {
  const socFromStatus = extractSocFromKv(statusRows)
  let batterySoc: number
  if (socFromStatus != null) {
    batterySoc = normalizeSocRatio(socFromStatus)
  } else if (statusRows != null) {
    // 已拉到 status 但无 Soc（如纯模拟车）→ 清掉投影写死的 0.8，避免假电量
    batterySoc = 0
  } else {
    batterySoc = parseSocNumber(car.batterySoc) ?? 0
  }

  const alarm = formatAlarmInfo(statusRows, car.lstatus)
  const siteRaw = kv(statusRows, 'siteID', 'siteId')
  const siteIdNum = Number(siteRaw)

  return {
    ...car,
    batterySoc,
    state: deriveCarState(car, statusRows),
    alarmInfo: alarm.text || undefined,
    alarmLevel: alarm.level || undefined,
    trafficStatus: formatTrafficStatus(statusRows),
    lockPoint: formatLockPoint(statusRows, { siteId: siteRaw }),
    siteId: Number.isFinite(siteIdNum) && siteIdNum > 0 ? siteIdNum : undefined
  }
}
