import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart, PieChart } from 'echarts/charts'
import { GridComponent, TooltipComponent, LegendComponent, TitleComponent, DataZoomComponent } from 'echarts/components'
import {
  getCompletedEfficiency,
  getInProgressByNode,
  getStuckInstances,
  getOverview,
  getStatusDistribution,
  getNodeCount,
} from '@/api/analysis'
import { listEnabled } from '@/api/flow/definition'
import { listInstance } from '@/api/flow/instance'
import type { FlowInstance, FlowDefinition } from '@/types/flow'
import type {
  ProcessEfficiency,
  NodeStayStat,
  StuckInstance,
  AnalysisOverview,
  StatusDistribution,
} from '@/types/analysis'

/* eslint-disable @typescript-eslint/no-explicit-any */
use([
  CanvasRenderer,
  BarChart,
  PieChart,
  GridComponent,
  TooltipComponent,
  LegendComponent,
  TitleComponent,
  DataZoomComponent,
])

const colorPalette = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']

function formatDateTime(d: Date): string {
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}

function formatMinutes(minutes: number): string {
  if (minutes < 60) return `${minutes}分钟`
  const hours = Math.floor(minutes / 60)
  const mins = minutes % 60
  if (hours < 24) return `${hours}小时${mins ? mins + '分钟' : ''}`
  const days = Math.floor(hours / 24)
  const remHours = hours % 24
  return `${days}天${remHours ? remHours + '小时' : ''}`
}

