<script setup lang="ts">
import { IotRyDailyReportApi } from '@/api/pms/iotrydailyreport'
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
import { useDebounceFn } from '@vueuse/core'
import * as echarts from 'echarts'

interface Query {
  pageNo: number
  pageSize: number
  deptId: number
  contractName?: string
  taskName?: string
  createTime: string[]
  projectClassification: 2
}

const props = defineProps<{
  query: Query
  deptName: string
  refreshKey: number
}>()

interface ListItem {
  id?: number | null
  name?: string | null
  type?: string
  teamId?: number
  projectDeptId?: number
  teamName?: string
  projectDeptName?: string
  accidentTime: number
  repairTime: number
  selfStopTime: number
  complexityTime: number
  relocationTime: number
  rectificationTime: number
  waitingStopTime: number
  winterBreakTime: number
  partyaDesign: number
  partyaPrepare: number
  partyaResource: number
  otherNptTime: number
  nptTotal: number
  nptRate: number
  calendarTime: number
}

const list = ref<ListItem[]>([])
const loading = ref(false)
const tab = ref<'表格' | '看板'>('表格')
const chartRef = ref<HTMLDivElement | null>(null)
let chart: echarts.ECharts | null = null
const router = useRouter()

const nonProductionTimeFields: [keyof ListItem, string][] = [
  ['accidentTime', '工程质量(H)'],
  ['repairTime', '设备故障(H)'],
  ['selfStopTime', '设备保养(H)'],
  ['complexityTime', '技术受限(H)'],
  ['relocationTime', '生产配合(H)'],
  ['rectificationTime', '生产组织(H)'],
  ['waitingStopTime', '不可抗力(H)'],
  ['winterBreakTime', '待命(H)'],
  ['partyaDesign', '甲方设计(H)'],
  ['partyaPrepare', '甲方准备(H)'],
  ['partyaResource', '甲方资源(H)'],
  ['otherNptTime', '其它(H)']
]

const getQueryWithoutPage = () => {
  const { pageNo: _pageNo, pageSize: _pageSize, ...query } = props.query

  void _pageNo
  void _pageSize

  return {
    ...query,
    projectClassification: 2
  }
}

const normalizeListData = (data: any) => {
  const rows = Array.isArray(data) ? data : data?.list || data?.records || []

  return rows.map(({ projectDeptId, projectDeptName, teamId, teamName, type, ...other }) => ({
    ...other,
    type,
    projectDeptId,
    projectDeptName,
    teamId,
    teamName,
    id: type === '2' ? projectDeptId : teamId,
    name: type === '2' ? projectDeptName : teamName
  }))
}

const loadList = useDebounceFn(async function () {
  loading.value = true
  try {
    const data = await IotRyDailyReportApi.nptStatistics(getQueryWithoutPage())

    list.value = normalizeListData(data)
    if (tab.value === '看板') {
      nextTick(renderChart)
    }
  } finally {
    loading.value = false
  }
}, 500)

function handleQuery() {
  loadList()
}

watch(
  () => [
    props.refreshKey,
    props.query.deptId,
    props.query.contractName,
    props.query.taskName,
    props.query.createTime?.[0],
    props.query.createTime?.[1],
    props.query.projectClassification
  ],
  () => {
    handleQuery()
  },
  { immediate: true }
)

const handleSelectTab = (val: '表格' | '看板') => {
  tab.value = val

  if (val === '看板') {
    nextTick(renderChart)
  } else {
    chart?.dispose()
    chart = null
  }
}

const formatNumber = (value: unknown) => {
  const num = Number(value || 0)
  return Number.isInteger(num) ? `${num}` : num.toFixed(2)
}

const getFieldTotal = (field: keyof ListItem) => {
  return list.value.reduce((total, row) => total + Number(row[field] || 0), 0)
}

const getSummaryRate = () => {
  const nptTotal = getFieldTotal('nptTotal')
  const calendarTime = getFieldTotal('calendarTime')

  if (!calendarTime) return '0.00%'

  return `${((nptTotal / calendarTime) * 100).toFixed(2)}%`
}

