<template>
  <el-row :gutter="20">
    <!-- 左侧部门树 -->
    <DeptTree @node-click="handleDeptNodeClick" v-model:collapsed="isLeftContentCollapsed" />

    <el-col :span="isLeftContentCollapsed ? 24 : 20" :xs="24">
      <div class="soc-summary-panel" v-loading="staticLoading">
        <div class="soc-summary-chart">
          <div class="soc-summary-chart__header">
            <div class="soc-summary-chart__title">
              {{ currentDrilldownKey ? `${currentDrilldownKey}分类统计` : 'SOC卡分类统计' }}
            </div>
            <el-button v-if="currentDrilldownKey" link type="primary" @click="resetDrilldown">
              返回总览
            </el-button>
          </div>
          <Echart
            ref="socChartRef"
            :options="socChartOption"
            :height="240"
            @chart-click="handleChartClick" />
        </div>
      </div>

      <ContentWrap style="border: none; margin-top: 5px">
        <!-- 搜索工作栏 -->
        <el-form
          class="-mb-15px"
          :model="queryParams"
          ref="queryFormRef"
          :inline="true"
          label-width="auto">
          <el-form-item label="姓名" prop="userName">
            <el-input
              v-model="queryParams.userName"
              placeholder="请输入姓名"
              clearable
              @keyup.enter="handleQuery"
              class="!w-120px" />
          </el-form-item>

          <el-form-item label="队伍名称" prop="deptName">
            <el-input
              v-model="queryParams.deptName"
              placeholder="请输入队伍名称"
              clearable
              @keyup.enter="handleQuery"
              class="!w-120px" />
          </el-form-item>

          <el-form-item label="观察日期" prop="observationDate">
            <el-date-picker
              v-model="queryParams.observationDate"
              value-format="YYYY-MM-DD HH:mm:ss"
              type="daterange"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
              class="!w-160px" />
          </el-form-item>
          <el-form-item>
            <el-button @click="handleQuery"
              ><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button
            >
            <el-button @click="resetQuery"
              ><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button
            >
            <el-button
              type="primary"
              plain
              @click="openForm('create')"
              v-hasPermi="['rq:iot-soc-summary:create']">
              <Icon icon="ep:plus" class="mr-5px" /> 新增
            </el-button>
            <el-button
              type="success"
              plain
              @click="handleExport"
              :loading="exportLoading"
              v-hasPermi="['rq:iot-soc-summary:export']">
              <Icon icon="ep:download" class="mr-5px" /> 导出
            </el-button>
          </el-form-item>
        </el-form>
      </ContentWrap>

      <!-- 列表 -->
      <ContentWrap style="border: none; margin-top: -10px">
        <zm-table
          :loading="loading"
          :data="list"
          height="35vh"
          :stripe="true"
          :show-overflow-tooltip="true">
          <zm-table-column :label="t('monitor.serial')" width="70" align="center">
            <template #default="scope">
              {{ scope.$index + 1 }}
            </template>
          </zm-table-column>
          <zm-table-column label="项目部" align="center" prop="projectName" />
          <!-- <el-table-column label="部门名称" align="center" prop="deptName" /> -->
          <zm-table-column label="队伍名称" align="center" prop="deptName" />
          <zm-table-column
            label="观察日期"
            align="center"
            prop="observationDate"
            :formatter="dateFormatter"
            类型名称
            width="180px" />

          <zm-table-column label="类型名称" align="center" prop="className" min-width="120" />
          <zm-table-column label="姓名" align="center" prop="userName" />
          <zm-table-column label="岗位" align="center" prop="post" />

          <zm-table-column label="详细描述" align="center" prop="remark" />
          <zm-table-column
            label="创建时间"
            align="center"
            prop="createTime"
            :formatter="dateFormatter"
            width="180px" />

          <zm-table-column label="操作" align="center" min-width="180px" fixed="right" action>
            <template #default="scope">
              <!-- <el-button link type="primary" @click="view(scope.row.id)"> 查看 </el-button> -->
              <el-button link type="primary" @click="downloadSOC(scope.row)"> 下载 </el-button>
              <el-button
                link
                type="primary"
                @click="openForm('update', scope.row.id)"
                v-hasPermi="['rq:iot-soc-summary:update']">
                编辑
              </el-button>
              <el-button
                link
                type="danger"
                @click="handleDelete(scope.row.id)"
                v-hasPermi="['rq:iot-soc-summary:delete']">
                删除
              </el-button>
            </template>
          </zm-table-column>
        </zm-table>
        <!-- 分页 -->
        <Pagination
          :total="total"
          v-model:page="queryParams.pageNo"
          v-model:limit="queryParams.pageSize"
          @pagination="getList" />

        <!-- <div id="docx-viewer" class="docx-viewer-container"></div> -->
        <teleport to="body">
          <transition name="dialog-fade">
            <div
              v-if="dialogVisible"
              class="custom-dialog-overlay"
              @click.self="dialogVisible = false">
              <div class="custom-dialog">
                <div class="custom-dialog-header">
                  <span class="custom-dialog-title">文档预览</span>
                  <el-icon class="custom-dialog-close" @click="dialogVisible = false">
                    <Close />
                  </el-icon>
                </div>
                <div class="custom-dialog-body">
                  <div id="docx-viewer" class="docx-viewer-container"></div>
                </div>
              </div>
            </div>
          </transition>
        </teleport>
      </ContentWrap>
    </el-col>
  </el-row>

  <!-- 表单弹窗：添加/修改 -->
  <IotSocSummaryForm ref="formRef" @success="getList" />