export function useAnalysis() {
  const now = new Date()
  const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000)
  const defaultStart = formatDateTime(thirtyDaysAgo)
  const defaultEnd = formatDateTime(now)

  const dateRange = ref<[string, string]>([defaultStart, defaultEnd])
  const query = reactive({
    startTime: defaultStart as string | undefined,
    endTime: defaultEnd as string | undefined,
    processDefinitionId: undefined as number | undefined,
  })

  const definitionOptions = ref<FlowDefinition[]>([])

  const loadingOverview = ref(false)
  const overview = ref<AnalysisOverview>({
    totalInstances: 0,
    completedCount: 0,
    runningCount: 0,
    rejectedCount: 0,
    revokedCount: 0,
    timeoutCount: 0,
    timeoutRate: 0,
    avgDurationMinutes: 0,
  })

  const loadingStatus = ref(false)
  const statusList = ref<StatusDistribution[]>([])
  const statusChartOption = computed(() => buildStatusOption(statusList.value))

  const loadingEfficiency = ref(false)
  const efficiencyList = ref<ProcessEfficiency[]>([])
  const efficiencyChartOption = computed(() => buildEfficiencyOption(efficiencyList.value))

  const loadingNode = ref(false)
  const nodeList = ref<NodeStayStat[]>([])
  const nodeChartOption = computed(() => buildNodeOption(nodeList.value))

  const stuckQuery = reactive({
    nodeId: undefined as string | undefined,
    processDefinitionId: undefined as number | undefined,
    minStayMinutes: 60,
    pageNum: 1,
    pageSize: 10,
  })
  const loadingStuck = ref(false)
  const stuckList = ref<StuckInstance[]>([])
  const stuckTotal = ref(0)

  const loadingAll = ref(false)

  // 流程明细
  const instanceQuery = reactive({
    pageNum: 1,
    pageSize: 10,
    processDefinitionId: undefined as number | undefined,
    processName: '',
    applicantName: '',
    currentNodeId: '',
  })
  const instanceList = ref<FlowInstance[]>([])
  const instanceTotal = ref(0)
  const loadingInstanceList = ref(false)
  const definitionList = ref<FlowDefinition[]>([])
  const currentNodeOptions = ref<{ id: string; name: string }[]>([])

  const instanceDetailVisible = ref(false)
  const instanceDetailId = ref(0)

  // 各节点统计图
  const nodeCountData = ref<{ nodeName: string; count: number }[]>([])
  const loadingNodeCount = ref(false)
  const nodeCountOption = computed(() => ({
    tooltip: { trigger: 'axis' as const, axisPointer: { type: 'shadow' as const } },
    grid: { left: 120, right: 40, top: 10, bottom: 10 },
    xAxis: { type: 'value' as const, minInterval: 1 },
    yAxis: { type: 'category' as const, data: nodeCountData.value.map((d) => d.nodeName), inverse: true },
    series: [
      {
        type: 'bar',
        data: nodeCountData.value.map((d, i) => ({
          value: d.count,
          itemStyle: { color: colorPalette[i % colorPalette.length] },
        })),
        barMaxWidth: 30,
        label: { show: true, position: 'right' as const },
      },
    ],
  }))

  function buildStatusOption(list: StatusDistribution[]) {
    if (!list.length) return null
    return {
      color: colorPalette,
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => {
          return `${params.name}<br/>数量：${params.value} 个<br/>占比：${params.percent}%`
        },
      },
      legend: {
        bottom: 0,
        type: 'scroll',
      },
      series: [
        {
          name: '流程状态',
          type: 'pie',
          radius: ['40%', '70%'],
          center: ['50%', '45%'],
          avoidLabelOverlap: true,
          itemStyle: {
            borderRadius: 8,
            borderColor: '#fff',
            borderWidth: 2,
          },
          label: {
            formatter: '{b}: {c} ({d}%)',
          },
          data: list.map((i) => ({ name: i.statusName || `状态${i.status}`, value: i.count })),
        },
      ],
    }
  }

  function buildEfficiencyOption(list: ProcessEfficiency[]) {
    if (!list.length) return null
    return {
      color: colorPalette,
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
        formatter: (params: any[]) => {
          const p = params[0]
          const item = list[p.dataIndex]
          return `${p.name}<br/>实例数：${item.instanceCount} 个<br/>平均耗时：${formatMinutes(Math.round(item.avgDurationMinutes))}<br/>最大：${formatMinutes(item.maxDurationMinutes)}<br/>最小：${formatMinutes(item.minDurationMinutes)}`
        },
      },
      grid: { left: '3%', right: '4%', bottom: list.length > 10 ? '18%' : '3%', containLabel: true },
      dataZoom:
        list.length > 10
          ? [
              {
                type: 'slider',
                xAxisIndex: 0,
                start: 0,
                end: Math.min(100, Math.round((10 / list.length) * 100)),
                height: 20,
                bottom: 0,
              },
            ]
          : [],
      xAxis: { type: 'category', data: list.map((i) => i.processName), axisLabel: { interval: 0, rotate: 20 } },
      yAxis: { type: 'value', name: '分钟' },
      series: [
        {
          name: '平均耗时',
          type: 'bar',
          data: list.map((i) => i.avgDurationMinutes),
          barMaxWidth: 48,
          itemStyle: { color: colorPalette[0], borderRadius: [6, 6, 0, 0] },
        },
      ],
    }
  }

  function buildNodeOption(list: NodeStayStat[]) {
    if (!list.length) return null
    const top = list.slice(0, 20)
    return {
      color: colorPalette,
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
        formatter: (params: any[]) => {
          const p = params[0]
          const item = top[p.dataIndex]
          return `${item.processName || ''} / ${item.nodeName}<br/>任务数：${item.taskCount} 个<br/>平均停留：${formatMinutes(Math.round(item.avgStayMinutes))}<br/>最大停留：${formatMinutes(item.maxStayMinutes)}`
        },
      },
      grid: { left: '3%', right: '4%', bottom: top.length > 10 ? '18%' : '3%', containLabel: true },
      dataZoom:
        top.length > 10
          ? [
              {
                type: 'slider',
                xAxisIndex: 0,
                start: 0,
                end: Math.min(100, Math.round((10 / top.length) * 100)),
                height: 20,
                bottom: 0,
              },
            ]
          : [],
      xAxis: { type: 'category', data: top.map((i) => i.nodeName), axisLabel: { interval: 0, rotate: 25 } },
      yAxis: { type: 'value', name: '分钟' },
      series: [
        {
          name: '平均停留',
          type: 'bar',
          data: top.map((i) => i.avgStayMinutes),
          barMaxWidth: 48,
          itemStyle: {
            color: (p: any) => {
              const v = top[p.dataIndex].avgStayMinutes
              return v > 1440 ? '#F56C6C' : v > 240 ? '#E6A23C' : '#67C23A'
            },
            borderRadius: [6, 6, 0, 0],
          },
        },
      ],
    }
  }

  function onDateRangeChange(val: [string, string] | null) {
    if (val && val.length === 2) {
      query.startTime = val[0]
      query.endTime = val[1]
    } else {
      query.startTime = undefined
      query.endTime = undefined
    }
    loadAll()
  }

  async function loadDefinitions() {
    try {
      definitionOptions.value = await listEnabled()
      if (definitionOptions.value.length > 0 && !query.processDefinitionId) {
        const last = definitionOptions.value[definitionOptions.value.length - 1]
        query.processDefinitionId = last.id
        // 同步默认流程到明细卡片
        instanceQuery.processDefinitionId = last.id
      }
      loadCurrentNodeOptions()
    } catch {
      definitionOptions.value = []
    }
  }

  function loadCurrentNodeOptions() {
    if (!query.processDefinitionId) {
      currentNodeOptions.value = []
      return
    }
    const def = definitionOptions.value.find((d) => d.id === query.processDefinitionId)
    if (def?.flowJson) {
      try {
        currentNodeOptions.value = JSON.parse(def.flowJson)
          .nodes.filter((n: any) => n.type !== 'start' && n.type !== 'end' && n.type !== 'condition' && n.type !== 'cc')
          .map((n: any) => ({ id: n.id, name: n.name }))
      } catch {
        currentNodeOptions.value = []
      }
    } else {
      currentNodeOptions.value = []
    }
  }

  async function loadOverview() {
    loadingOverview.value = true
    try {
      overview.value = await getOverview({
        startTime: query.startTime,
        endTime: query.endTime,
        processDefinitionId: query.processDefinitionId,
      })
    } catch {
      // keep default zeros
    } finally {
      loadingOverview.value = false
    }
  }

  async function loadStatusDistribution() {
    loadingStatus.value = true
    try {
      statusList.value = await getStatusDistribution({
        startTime: query.startTime,
        endTime: query.endTime,
        processDefinitionId: query.processDefinitionId,
      })
    } finally {
      loadingStatus.value = false
    }
  }

  async function loadEfficiency() {
    loadingEfficiency.value = true
    try {
      efficiencyList.value = await getCompletedEfficiency({
        startTime: query.startTime,
        endTime: query.endTime,
        processDefinitionId: query.processDefinitionId,
      })
    } finally {
      loadingEfficiency.value = false
    }
  }

  async function loadNodes() {
    loadingNode.value = true
    try {
      nodeList.value = await getInProgressByNode(query.processDefinitionId)
    } finally {
      loadingNode.value = false
    }
  }

  async function loadStuck(pageNum = stuckQuery.pageNum) {
    loadingStuck.value = true
    stuckQuery.pageNum = pageNum
    stuckQuery.processDefinitionId = query.processDefinitionId
    try {
      const res = await getStuckInstances({
        nodeId: stuckQuery.nodeId,
        processDefinitionId: stuckQuery.processDefinitionId,
        minStayMinutes: stuckQuery.minStayMinutes,
        pageNum: stuckQuery.pageNum,
        pageSize: stuckQuery.pageSize,
      })
      stuckList.value = res.list || []
      stuckTotal.value = res.total || 0
    } finally {
      loadingStuck.value = false
    }
  }

  async function loadAll() {
    if (loadingAll.value) return
    loadingAll.value = true
    try {
      loadCurrentNodeOptions()
      await Promise.all([loadOverview(), loadStatusDistribution(), loadEfficiency(), loadNodes(), loadNodeCount()])
      await loadStuck(1)
    } finally {
      loadingAll.value = false
    }
  }

  function onNodeChartClick(params: any) {
    const idx = params?.dataIndex
    if (idx == null) return
    const node = nodeList.value[idx]
    if (!node) return
    instanceQuery.currentNodeId = node.nodeId || ''
    instanceQuery.processName = node.processName || ''
    instanceQuery.pageNum = 1
    loadInstanceList()
    ElMessage.info(`已筛选节点「${node.nodeName}」`)
  }

  function openInstanceDetail(id: number) {
    instanceDetailId.value = id
    instanceDetailVisible.value = true
  }

  function onInstanceProcessChange() {
    instanceQuery.currentNodeId = ''
    // 按名称或 ID 查找定义（StuckInstanceTable 切换时传 processName，顶栏切换时传 processDefinitionId）
    const def =
      definitionList.value.find((d) => d.name === instanceQuery.processName) ||
      definitionOptions.value.find((d) => d.name === instanceQuery.processName) ||
      definitionList.value.find((d) => d.id === instanceQuery.processDefinitionId) ||
      definitionOptions.value.find((d) => d.id === instanceQuery.processDefinitionId)
    if (def?.flowJson) {
      try {
        currentNodeOptions.value = JSON.parse(def.flowJson)
          .nodes.filter((n: any) => n.type !== 'start' && n.type !== 'end' && n.type !== 'condition' && n.type !== 'cc')
          .map((n: any) => ({ id: n.id, name: n.name }))
      } catch {
        currentNodeOptions.value = []
      }
    } else {
      loadCurrentNodeOptions()
    }
    loadInstanceList()
  }

  async function loadInstanceList() {
    loadingInstanceList.value = true
    try {
      const res = await listInstance({
        pageNum: instanceQuery.pageNum,
        pageSize: instanceQuery.pageSize,
        processDefinitionId: instanceQuery.processDefinitionId,
        definitionName: instanceQuery.processName || undefined,
        applicantName: instanceQuery.applicantName || undefined,
        currentNodeId: instanceQuery.currentNodeId || undefined,
      })
      instanceList.value = res.list
      instanceTotal.value = res.total
    } finally {
      loadingInstanceList.value = false
    }
  }

  async function loadNodeCount() {
    if (!query.processDefinitionId) {
      nodeCountData.value = []
      return
    }
    loadingNodeCount.value = true
    try {
      nodeCountData.value = await getNodeCount(query.processDefinitionId)
    } catch {
      nodeCountData.value = []
    } finally {
      loadingNodeCount.value = false
    }
  }

  async function loadDefinitionsFull() {
    try {
      definitionList.value = await listEnabled()
    } catch {
      /* ignore */
    }
  }

  onMounted(async () => {
    await loadDefinitions()
    await loadDefinitionsFull()
    loadAll()
    loadInstanceList()
  })

  return {
    // filters
    dateRange,
    query,
    definitionOptions,
    instanceQuery,

    // overview
    loadingOverview,
    overview,

    // status distribution
    loadingStatus,
    statusList,
    statusChartOption,

    // efficiency
    loadingEfficiency,
    efficiencyList,
    efficiencyChartOption,

    // node stay
    loadingNode,
    nodeList,
    nodeChartOption,

    // stuck
    stuckQuery,
    loadingStuck,
    stuckList,
    stuckTotal,

    // instance list
    instanceList,
    instanceTotal,
    loadingInstanceList,
    definitionList,
    currentNodeOptions,

    // node count
    nodeCountData,
    loadingNodeCount,
    nodeCountOption,

    // detail
    instanceDetailVisible,
    instanceDetailId,

    // loading guard
    loadingAll,

    // actions
    loadAll,
    loadInstanceList,
    loadStuck,
    loadDefinitions,
    loadOverview,
    loadStatusDistribution,
    loadEfficiency,
    loadNodes,
    loadNodeCount,
    loadDefinitionsFull,
    onDateRangeChange,
    onNodeChartClick,
    onInstanceProcessChange,
    openInstanceDetail,
    formatMinutes,
    buildStatusOption,
    buildEfficiencyOption,
    buildNodeOption,
  }
}