const getSummaries = ({ columns }: { columns: Array<{ property?: keyof ListItem | string }> }) => {
  const nonSummaryFields = ['id', 'name', 'teamName', 'projectDeptName']

  return columns.map((column, index) => {
    if (index === 0) return '合计'

    const property = column.property as keyof ListItem | undefined
    if (!property) return ''

    if (property === 'nptRate') return getSummaryRate()
    if (nonSummaryFields.includes(property)) return ''

    return formatNumber(getFieldTotal(property))
  })
}

const formatTeamName = (row: ListItem) => {
  return row.name || '-'
}

const formatRate = (row: ListItem) => {
  return `${(Number(row.nptRate || 0) * 100).toFixed(2)}%`
}

const handleRowClick = (row: ListItem) => {
  if (!row.id) return

  router.push({
    name: 'IotRyXjDailyReport',
    query: {
      deptId: row.id,
      createTime: props.query.createTime,
      projectClassification: 2
    }
  })
}

const getClickableRowClassName = () => 'summary-clickable-row'

const getPieData = () => {
  return list.value
    .map((row) => ({
      name: formatTeamName(row),
      value: Number(row.nptTotal || 0)
    }))
    .filter((item) => item.value > 0)
}

const getNptFieldPieData = () => {
  const excludedFields: Array<keyof ListItem> = [
    'selfStopTime',
    'relocationTime',
    'winterBreakTime'
  ]

  return nonProductionTimeFields
    .filter(([field]) => !excludedFields.includes(field))
    .map(([field, label]) => ({
      name: label,
      value: getFieldTotal(field)
    }))
    .filter((item) => item.value > 0)
}

const resizeChart = useDebounceFn(() => {
  renderChart()
}, 150)

const renderChart = () => {
  if (!chartRef.value) return

  chart?.dispose()
  chart = echarts.init(chartRef.value, undefined, { renderer: 'canvas' })

  window.removeEventListener('resize', resizeChart)
  window.addEventListener('resize', resizeChart)

  const projectPieData = getPieData()
  const nptFieldPieData = getNptFieldPieData()
  const chartWidth = chart.getWidth()
  const chartHeight = chart.getHeight()
  const projectCenter = chartWidth * 0.25
  const nptFieldCenter = chartWidth * 0.73
  const pieCenterY = chartHeight * 0.55
  const graphic: any[] = [
    {
      type: 'text',
      x: projectCenter,
      y: 32,
      style: {
        text: '项目NPT占比',
        fill: '#303133',
        fontSize: 14,
        fontWeight: 500,
        textAlign: 'center',
        textVerticalAlign: 'middle'
      }
    },
    {
      type: 'text',
      x: nptFieldCenter,
      y: 32,
      style: {
        text: 'NPT各项时间占比',
        fill: '#303133',
        fontSize: 14,
        fontWeight: 500,
        textAlign: 'center',
        textVerticalAlign: 'middle'
      }
    }
  ]

  if (projectPieData.length === 0) {
    graphic.push({
      type: 'text',
      x: projectCenter,
      y: pieCenterY,
      style: {
        text: '暂无项目NPT数据',
        fill: '#909399',
        fontSize: 14,
        textAlign: 'center'
      }
    })
  }

  if (nptFieldPieData.length === 0) {
    graphic.push({
      type: 'text',
      x: nptFieldCenter,
      y: pieCenterY,
      style: {
        text: '暂无NPT项数据',
        fill: '#909399',
        fontSize: 14,
        textAlign: 'center'
      }
    })
  }

  chart.setOption({
    tooltip: {
      trigger: 'item',
      formatter: (params: any) =>
        `${params.seriesName}<br/>${params.name}: ${formatNumber(params.value)} H<br/>占比: ${params.percent}%`
    },
    legend: [
      {
        type: 'scroll',
        orient: 'vertical',
        left: 16,
        top: 64,
        bottom: 24,
        data: projectPieData.map((item) => item.name)
      },
      {
        type: 'scroll',
        orient: 'vertical',
        right: 16,
        top: 64,
        bottom: 24,
        data: nptFieldPieData.map((item) => item.name)
      }
    ],
    graphic,
    series: [
      {
        name: '项目NPT占比',
        type: 'pie',
        radius: ['34%', '56%'],
        center: ['25%', '55%'],
        avoidLabelOverlap: true,
        itemStyle: {
          borderRadius: 4,
          borderColor: '#fff',
          borderWidth: 2
        },
        label: {
          formatter: '{b}: {d}%'
        },
        data: projectPieData
      },
      {
        name: 'NPT各项时间占比',
        type: 'pie',
        radius: ['34%', '56%'],
        center: ['73%', '55%'],
        avoidLabelOverlap: true,
        itemStyle: {
          borderRadius: 4,
          borderColor: '#fff',
          borderWidth: 2
        },
        label: {
          formatter: '{b}: {d}%'
        },
        data: nptFieldPieData
      }
    ]
  })
}

