<script setup lang="ts">
import { GridLayout, GridItem } from 'grid-layout-plus'
import * as echarts from 'echarts';
import { PageContainer } from 'antdv-pro-layout';
import { onMounted, reactive, ref, markRaw, nextTick, onUnmounted, watch } from 'vue';
import { RESULT_CODE_ERROR, RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { listKPIData, getKPITitle } from '@/api/perfManage/goldTarget';
import useI18n from '@/hooks/useI18n';
import { parseDateToStr } from '@/utils/date-utils';
import dayjs, { Dayjs } from 'dayjs';
import useNeInfoStore from '@/store/modules/neinfo';
import { message, Switch, Form } from 'ant-design-vue';
import { ColumnsType } from 'ant-design-vue/es/table';
import { generateColorRGBA } from '@/utils/generate-utils';
import { LineSeriesOption } from 'echarts/charts';
import { OptionsType, WS } from '@/plugins/ws-websocket';
const { t, currentLocale } = useI18n();

const neInfoStore = useNeInfoStore();

//WebSocket连接
const ws = ref<WS | null>(null);

//添加实时数据开关状态
const realTimeEnabled = ref(false);
//实时数据开关
const handleRealTimeSwitch = (checked: any) => {
  fnRealTimeSwitch(!!checked);
};


// 网元数组
const networkElementTypes = ['udm', 'upf', 'amf', 'smf', 'ims','ausf'] as const;
// 定义 ChartType
type ChartType = typeof networkElementTypes[number];  // 将 i 的类型改为 ChartType

// 添加类型定义
interface LayoutItem {
  x: number;
  y: number;
  w: number;
  h: number;
  i: ChartType;  // 将 i 的类型改为 ChartType
}

type Layout = LayoutItem[];

//构建响应式数组储存图表类型数据
const chartOrder = ref<Layout>(
  networkElementTypes.map((type, index) => ({
    x: index % 2 * 6,  // 每行两个图表，宽度为6
    y: Math.floor(index / 2) * 4,  // 每个图表占据 4 个单位高度
    w: 6,  // 宽度为6个单位
    h: 4,  // 高度为4个单位
    i: type,  // 使用网元类型作为唯一标识符
  }))
);

// 改变布局触发更新
const handleLayoutUpdated = (newLayout: Layout) => {
  chartOrder.value = newLayout;
  nextTick(() => {
    newLayout.forEach((item) => {
      const state = chartStates[item.i];
      if (state.chart.value) {
        state.chart.value.resize();
      }
    });
  });
};

// 监听 chartOrder 的变化
watch(chartOrder, () => {
  nextTick(() => {
    Object.values(chartStates).forEach(state => {
      if (state.chart.value) {
        state.chart.value.resize();
      }
    });
  });
});

// 定义表格状态类型
type TableStateType = {
  loading: boolean;
  size: SizeType;
  seached: boolean;
  data: Record<string, any>[];
  selectedRowKeys: (string | number)[];
};


// 创建可复用的状态
const createChartState = () => {
  const chartDom = ref<HTMLElement | null>(null);
  const chart = ref<echarts.ECharts | null>(null);
  const observer = ref<ResizeObserver | null>(null);

  return {
    chartDom,
    chart,
    observer,
    tableColumns: ref<ColumnsType>([]),
    tableState: reactive<TableStateType>({
      loading: false,
      size: 'small',
      seached: true,
      data: [],
      selectedRowKeys: [],
    }),
    chartLegendSelected: {} as Record<string, boolean>,
    chartDataXAxisData: [] as string[],
    chartDataYSeriesData: [] as CustomSeriesOption[],
  };
};

// 为每种图表类型创建状态
const chartStates: Record<ChartType, ReturnType<typeof createChartState>> = Object.fromEntries(
  networkElementTypes.map(type => [type, createChartState()])
) as Record<ChartType, ReturnType<typeof createChartState>>;

//日期选择器
interface RangePicker extends Record<ChartType, [string, string]> {
  placeholder: [string, string];
  ranges: Record<string, [Dayjs, Dayjs]>;
}

// 创建日期选择器状态
const rangePicker = reactive<RangePicker>({
  ...Object.fromEntries(networkElementTypes.map(type => [
    type,
    [
      dayjs('2024-09-20 00:00:00').valueOf().toString(),//模拟数据的日期设为默认日期
      dayjs('2024-09-20 23:59:59').valueOf().toString()
    ]
  ])) as Record<ChartType, [string, string]>,
  placeholder: [t('views.monitor.monitor.startTime'), t('views.monitor.monitor.endTime')] as [string, string],
  ranges: {
    [t('views.monitor.monitor.yesterday')]: [dayjs().subtract(1, 'day').startOf('day'), dayjs().subtract(1, 'day').endOf('day')],
    [t('views.monitor.monitor.today')]: [dayjs().startOf('day'), dayjs()],
    [t('views.monitor.monitor.week')]: [dayjs().startOf('week'), dayjs().endOf('week')],
    [t('views.monitor.monitor.month')]: [dayjs().startOf('month'), dayjs().endOf('month')],
  } as Record<string, [Dayjs, Dayjs]>,
});

// 创建可复用的图表初始化函数
const initChart = (type: ChartType) => {
  nextTick(() => {
    const state = chartStates[type];
    const container = state.chartDom.value;
    if (!container) return;

    state.chart.value = markRaw(echarts.init(container, 'light'));
    const option: echarts.EChartsOption = {
      tooltip: {
        trigger: 'axis',
        position: function(pt: any) {
          return [pt[0], '10%'];
        },
      },
      xAxis: {
        type: 'category',
        boundaryGap: false,
        data: [],
      },
      yAxis: {
        type: 'value',
        boundaryGap: [0, '100%'],
      },
      legend: {
        type: 'scroll',
        orient: 'horizontal',
        top: -5,
        itemWidth: 20,
        textStyle: {
          color: '#646A73',
        },
        icon: 'circle',
        selected: {},
      },
      grid: {
        left: '10%',
        right: '10%',
        bottom: '15%',
      },
      dataZoom: [
        {
          type: 'inside',
          start: 0,
          end: 100,
        },
        {
          start: 0,
          end: 100,
        },
      ],
      series: [],
    };
    state.chart.value.setOption(option);
    state.chart.value.resize();  // 确保图表正确调整大小

    // 创建 ResizeObserver 实例
    state.observer.value = new ResizeObserver(() => {
      if (state.chart.value) {
        state.chart.value.resize();
      }
    });

    // 开始观察图表容器
    state.observer.value.observe(container);
  });
};

//结束拖拽事件
const onDragEnd = () => {
  nextTick(() => {
    chartOrder.value.forEach((type:any) => {
      const state = chartStates[type as ChartType];
      if (state.chart.value) {
        state.chart.value.resize(); // 调整图表大小
        // 重新设置图表选项，保留原有数
        state.chart.value.setOption({
          xAxis: { data: state.chartDataXAxisData },
          series: state.chartDataYSeriesData,
        });
      }
    });
  });
};


// 可复用的数据获取函数
const fetchData = async (type: ChartType) => {
  const state = chartStates[type];  // 直接使用 type
  const neId = '001';
  state.tableState.loading = true;
  try {
    const dateRange = rangePicker[type] as [string, string];
    const [startTime, endTime] = dateRange;
    const res = await listKPIData({
      neType: type.toUpperCase(),
      neId,
      startTime,
      endTime,
      sortField: 'timeGroup',
      sortOrder: 'desc',
      interval: 5,
    });
    if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
      state.tableState.data = res.data;
      nextTick(() => {
        renderChart(type);
      });
    }
  } catch (error) {
    console.error(error);
    message.error(t('common.getInfoFail'));
  } finally {
    state.tableState.loading = false;
  }
};