</template>

<script setup lang="ts">
import { dateFormatter, formatDate } from '@/utils/formatTime'
import download from '@/utils/download'
import { IotSocSummaryApi } from '@/api/pms/qhse/index'
import IotSocSummaryForm from './IotSocSummaryForm.vue'
import DeptTree from '@/views/system/user/DeptTree2.vue'
import { Close } from '@element-plus/icons-vue'
import type { EChartsOption } from 'echarts'
import { Echart } from '@/components/Echart'

import { useTableComponents } from '@/components/ZmTable/useTableComponents'
const { ZmTable, ZmTableColumn } = useTableComponents()
import { useUserStore } from '@/store/modules/user'
const userStore = useUserStore()

type SummaryItem = Record<string, any>
type ChartDataItem = {
  id?: string | number
  name: string
  value: number
}

const DRILLDOWN_KEYS = ['个人防护', '规范操作', '规范指挥', '人员位置', '作业场所'] as const

/** SOC卡汇总 列表 */
defineOptions({ name: 'IotSocSummary' })

const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const dialogVisible = ref(false) // 文档预览弹框显示状态
const loading = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const isLeftContentCollapsed = ref(false)
const socChartRef = ref<{ resize: () => void } | null>(null)
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  project: undefined,
  observationDate: [],
  socClass: undefined,
  className: undefined,
  userName: undefined,
  post: undefined,
  deptId: undefined,
  remark: undefined,
  createTime: [],
  deptName: undefined
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中

/** 查询列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await IotSocSummaryApi.getIotSocSummaryPage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
  }
}

const handleDeptNodeClick = async (row) => {
  queryParams.deptId = row.id
  queryParams.pageNo = 1
  resetDrilldown()
  await getStatic()
  getList()
}

/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNo = 1
  getList()
  getStatic()
}

/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  handleQuery()
}

/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
  formRef.value.open(type, id)
}

/** 删除按钮操作 */
const handleDelete = async (id: number) => {
  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    await IotSocSummaryApi.deleteIotSocSummary(id)
    message.success(t('common.delSuccess'))
    // 刷新列表
    await getList()
  } catch {}
}

/** 导出按钮操作 */
const handleExport = async () => {
  try {
    // 导出的二次确认
    await message.exportConfirm()
    // 发起导出
    exportLoading.value = true
    const data = await IotSocSummaryApi.exportIotSocSummary(queryParams)
    download.excel(data, 'SOC卡汇总.xlsx')
  } catch {
  } finally {
    exportLoading.value = false
  }
}

