import * as echarts from "echarts"
import { SCREEN2_COLORS, SCREEN2_FONT_SIZE, SCREEN2_FONTS } from "@/utils/screen2Standard"

export const chartFontFamily = SCREEN2_FONTS.ui
export const chartNumberFontFamily = SCREEN2_FONTS.number
export const chartPalette = [
  SCREEN2_COLORS.accentCyan,
  SCREEN2_COLORS.accentMint,
  SCREEN2_COLORS.accentWater,
  SCREEN2_COLORS.accentOrange,
  "#16b6e8",
  "#b9fbff",
]
export const chartTextColor = SCREEN2_COLORS.textPrimary
export const chartStrongTextColor = SCREEN2_COLORS.textStrong
export const chartSecondaryTextColor = SCREEN2_COLORS.textSecondary
export const chartAxisTextColor = SCREEN2_COLORS.textMuted
export const chartGridLineColor = SCREEN2_COLORS.chartGridLine

const chartColorReplacementMap = new Map([
  ["#ffd76c", "#8bf7ff"],
  ["#ffe06b", "#8bf7ff"],
  ["#ffcf62", "#8bf7ff"],
  ["#ffbf5a", "#8bf7ff"],
  ["#ff9a62", "#48cfff"],
  ["#ff9a5c", "#48cfff"],
  ["#ff8f6b", "#48cfff"],
  ["#ff5a64", "#8bf7ff"],
  ["#ff4054", "#30dcff"],
  ["#7ee269", "#24f6c4"],
  ["#86dc62", "#24f6c4"],
  ["#a6f06d", "#24f6c4"],
  ["#c7e86b", "#8bf7ff"],
  ["#9ea7ff", "#48cfff"],
  ["#7aa7ff", "#48cfff"],
])

export const chartTextStyle = {
  color: chartAxisTextColor,
  fontFamily: chartFontFamily,
  fontSize: SCREEN2_FONT_SIZE.chartAxis,
}

export function chartTooltip(formatter, overrides = {}) {
  return {
    trigger: "item",
    appendToBody: true,
    confine: false,
    backgroundColor: "rgba(5, 31, 51, 0.96)",
    borderColor: "rgba(0, 210, 255, 0.54)",
    borderWidth: 1,
    padding: [7, 10],
    textStyle: {
      color: chartTextColor,
      fontFamily: chartFontFamily,
      fontSize: SCREEN2_FONT_SIZE.tooltip,
      lineHeight: 18,
    },
    extraCssText: "box-shadow:0 0 10px rgba(0,210,255,.12);z-index:2147483647!important;pointer-events:none;",
    formatter,
    ...overrides,
  }
}

export function chartLegend(overrides = {}) {
  return {
    itemWidth: 10,
    itemHeight: 7,
    itemGap: 8,
    textStyle: {
      ...chartTextStyle,
      color: chartSecondaryTextColor,
      fontSize: SCREEN2_FONT_SIZE.chartAxis,
    },
    ...overrides,
  }
}

export function categoryAxis(data = [], overrides = {}) {
  return {
    type: "category",
    data,
    axisLabel: {
      ...chartTextStyle,
      color: chartAxisTextColor,
      interval: 0,
      hideOverlap: true,
      margin: 8,
      ...(overrides.axisLabel || {}),
    },
    axisLine: { lineStyle: { color: "rgba(48, 220, 255, 0.26)" }, ...(overrides.axisLine || {}) },
    axisTick: { show: false, ...(overrides.axisTick || {}) },
    splitLine: { show: false, ...(overrides.splitLine || {}) },
    ...stripAxisOverrides(overrides),
  }
}

export function valueAxis(overrides = {}) {
  return {
    type: "value",
    axisLabel: {
      ...chartTextStyle,
      color: chartAxisTextColor,
      ...(overrides.axisLabel || {}),
    },
    axisLine: { show: false, ...(overrides.axisLine || {}) },
    axisTick: { show: false, ...(overrides.axisTick || {}) },
    splitLine: {
      lineStyle: { color: chartGridLineColor, type: "dashed" },
      ...(overrides.splitLine || {}),
    },
    ...stripAxisOverrides(overrides),
  }
}

export function chartGrid(overrides = {}) {
  return {
    left: 42,
    right: 28,
    top: 30,
    bottom: 24,
    containLabel: false,
    ...overrides,
  }
}

export function verticalGradient(color, endColor = `${color}12`) {
  return new echarts.graphic.LinearGradient(0, 0, 0, 1, [
    { offset: 0, color },
    { offset: 1, color: endColor },
  ])
}