//建立实时数据连接
function fnRealTimeSwitch(bool: boolean) {

  realTimeEnabled.value = bool;
  if (bool) {
    if(!ws.value){

      ws.value = new WS();
    }
    Object.values(chartStates).forEach(state => {
      state.tableState.seached = false;
    });
    // 建立连接
    const options: OptionsType = {
      url: '/ws',
      params: {
        subGroupID: networkElementTypes.map(type => `10_${type.toUpperCase()}_001`).join(','),
      },
      onmessage: wsMessage,
      onerror: wsError,

    };
    ws.value.connect(options);
  } else if(ws.value){

    Object.values(chartStates).forEach(state => {
      state.tableState.seached = true;
    });
    ws.value.close();
    ws.value = null;
  }
}

// 接收数据后错误回调
function wsError() {

  message.error(t('common.websocketError'));
}

// 接收数据后回调
function wsMessage(res: Record<string, any>) {
  //const res = JSON.parse(event.data);
  const { code, data } = res;
  if (code === RESULT_CODE_ERROR) {
    console.warn(res.msg);
    return;
  }

  // 订阅组信息
  if (!data?.groupId) {
    return;
  }

  // 处理四个图表的数据
  networkElementTypes.forEach((type) => {
    const state = chartStates[type];
    const kpiEvent:any = data.data[type.toUpperCase()];

    if (kpiEvent) {
      // 更新 X 轴数据
      if (kpiEvent.timeGroup) {
        state.chartDataXAxisData.push(parseDateToStr(+kpiEvent.timeGroup));
        if (state.chartDataXAxisData.length > 100) {
          state.chartDataXAxisData.shift();
        }
      }

      // 更新 Y 轴数据
      state.chartDataYSeriesData.forEach(series => {
        if (kpiEvent[series.customKey as string] !== undefined) {
          series.data.push(+kpiEvent[series.customKey as string]);
          if (series.data.length > 100) {
            series.data.shift();
          }
        }
      });

      // 更新图表
      if (state.chart.value) {
        state.chart.value.setOption({
          xAxis: { data: state.chartDataXAxisData },
          series: state.chartDataYSeriesData,
        });
      }
    }
  });
}