const downloadSOC = async (row) => {
  const res = await IotSocSummaryApi.downloadIotSocSummary(row.id)
  download.excel(
    res,
    `行为安全观察与沟通卡_${formatDate(row.observationDate).substring(0, 10)}_${row.userName}.docx`
  )
}

const childData = ref<SummaryItem[]>([])
const totalData = ref<SummaryItem[]>([])
const currentDrilldownKey = ref('')
const currentDrilldownId = ref<string | number | undefined>(undefined)

const normalizeChartData = (source: SummaryItem[] = []): ChartDataItem[] => {
  return source
    .map((item) => {
      if (!item) return null

      if ('name' in item || 'className' in item || 'label' in item) {
        return {
          id: item.id ?? item.socClass ?? item.valueId,
          name: item.name ?? item.className ?? item.label ?? '',
          value: Number(item.value ?? item.count ?? item.total ?? 0) || 0
        }
      }

      const entries = Object.entries(item)
      const nameEntry =
        entries.find(
          ([key, value]) =>
            !['id', 'socClass', 'valueId', 'value', 'count', 'total'].includes(key) &&
            typeof value === 'number'
        ) || entries.find(([key]) => !['id', 'socClass', 'valueId'].includes(key))

      const [name, value] = nameEntry || ['', 0]
      return {
        id: item.id ?? item.socClass ?? item.valueId,
        name,
        value: Number(value) || 0
      }
    })
    .filter((item): item is ChartDataItem => !!item && !!item.name)
}

const totalChartData = computed(() => {
  return normalizeChartData(totalData.value as SummaryItem[])
})

const childChartData = computed(() => {
  if (!currentDrilldownKey.value) return []
  return normalizeChartData(childData.value as SummaryItem[])
})

const chartColorMap: Record<string, string> = {
  不安全: '#f56c6c',
  个人防护: '#0000ff',
  规范操作: '#810081',
  规范指挥: '#d09cff',
  人员位置: '#00ffff',
  作业场所: '#ff00ff'
}

const childChartColorPalette = [
  '#4f8dff',
  '#43c7ca',
  '#ff981f',
  '#8d8cff',
  '#ff7a7a',
  '#52c41a',
  '#13c2c2',
  '#faad14'
]

const hexToRgba = (hex: string, alpha: number) => {
  const normalizedHex = hex.replace('#', '')
  const safeHex =
    normalizedHex.length === 3
      ? normalizedHex
          .split('')
          .map((char) => char + char)
          .join('')
      : normalizedHex

  const red = Number.parseInt(safeHex.slice(0, 2), 16)
  const green = Number.parseInt(safeHex.slice(2, 4), 16)
  const blue = Number.parseInt(safeHex.slice(4, 6), 16)

  return `rgba(${red}, ${green}, ${blue}, ${alpha})`
}

const getBarBaseColor = (name: string, isDrilldown: boolean, index: number) => {
  if (isDrilldown) {
    return childChartColorPalette[index % childChartColorPalette.length]
  }

  return chartColorMap[name] || '#409eff'
}

const getBarItemStyle = (name: string, isDrilldown: boolean, index: number) => {
  const baseColor = getBarBaseColor(name, isDrilldown, index)

  return {
    color: {
      type: 'linear',
      x: 0,
      y: 0,
      x2: 0,
      y2: 1,
      colorStops: [
        { offset: 0, color: hexToRgba(baseColor, 0.98) },
        { offset: 0.55, color: baseColor },
        { offset: 1, color: hexToRgba(baseColor, 0.72) }
      ]
    },
    borderRadius: [10, 10, 3, 3],
    shadowBlur: 14,
    shadowColor: hexToRgba(baseColor, 0.28),
    shadowOffsetY: 6,
    borderColor: hexToRgba(baseColor, 0.9),
    borderWidth: 1
  }
}