export function systemBarGradient(color = chartPalette[0]) {
  return new echarts.graphic.LinearGradient(0, 0, 0, 1, [
    { offset: 0, color: "rgba(255,255,255,0.96)" },
    { offset: 0.16, color },
    { offset: 0.72, color: `${color}a3` },
    { offset: 1, color: `${color}14` },
  ])
}

export function horizontalGradient(color, startColor = `${color}20`, endColor = "#ffffff") {
  return new echarts.graphic.LinearGradient(0, 0, 1, 0, [
    { offset: 0, color: startColor },
    { offset: 0.68, color },
    { offset: 1, color: endColor },
  ])
}

export function withChartDefaults(option = {}) {
  const normalized = {
    textStyle: {
      fontFamily: chartFontFamily,
      color: chartAxisTextColor,
      ...(option.textStyle || {}),
    },
    animation: option.animation ?? true,
    animationDuration: option.animationDuration ?? 900,
    animationDurationUpdate: option.animationDurationUpdate ?? 700,
    animationEasing: option.animationEasing || "cubicOut",
    ...option,
  }
  normalizeChartColors(normalized)
  normalizeChartTypography(normalized)
  return normalized
}

export function createSystemBarOption({
  categories = [],
  rows = [],
  unit = "",
  name = "指标",
  orientation = "vertical",
  colorIndex = 0,
  grid = {},
  showLabel = true,
} = {}) {
  const horizontal = orientation === "horizontal"
  const data = rows.map((item, index) => ({
    name: item.name || categories[index],
    value: Number(item.value) || 0,
    itemStyle: {
      borderRadius: horizontal ? [0, 6, 6, 0] : [7, 7, 1, 1],
      color: horizontal
        ? horizontalGradient(chartPalette[(colorIndex + index) % chartPalette.length], "rgba(48, 220, 255, 0.1)", chartPalette[(colorIndex + index) % chartPalette.length])
        : systemBarGradient(chartPalette[(colorIndex + index) % chartPalette.length]),
    },
  }))

  return withChartDefaults({
    color: chartPalette,
    grid: chartGrid(horizontal ? { left: 72, right: showLabel ? 58 : 26, top: 24, bottom: 22, ...grid } : { left: 46, right: 24, top: 28, bottom: 42, ...grid }),
    tooltip: chartTooltip((params) => `${params.marker}${params.name}：${formatChartValue(params.value)}${unit}`),
    xAxis: horizontal ? valueAxis() : categoryAxis(categories, { axisLabel: { rotate: categories.length > 6 ? 24 : 0 } }),
    yAxis: horizontal ? categoryAxis(categories, { inverse: true, axisLabel: { color: chartTextColor, fontWeight: 700 } }) : valueAxis(),
    series: [
      {
        name,
        type: "bar",
        barWidth: horizontal ? 8 : categories.length > 7 ? 6 : 8,
        data,
        label: {
          show: showLabel,
          position: horizontal ? "right" : "top",
          color: chartStrongTextColor,
          fontFamily: chartNumberFontFamily,
          fontSize: SCREEN2_FONT_SIZE.chartLabel,
          fontWeight: 700,
          formatter: ({ value }) => formatChartValue(value),
        },
      },
    ],
  })
}

export function createSystemGroupedBarOption({ categories = [], series = [], unit = "", grid = {} } = {}) {
  return withChartDefaults({
    color: chartPalette,
    grid: chartGrid({ left: 46, right: 20, top: 42, bottom: 42, ...grid }),
    tooltip: chartTooltip((params) => formatAxisTooltip(params, unit), { trigger: "axis", axisPointer: { type: "shadow" } }),
    legend: chartLegend({ top: 0, right: 4 }),
    xAxis: categoryAxis(categories),
    yAxis: valueAxis(),
    series: series.map((item, index) => ({
      name: item.name,
      type: "bar",
      barWidth: categories.length > 7 ? 6 : 8,
      data: item.values || [],
      itemStyle: {
        borderRadius: [7, 7, 1, 1],
        color: systemBarGradient(chartPalette[index % chartPalette.length]),
      },
    })),
  })
}

export function createSystemStackedBarOption({ categories = [], series = [], unit = "", grid = {} } = {}) {
  return withChartDefaults({
    color: chartPalette,
    grid: chartGrid({ left: 48, right: 22, top: 42, bottom: 42, ...grid }),
    tooltip: chartTooltip((params) => formatAxisTooltip(params, unit), { trigger: "axis", axisPointer: { type: "shadow" } }),
    legend: chartLegend({ top: 0, right: 4 }),
    xAxis: categoryAxis(categories),
    yAxis: valueAxis(),
    series: series.map((item, index) => ({
      name: item.name,
      type: "bar",
      stack: "total",
      barWidth: categories.length > 7 ? 6 : 8,
      data: item.values || [],
      itemStyle: {
        color: systemBarGradient(chartPalette[index % chartPalette.length]),
      },
    })),
  })
}

