import { normalizeResponseData, requestJson } from "./request"

const JSY_API_BASE = import.meta.env.VITE_JSY_API_BASE || "/jsyApi"
const HONGYUAN_TOWN_NAMES = [
  "邛溪镇",
  "刷经寺镇",
  "安曲镇",
  "龙日镇",
  "江茸乡",
  "查尔玛乡",
  "瓦切镇",
  "阿木乡",
  "麦洼乡",
  "色地镇",
]
function joinBase(path) {
  if (/^https?:\/\//.test(path)) return path
  return `${JSY_API_BASE}${path.startsWith("/") ? path : `/${path}`}`
}

function unwrapResponse(response) {
  const failed =
    response?.success === false ||
    (response?.code !== undefined && ![0, 200, "0", "200"].includes(response.code))

  if (failed) {
    const error = new Error(response?.msg || response?.message || "视频监控接口请求失败")
    error.code = response?.code
    throw error
  }

  return normalizeResponseData(response)
}

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

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

function getMonitoringToken(row) {
  return pickValue(row, ["token", "accessToken", "access_token"])
}

function getMonitoringPlayUrl(row) {
  return pickValue(row, ["hdPlayUrl", "hd_play_url", "playUrl", "play_url", "url"])
}

function hasMonitoringStream(row) {
  return Boolean(getMonitoringToken(row) && getMonitoringPlayUrl(row))
}

function getMonitoringStatusEntry(row) {
  return pickEntry(row, [
    "isOnline",
    "is_online",
    "online",
    "onlineStatus",
    "online_status",
    "statusName",
    "status_name",
    "deviceStatus",
    "device_status",
    "cameraStatus",
    "camera_status",
    "rawStatus",
    "raw_status",
    "status",
    "state",
    "deviceState",
    "device_state",
  ])
}

function getMonitoringStatusInfo(row) {
  const hasStream = hasMonitoringStream(row)
  const entry = getMonitoringStatusEntry(row)
  if (!entry) {
    return {
      online: hasStream,
      raw: "",
      reason: hasStream ? "后台未返回设备状态" : "缺少播放地址或令牌",
    }
  }

  const value = entry.value
  if (typeof value === "boolean") {
    return {
      online: value,
      raw: value ? "在线" : "离线",
      reason: `后台状态：${value ? "在线" : "离线"}`,
    }
  }

  const text = String(value ?? "").trim().toLowerCase()
  if (!text) {
    return {
      online: hasStream,
      raw: "",
      reason: hasStream ? "后台状态为空" : "缺少播放地址或令牌",
    }
  }

  if (typeof value === "number" || /^-?\d+(\.\d+)?$/.test(text)) {
    const online = Number(value) !== 0
    return {
      online,
      raw: String(value),
      reason: `后台状态：${value}`,
    }
  }

  if (["true", "online", "on", "open", "running", "active", "enabled"].includes(text)) {
    return { online: true, raw: String(value), reason: `后台状态：${value}` }
  }
  if (["false", "offline", "off", "closed", "disabled", "stop", "stopped"].includes(text)) {
    return { online: false, raw: String(value), reason: `后台状态：${value}` }
  }
  if (/(离线|不在线|未在线|断线|断开|异常|故障|停用|不可用|offline|disabled|closed|stop)/i.test(text)) {
    return { online: false, raw: String(value), reason: `后台状态：${value}` }
  }
  if (/(在线|直播中|正常|启用|可用|online|enabled|open|running|active)/i.test(text)) {
    return { online: true, raw: String(value), reason: `后台状态：${value}` }
  }
  return {
    online: hasStream,
    raw: String(value),
    reason: `后台状态：${value}`,
  }
}

function isMonitoringOnline(row) {
  return getMonitoringStatusInfo(row).online
}

function getMonitoringImage(row) {
  return pickValue(row, [
    "previewImgUrl",
    "preview_img_url",
    "latestCaptureUrl",
    "latest_capture_url",
    "img",
    "image",
    "cover",
    "snapshot",
  ])
}

function getMonitoringLastCaptureTime(row) {
  return pickValue(row, [
    "lastCaptureTime",
    "last_capture_time",
    "captureTime",
    "capture_time",
    "latestCaptureTime",
    "latest_capture_time",
  ])
}

export function isPlayableMonitoring(row) {
  return Boolean(hasMonitoringStream(row) && isMonitoringOnline(row))
}

function inferTownName(name = "") {
  const normalizedName = String(name)
  const town = HONGYUAN_TOWN_NAMES.find((item) => normalizedName.includes(item.replace(/[镇乡]$/, "")))
  return town || "红原县"
}

function inferSceneName(name = "") {
  const text = String(name)
  if (text.includes("养殖")) return "养殖基地"
  if (text.includes("饲草")) return "饲草基地"
  if (text.includes("种草") || text.includes("牧草")) return "牧草基地"
  if (text.includes("虫情")) return "虫情监测"
  if (text.includes("机场")) return "机场周边"
  return "重点点位"
}

function getChannel(row, index) {
  const url = pickValue(row, ["hdPlayUrl", "playUrl", "url"])
  const match = String(url).match(/\/(\d+)(?:\.hd)?\.live/i)
  if (match) return match[1].padStart(2, "0")
  return String(index + 1).padStart(2, "0")
}

function getUpdateTime() {
  return new Date().toLocaleTimeString("zh-CN", {
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
  })
}

function normalizeMonitoring(row, index, total, validTotal) {
  const name = pickValue(row, ["name", "title", "deviceName"], `视频监控${index + 1}`)
  const hdPlayUrl = pickValue(row, ["hdPlayUrl", "hd_play_url", "url"])
  const playUrl = pickValue(row, ["playUrl", "play_url"], hdPlayUrl)
  const token = getMonitoringToken(row)
  const statusInfo = getMonitoringStatusInfo(row)
  const isOnline = Boolean(hasMonitoringStream(row) && statusInfo.online)
  const onlineRate = total ? Math.round((validTotal / total) * 100) : 0

  return {
    key: pickValue(row, ["id", "number", "deviceSerial"], `${name}-${index}`),
    title: name,
    town: inferTownName(name),
    scene: inferSceneName(name),
    device: pickValue(row, ["number", "deviceSerial", "serialNumber"], `CAM-${String(index + 1).padStart(3, "0")}`),
    channel: getChannel(row, index),
    cameraCount: total,
    status: isOnline ? "直播中" : "离线",
    rawStatus: statusInfo.raw,
    statusReason: statusInfo.reason,
    onlineRate,
    updateTime: getUpdateTime(),
    operator: isOnline ? "萤石云 · 在线预览" : statusInfo.reason,
    progress: isOnline ? 100 : 0,
    image: getMonitoringImage(row),
    lastCaptureTime: getMonitoringLastCaptureTime(row),
    playUrl,
    hdPlayUrl,
    token,
    source: row,
  }
}

export async function getHomeMonitorings(params = {}) {
  const { includeOffline = false, ...requestParams } = params
  const data = await requestJson(joinBase("/api/home/monitorings"), {
    params: requestParams,
    timeout: 18000,
  }).then(unwrapResponse)
  const rows = Array.isArray(data) ? data : data?.rows || data?.list || []
  const playableRows = rows.filter(isPlayableMonitoring)
  const normalizedRows = rows.map((row, index) => normalizeMonitoring(row, index, rows.length, playableRows.length))
  if (!includeOffline) return normalizedRows.filter((row) => row.status === "直播中")
  return normalizedRows.sort((a, b) => Number(b.status === "直播中") - Number(a.status === "直播中"))
}