type LineDataItem = {
  value: number;
  [key: string]: any;
};
interface CustomSeriesOption extends Omit<LineSeriesOption, 'data'> {
  customKey?: string;
  data: (number | LineDataItem)[];
}
// 创建可复用的图表渲染函数
const renderChart = (type: ChartType) => {
  const state = chartStates[type];
  if (state.chart.value == null) {
    return;
  }
  // 重置数据
  state.chartLegendSelected = {};
  state.chartDataXAxisData = [];
  state.chartDataYSeriesData = [];

  // 处理数据
  for (const column of state.tableColumns.value) {
    if (['neName', 'startIndex', 'timeGroup'].includes(column.key as string)) continue;
    const color = generateColorRGBA();
    state.chartDataYSeriesData.push({
      name: column.title as string,
      customKey: column.key as string,
      type: 'line',
      symbol: 'none',
      sampling: 'lttb',
      itemStyle: { color },
      areaStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          { offset: 0, color: color.replace(')', ',0.8)') },
          { offset: 1, color: color.replace(')', ',0.3)') },
        ]),
      },
      data: [],
    } as CustomSeriesOption);
    state.chartLegendSelected[column.title as string] = true;
  }

  const orgData = [...state.tableState.data].reverse();
  for (const item of orgData) {
    state.chartDataXAxisData.push(parseDateToStr(+item.timeGroup));
    for (const series of state.chartDataYSeriesData) {
      series.data.push(+item[series.customKey as string]);
    }
  }

  // 更新图表
  state.chart.value.setOption(
    {
      legend: { selected: state.chartLegendSelected },
      xAxis: {
        data: state.chartDataXAxisData,
        type: 'category',
        boundaryGap: false,
      },
      series: state.chartDataYSeriesData,
      dataZoom: [
        {
          type: 'inside',
          start: 0,
          end: 100,
        },
        {
          start: 0,
          end: 100,
        },
      ],
    },
    { replaceMerge: ['xAxis', 'series'] }
  );
};


// 获取表头数据
const fetchKPITitle = async (type: ChartType) => {
  const language = currentLocale.value.split('_')[0] === 'zh' ? 'cn' : currentLocale.value.split('_')[0];
  try {
    const res = await getKPITitle(type.toUpperCase());
    if (res.code === RESULT_CODE_SUCCESS && Array.isArray(res.data)) {
      chartStates[type].tableColumns.value = res.data.map(item => ({
        title: item[`${language}Title`],
        dataIndex: item.kpiId,
        align: 'left',
        key: item.kpiId,
        resizable: true,
        width: 100,
        minWidth: 150,
        maxWidth: 300,
      }));
    }
  } catch (error) {
    console.error(error);
    message.warning(t('common.getInfoFail'));
  }
};

// 初始化所有图表
onMounted(async () => {
  ws.value = new WS();
  await neInfoStore.fnNelist();
  for (const type of networkElementTypes) {
    await fetchKPITitle(type);
    initChart(type);
    fetchData(type);  // 确保这行存在
  }

});