const socChartOption = computed<EChartsOption>(() => {
  const isDrilldown = !!currentDrilldownKey.value
  const sourceData = isDrilldown ? childChartData.value : totalChartData.value

  return {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow',
        shadowStyle: {
          color: 'rgba(64, 158, 255, 0.08)'
        }
      },
      backgroundColor: 'rgba(18, 34, 61, 0.9)',
      borderWidth: 0,
      padding: [10, 14],
      textStyle: {
        color: '#f5f7fa'
      }
    },
    grid: {
      left: 24,
      right: 24,
      top: 36,
      bottom: 40,
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: sourceData.map((item) => item.name),
      axisTick: {
        show: false
      },
      axisLabel: {
        interval: 0,
        rotate: isDrilldown ? 18 : 0,
        color: '#5b6475',
        fontSize: 12
      },
      axisLine: {
        lineStyle: {
          color: '#d7deea'
        }
      }
    },
    yAxis: {
      type: 'value',
      minInterval: 1,
      axisLabel: {
        color: '#7a8599'
      },
      axisLine: {
        show: false
      },
      axisTick: {
        show: false
      },
      splitLine: {
        lineStyle: {
          color: 'rgba(148, 163, 184, 0.2)',
          type: 'dashed'
        }
      }
    },
    series: [
      {
        type: 'bar',
        barMaxWidth: isDrilldown ? 42 : 56,
        showBackground: true,
        backgroundStyle: {
          color: 'rgba(22, 136, 245, 0.055)'
        },
        emphasis: {
          focus: 'series',
          itemStyle: {
            shadowBlur: 20,
            shadowOffsetY: 8
          }
        },
        data: sourceData.map((item, index) => ({
          id: item.id,
          name: item.name,
          value: item.value,
          itemStyle: getBarItemStyle(item.name, isDrilldown, index)
        })),
        label: {
          show: true,
          position: 'top',
          distance: 10,
          color: '#303133',
          fontSize: 12,
          fontWeight: 600
        }
      }
    ]
  }
})

let staticLoading = ref(false)
async function loadChildChartData(drilldownKey: string, socClass: string | number) {
  const res = await IotSocSummaryApi.getSocSummaryStatisticsChild({
    deptId: queryParams.deptId || userStore.user.deptId,
    observationDate: queryParams.observationDate,
    socClass
  })

  currentDrilldownKey.value = drilldownKey
  currentDrilldownId.value = socClass
  childData.value = res?.total || res?.list || res || []
}

async function getStatic() {
  const drilldownKey = currentDrilldownKey.value
  const drilldownId = currentDrilldownId.value
  if (queryParams.deptId) {
    staticLoading.value = true
    const res = await IotSocSummaryApi.getSocSummaryStatistics({
      deptId: queryParams.deptId,
      // 日期
      observationDate: queryParams.observationDate
    })
    totalData.value = res.total || res || []
    childData.value = []
    if (drilldownKey && drilldownId !== undefined) {
      await loadChildChartData(drilldownKey, drilldownId)
    }
    staticLoading.value = false
  } else {
    staticLoading.value = true
    queryParams.deptId = userStore.user.deptId
    const res = await IotSocSummaryApi.getSocSummaryStatistics({
      deptId: queryParams.deptId,
      // 日期
      observationDate: queryParams.observationDate
    })
    totalData.value = res.total || res || []
    childData.value = []
    if (drilldownKey && drilldownId !== undefined) {
      await loadChildChartData(drilldownKey, drilldownId)
    }
    staticLoading.value = false
  }
}

const handleChartClick = async (params: any) => {
  const name = params?.name
  if (!name || currentDrilldownKey.value) return
  const target = totalChartData.value.find((item) => item.name === name)
  const socClass = params?.data?.id ?? target?.id
  if (DRILLDOWN_KEYS.some((item) => item === name) && socClass !== undefined) {
    staticLoading.value = true
    try {
      await loadChildChartData(name, socClass)
    } finally {
      staticLoading.value = false
    }
  }
}

const resetDrilldown = () => {
  currentDrilldownKey.value = ''
  currentDrilldownId.value = undefined
  childData.value = []
}

/** 初始化 **/
watch(isLeftContentCollapsed, async () => {
  await nextTick()
  setTimeout(() => {
    socChartRef.value?.resize()
  }, 320)
})