export function createSystemLineOption({ categories = [], series = [], unit = "", area = false, grid = {} } = {}) {
  return withChartDefaults({
    color: chartPalette,
    grid: chartGrid({ left: 46, right: 24, top: 42, bottom: 38, ...grid }),
    tooltip: chartTooltip((params) => formatAxisTooltip(params, unit), {
      trigger: "axis",
      axisPointer: {
        type: "line",
        lineStyle: { color: "rgba(139, 247, 255, 0.42)" },
      },
    }),
    legend: chartLegend({ top: 0, right: 4 }),
    xAxis: categoryAxis(categories),
    yAxis: valueAxis(),
    series: series.map((item, index) => {
      const color = chartPalette[index % chartPalette.length]
      return {
        name: item.name,
        type: "line",
        smooth: true,
        symbol: "circle",
        symbolSize: 5,
        data: item.values || [],
        lineStyle: {
          width: 1.6,
          color,
          shadowColor: `${color}22`,
          shadowBlur: 1,
        },
        itemStyle: {
          color: "#041522",
          borderColor: color,
          borderWidth: 1,
        },
        areaStyle: area
          ? {
              color: verticalGradient(color, `${color}08`),
            }
          : undefined,
      }
    }),
  })
}

export function createSystemPieOption({ rows = [], unit = "", name = "结构占比", rose = false, donut = true } = {}) {
  return withChartDefaults({
    color: chartPalette,
    tooltip: chartTooltip((params) => `${params.marker}${params.name}：${formatChartValue(params.value)}${unit}<br/>占比：${formatChartValue(params.percent)}%`),
    legend: chartLegend({
      orient: "vertical",
      right: 6,
      top: "middle",
      itemWidth: 9,
      itemHeight: 9,
    }),
    series: [
      {
        name,
        type: "pie",
        radius: donut ? ["45%", rose ? "74%" : "66%"] : rose ? [12, "72%"] : "64%",
        center: ["36%", "52%"],
        roseType: rose ? "radius" : undefined,
        avoidLabelOverlap: true,
        itemStyle: {
          borderColor: "rgba(3, 18, 31, 0.94)",
          borderWidth: 3,
        },
        label: {
          color: "#f7feff",
          fontSize: 10,
          formatter: "{b}\n{d}%",
        },
        labelLine: {
          length: 8,
          length2: 8,
          lineStyle: { color: "rgba(223, 250, 255, 0.42)" },
        },
        data: rows.map((row, index) => ({
          name: row.name,
          value: Number(row.value) || 0,
          itemStyle: { color: chartPalette[index % chartPalette.length] },
        })),
      },
    ],
  })
}

export function createSystemRadarOption({ indicators = [], rows = [], name = "综合评价" } = {}) {
  return withChartDefaults({
    color: chartPalette,
    tooltip: chartTooltip(),
    legend: chartLegend({ top: 0, right: 4 }),
    radar: {
      center: ["50%", "58%"],
      radius: "62%",
      indicator: indicators,
      splitNumber: 4,
      axisName: {
        color: chartAxisTextColor,
        fontSize: SCREEN2_FONT_SIZE.chartAxis,
      },
      axisLine: { lineStyle: { color: "rgba(48, 220, 255, 0.18)" } },
      splitLine: { lineStyle: { color: chartGridLineColor } },
      splitArea: {
        areaStyle: {
          color: ["rgba(48, 220, 255, 0.04)", "rgba(36, 246, 196, 0.02)"],
        },
      },
    },
    series: [
      {
        name,
        type: "radar",
        data: rows.map((row, index) => ({
          name: row.name,
          value: row.values || [],
          areaStyle: { color: `${chartPalette[index % chartPalette.length]}24` },
          lineStyle: { color: chartPalette[index % chartPalette.length], width: 2 },
          itemStyle: { color: chartPalette[index % chartPalette.length] },
        })),
      },
    ],
  })
}

export function formatChartValue(value) {
  const number = Number(value)
  if (!Number.isFinite(number)) return "--"
  return Number.isInteger(number) ? number.toLocaleString("zh-CN") : number.toLocaleString("zh-CN", { maximumFractionDigits: 2 })
}

function stripAxisOverrides(overrides = {}) {
  const { axisLabel, axisLine, axisTick, splitLine, ...rest } = overrides
  return rest
}