// 在组件卸载时销毁图表实例
onUnmounted(() => {
  if(ws.value &&ws.value.state()===WebSocket.OPEN) {
    ws.value.close();
  }
  Object.values(chartStates).forEach((state) => {
    if (state.chart.value) {
      state.chart.value.dispose();
    }
    if (state.observer.value) {
      state.observer.value.disconnect();
    }
  });
});
</script>

<template>
  <PageContainer>
    <div class="control-row">
      <a-form layout="inline">
        <a-form-item>
          <a-switch
            v-model:checked="realTimeEnabled"
            @change="handleRealTimeSwitch"
          />
        </a-form-item>
        <a-form-item>
          <span class="switch-label">{{ realTimeEnabled ? t('views.dashboard.cdr.realTimeDataStart') : t('views.dashboard.cdr.realTimeDataStop') }}</span>
        </a-form-item>
        <!-- 这里可以添加更多的表单项 -->
      </a-form>
    </div>
    <GridLayout
      v-model:layout="chartOrder"
      :col-num="12"
      :row-height="100"
      :margin="[10, 10]"
      :is-draggable="true"
      :is-resizable="true"
      :vertical-compact="true"
      :use-css-transforms="true"
      :responsive="true"
      :prevent-collision="false"
      @layout-updated="handleLayoutUpdated"
      class="charts-container"
    >
      <GridItem
        v-for="item in chartOrder"
        :key="item.i"
        :x="item.x"
        :y="item.y"
        :w="item.w"
        :h="item.h"
        :i="item.i"
        :min-w="4"
        :min-h="3"
        :is-draggable="true"
        :is-resizable="true"
        :resizable-handles="['ne']"
        drag-allow-from=".drag-handle"
        drag-ignore-from=".no-drag"
        class="grid-item"
      >
        <div class="drag-handle"></div>
        <a-card :bordered="false" class="card-container">
          <template #title>
            <span class="no-drag">{{ item.i.toUpperCase() }}</span>
          </template>
          <template #extra>
            <a-range-picker
              v-model:value="rangePicker[item.i]"
              :allow-clear="false"
              bordered
              :show-time="{ format: 'HH:mm:ss' }"
              format="YYYY-MM-DD HH:mm:ss"
              value-format="x"
              :placeholder="rangePicker.placeholder"
              :ranges="rangePicker.ranges"
              style="width: 100%"
              @change="() => fetchData(item.i)"
            ></a-range-picker>
          </template>
          <div class='chart'>
            <div :ref="el => { if (el) chartStates[item.i].chartDom.value = el as HTMLElement }"></div>
          </div>
        </a-card>
      </GridItem>
    </GridLayout>
  </PageContainer>
</template>

<style lang="less" scoped>
.charts-container {
  width: 100%;
  min-height: 600px;  // 减小最小高度
}

.grid-item {
  overflow: visible; // 改为 visible 以确保拖拽手柄可见
  position: relative;
}

.card-container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

:deep(.ant-card-body) {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 12px !important;
  overflow: hidden;
}

.chart {
  flex: 1;
  min-height: 0;
}

.chart > div {
  width: 100%;
  height: 100%;
}

.control-row {
  margin-bottom: 16px;
  background-color: #ffffff;  // 改为白色背景
  border-radius: 4px;
  padding: 16px;
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03);  // 添加轻微阴影
  border: 1px solid #f0f0f0;  // 添加浅色边框
}

:deep(.ant-form-item) {
  margin-bottom: 0;
}

:deep(.ant-form-item-label) {
  font-weight: 500;  // 加粗标签文字
  color: rgba(0, 0, 0, 0.85);  // 调整标签颜色
}

.switch-label {
  margin-left: 8px;
  font-size: 14px;
  color: rgba(0, 0, 0, 0.65);  // 调整文字颜色
  white-space: nowrap;
}

.drag-handle {
  position: absolute;
  top: 0;
  right: 0;
  width: 20px;
  height: 20px;
  background-color: #1890ff;
  cursor: move;
  z-index: 100; // 增加 z-index 确保在最上层
}

/* 可以根据需要调整卡片标题的样式 */
:deep(.ant-card-head-title) {
  padding-right: 25px;  /* 为拖拽手柄留出空间 */
}
</style>