onMounted(() => {
  getList()
  getStatic()
})
</script>

<style scoped lang="scss">
.custom-dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
}

.custom-dialog {
  background: #fff;
  border-radius: 8px;
  width: 60%;
  max-width: 1200px;
  height: 90vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.custom-dialog-header {
  padding: 16px 20px;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #f5f7fa;
  border-radius: 8px 8px 0 0;
}

.custom-dialog-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.custom-dialog-close {
  font-size: 20px;
  cursor: pointer;
  color: #909399;
  transition: color 0.3s;

  &:hover {
    color: #409eff;
  }
}

.custom-dialog-body {
  flex: 1;
  overflow: hidden;
  padding: 20px;
  background: transparent;
  min-height: 400px;
}

.docx-viewer-container {
  width: 100%;
  height: 100%;
  overflow: auto;
  background: transparent !important;

  :deep(.docx-wrapper) {
    background: transparent !important;
    padding: 0 !important;
  }

  :deep(.docx-wrapper > section.docx) {
    background: #fff !important;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    margin: 0 auto;
    padding: 40px;
  }
}

.custom-dialog-footer {
  padding: 12px 20px;
  border-top: 1px solid #e4e7ed;
  text-align: right;
  background: #f5f7fa;
  border-radius: 0 0 8px 8px;
}

// 动画效果
.dialog-fade-enter-active,
.dialog-fade-leave-active {
  transition: opacity 0.3s ease;
}

.dialog-fade-enter-from,
.dialog-fade-leave-to {
  opacity: 0;
}

.dialog-fade-enter-active .custom-dialog,
.dialog-fade-leave-active .custom-dialog {
  transition: transform 0.3s ease;
}

.dialog-fade-enter-from .custom-dialog,
.dialog-fade-leave-to .custom-dialog {
  transform: scale(0.9);
}

.soc-summary-panel {
  position: relative;
  overflow: hidden;
  margin-bottom: 5px;
  padding: 3px 16px 0px;
  border: 1px solid rgba(143, 168, 211, 0.22);
  border-radius: 10px;
  background: radial-gradient(
      circle at 102% 104%,
      rgba(142, 164, 255, 0.12) 0,
      rgba(142, 164, 255, 0.12) 14%,
      transparent 14.5%
    ),
    radial-gradient(
      circle at 88% 16%,
      rgba(118, 183, 255, 0.08) 0,
      rgba(118, 183, 255, 0.08) 7%,
      transparent 100%
    ),
    linear-gradient(135deg, #fdfefe 0%, #f3f8ff 68%, #eef4ff 100%);
  box-shadow:
    0 12px 28px rgba(64, 112, 196, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

.soc-summary-panel::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
      circle at 76% -4%,
      rgba(129, 224, 202, 0.14) 0,
      rgba(129, 224, 202, 0.14) 12.8%,
      transparent 13%
    ),
    radial-gradient(
      circle at 101% 101%,
      rgba(142, 164, 255, 0.1) 0,
      rgba(142, 164, 255, 0.1) 15.8%,
      transparent 16%
    ),
    linear-gradient(115deg, rgba(255, 255, 255, 0.22), transparent 42%),
    repeating-linear-gradient(
      135deg,
      rgba(255, 255, 255, 0.08) 0,
      rgba(255, 255, 255, 0.08) 1px,
      transparent 1px,
      transparent 14px
    );
  pointer-events: none;
}

.soc-summary-chart {
  position: relative;
  z-index: 1;
  width: 100%;
  padding: 4px;
}

.soc-summary-chart__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.soc-summary-chart__title {
  position: relative;
  padding-left: 14px;
  font-size: 16px;
  font-weight: 700;
  color: #1f2a44;
  letter-spacing: 0.5px;
}

.soc-summary-chart__title::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 6px;
  height: 18px;
  border-radius: 999px;
  background: linear-gradient(180deg, #409eff 0%, #9b8cff 100%);
  transform: translateY(-50%);
  box-shadow: 0 4px 10px rgba(64, 158, 255, 0.35);
}
</style>