function formatAxisTooltip(params, unit = "") {
  const rows = Array.isArray(params) ? params : [params]
  const title = rows[0]?.axisValueLabel || rows[0]?.name || ""
  const body = rows
    .map((item) => `${item.marker}${item.seriesName || item.name}：${formatChartValue(item.value)}${unit}`)
    .join("<br/>")
  return `${title}<br/>${body}`
}

function normalizeChartTypography(target) {
  if (!target || typeof target !== "object") return
  const styleKeys = ["textStyle", "axisLabel", "nameTextStyle", "label", "axisName"]
  styleKeys.forEach((key) => {
    if (!target[key] || typeof target[key] !== "object") return
    target[key] = normalizeTextObject(target[key])
  })
  Object.keys(target).forEach((key) => {
    const value = target[key]
    if (!value || typeof value !== "object") return
    if (key === "color" || key === "itemStyle" || key === "areaStyle" || key === "lineStyle") return
    if (Array.isArray(value)) {
      value.forEach(normalizeChartTypography)
      return
    }
    normalizeChartTypography(value)
  })
}

function normalizeChartColors(target) {
  if (!target || typeof target !== "object") return
  Object.keys(target).forEach((key) => {
    const value = target[key]
    if (typeof value === "string") {
      target[key] = normalizeChartColorString(value)
      return
    }
    if (Array.isArray(value)) {
      value.forEach((item, index) => {
        if (typeof item === "string") {
          value[index] = normalizeChartColorString(item)
        } else {
          normalizeChartColors(item)
        }
      })
      return
    }
    if (value && typeof value === "object") {
      normalizeChartColors(value)
    }
  })
}

function normalizeChartColorString(value) {
  let next = value
  chartColorReplacementMap.forEach((targetColor, sourceColor) => {
    next = next.replace(new RegExp(sourceColor, "gi"), targetColor)
  })
  next = next
    .replace(/rgba\(\s*255\s*,\s*215\s*,\s*108\s*,\s*([^)]+)\)/gi, "rgba(139, 247, 255, $1)")
    .replace(/rgba\(\s*255\s*,\s*224\s*,\s*107\s*,\s*([^)]+)\)/gi, "rgba(139, 247, 255, $1)")
    .replace(/rgba\(\s*255\s*,\s*154\s*,\s*98\s*,\s*([^)]+)\)/gi, "rgba(72, 207, 255, $1)")
    .replace(/rgba\(\s*255\s*,\s*143\s*,\s*107\s*,\s*([^)]+)\)/gi, "rgba(72, 207, 255, $1)")
    .replace(/rgba\(\s*126\s*,\s*226\s*,\s*105\s*,\s*([^)]+)\)/gi, "rgba(36, 246, 196, $1)")
    .replace(/rgba\(\s*134\s*,\s*220\s*,\s*98\s*,\s*([^)]+)\)/gi, "rgba(36, 246, 196, $1)")
    .replace(/rgba\(\s*166\s*,\s*240\s*,\s*109\s*,\s*([^)]+)\)/gi, "rgba(36, 246, 196, $1)")
    .replace(/rgba\(\s*158\s*,\s*167\s*,\s*255\s*,\s*([^)]+)\)/gi, "rgba(72, 207, 255, $1)")
    .replace(/rgba\(\s*122\s*,\s*167\s*,\s*255\s*,\s*([^)]+)\)/gi, "rgba(72, 207, 255, $1)")
    .replace(/rgba\(\s*255\s*,\s*64\s*,\s*84\s*,\s*([^)]+)\)/gi, "rgba(48, 220, 255, $1)")
    .replace(/rgba\(\s*255\s*,\s*90\s*,\s*100\s*,\s*([^)]+)\)/gi, "rgba(139, 247, 255, $1)")
  return next
}

function normalizeTextObject(style) {
  const next = {
    fontFamily: style.fontFamily || chartFontFamily,
    ...style,
  }
  next.color = normalizeChartTextColor(next.color)
  if (typeof next.fontSize === "number" && next.fontSize < 10) {
    next.fontSize = 10
  }
  return next
}

function normalizeChartTextColor(color) {
  if (typeof color !== "string") return color
  const rgbaMatch = color.match(/^rgba\(\s*(22[0-9]|23[0-9]|24[0-9]|25[0-5])\s*,\s*(24[0-9]|25[0-5])\s*,\s*(24[0-9]|25[0-5])\s*,\s*([0-9.]+)\s*\)$/i)
  if (!rgbaMatch) return color
  const alpha = Number(rgbaMatch[4])
  if (!Number.isFinite(alpha) || alpha >= 0.72) return color
  return alpha < 0.6 ? chartAxisTextColor : chartSecondaryTextColor
}