onUnmounted(() => {
  window.removeEventListener('resize', resizeChart)
  chart?.dispose()
})

const { ZmTable, ZmTableColumn } = useTableComponents<ListItem>()
</script>

<template>
  <div class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow flex flex-col p-4 gap-2 h-full min-h-0">
    <div class="flex h-12 items-center justify-between">
      <el-button-group>
        <el-button
          size="default"
          :type="tab === '表格' ? 'primary' : 'default'"
          @click="handleSelectTab('表格')"
          >表格
        </el-button>
        <el-button
          size="default"
          :type="tab === '看板' ? 'primary' : 'default'"
          @click="handleSelectTab('看板')"
          >看板
        </el-button>
      </el-button-group>
      <!-- <h3 class="text-xl font-medium">{{ `${deptName}-${tab}` }}</h3> -->
      <div class="w-80px"></div>
    </div>

    <div class="flex-1 relative min-h-0">
      <el-auto-resizer class="absolute">
        <template #default="{ width, height }">
          <zm-table
            v-if="tab === '表格'"
            :data="list"
            :loading="loading"
            :width="width"
            :max-height="height"
            :height="height"
            show-border
            show-summary
            :summary-method="getSummaries"
            :row-class-name="getClickableRowClassName"
            @row-click="handleRowClick">
            <zm-table-column
              prop="name"
              label="队伍"
              min-width="120"
              fixed="left"
              cover-formatter
              :real-value="formatTeamName" />
            <zm-table-column
              v-for="[prop, label] in nonProductionTimeFields"
              :key="prop"
              :prop="prop"
              :label="label"
              min-width="92"
              cover-formatter
              :real-value="(row: ListItem) => formatNumber(row[prop])" />
            <zm-table-column label="npt合计" is-parent>
              <zm-table-column
                prop="nptTotal"
                label="时长(H)"
                min-width="92"
                cover-formatter
                :real-value="(row: ListItem) => formatNumber(row.nptTotal)" />
              <zm-table-column
                prop="nptRate"
                label="占比"
                min-width="92"
                cover-formatter
                :real-value="formatRate" />
            </zm-table-column>
            <zm-table-column
              prop="calendarTime"
              label="自然时间(H)"
              min-width="92"
              cover-formatter
              action
              :real-value="(row: ListItem) => formatNumber(row.calendarTime)" />
          </zm-table>
          <div
            v-else
            ref="chartRef"
            v-loading="loading"
            class="npt-board-container"
            :style="{ width: `${width}px`, height: `${height}px` }">
          </div>
        </template>
      </el-auto-resizer>
    </div>
  </div>
</template>

<style scoped>
:deep(.npt-cell-highlight) {
  background-color: #fff566 !important;
}

:deep(.summary-clickable-row) {
  cursor: pointer;
}

.npt-board-container {
  background: var(--el-bg-color);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 4px;
}
</style>
