<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue';
import VChart from 'vue-echarts';
import dayjs from 'dayjs';
import { LineChart, PieChart } from 'echarts/charts';
import {
  AxisPointerComponent,
  DatasetComponent,
  DataZoomComponent,
  GridComponent,
  LegendComponent,
  MarkLineComponent,
  TitleComponent,
  TooltipComponent,
  TransformComponent,
} from 'echarts/components';
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';

import SvgIcon from '@/components/SvgIcon.vue';
import { useRequest } from '@/hooks/request';
import { t } from '@/i18n';
import { getPointTimeSeries } from '@/api';

import SetTempHumidityModal from './SetTempHumidityModal.vue';

import type { SelectValue } from 'ant-design-vue/es/select';
import type { Dayjs } from 'dayjs';
import type { FormatterData, HistoricalDataSequence, MonitoringPointData, TempHumidityControlSettings } from '@/types';

use([
  CanvasRenderer,
  TitleComponent,
  DatasetComponent,
  TransformComponent,
  TooltipComponent,
  LegendComponent,
  GridComponent,
  LineChart,
  PieChart,
  MarkLineComponent,
  AxisPointerComponent,
  DataZoomComponent,
]);

const { handleRequest } = useRequest();

interface Props {
  monitoringId?: number;
  monitoringData: MonitoringPointData[];
  setShow: boolean;
  width: string;
  height: string;
}
const props = defineProps<Props>();
const dateShortcut = ref<number>(0);
const degreeValue = ref<string>('1');
const curvedDataList = ref<TempHumidityControlSettings>();
type RangeValue = [Dayjs, Dayjs];
const historicalDataValue = ref<RangeValue>();
interface ChartStyle {
  width: string;
  height: string;
}

const chartStyle = ref<ChartStyle>({
  width: props.width,
  height: props.height,
});

const degreeData = ref([
  {
    value: '1',
    label: t('envMonitor.temperature'),
    icon: 'temperature',
  },
  {
    value: '2',
    label: t('envMonitor.humidity'),
    icon: 'humidity',
  },
]);

// 初始化默认值
initDateRange();

const disabledDate = (current: Dayjs): boolean => {
  return current ? current.isAfter(dayjs().endOf('day')) : false;
};

// 添加格式转换
const formatDate = (date: Dayjs) => date.format('YYYY-MM-DD HH:mm:ss');

// 处理日期快捷选择
function updateDateRange(type: number) {
  const today = dayjs().endOf('day');
  let startDate: Dayjs;

  switch (type) {
    case 0: // 最近1天
      startDate = today.subtract(1, 'day').startOf('day');
      break;
    case 1: // 最近7天
      startDate = today.subtract(6, 'days').startOf('day');
      break;
    case 2: // 最近30天
      startDate = today.subtract(29, 'days').startOf('day');
      break;
    default:
      return;
  }

  historicalDataValue.value = [startDate, today];
}

// 监听快捷选项变化
watch(dateShortcut, (newVal) => {
  if (newVal !== 3) {
    updateDateRange(newVal);
    getPointTimeSeriesList();
  }
});

// 初始化日期范围
function initDateRange() {
  updateDateRange(dateShortcut.value);
}

// 处理自定义选择
const handleShortcutChange = (value: SelectValue) => {
  if (value !== 3) {
    updateDateRange(value as number);
  }
};

const getPointTimeSeriesList = () => {
  handleRequest(async () => {
    if (props.monitoringId) {
      const data = historicalDataValue.value?.map(formatDate) || [];
      curvedDataList.value = await getPointTimeSeries(
        {
          startTime: data[0],
          endTime: data[1],
        },
        props.monitoringId,
      );
    }
  });
};

const addCustomizedTime = (status: boolean) => {
  if (!status) {
    getPointTimeSeriesList();
    dateShortcut.value = 3;
  }
};

const getMaximumScale = (value: string, scale: string) => {
  if (curvedDataList.value) {
    if (value === '1') {
      const a: string[] = getCurvedData(curvedDataList.value.supplyTempData, 'value') as string[];
      const b: string[] = getCurvedData(curvedDataList.value.tempData, 'value') as string[];
      const merged = a.concat(b, String(curvedDataList.value.tempUpper), String(curvedDataList.value.tempPreset));

      const filteredArray = merged.filter((item) => item !== '-').map(Number);
      if (scale === 'max') {
        return Math.max(...filteredArray); // 最大值
      }

      if (scale === 'min') {
        Math.min(...filteredArray); // 最小值
      }
    }

    if (value === '2') {
      const a: string[] = getCurvedData(curvedDataList.value.supplyHumidityData, 'value') as string[];
      const b: string[] = getCurvedData(curvedDataList.value.humidityData, 'value') as string[];
      const merged = a.concat(
        b,
        String(curvedDataList.value.humidityUpper),
        String(curvedDataList.value.humidityPreset),
      );
      const filteredArray = merged.filter((item) => item !== '-').map(Number);

      if (scale === 'max') {
        return Math.max(...filteredArray); // 最大值
      }

      if (scale === 'min') {
        Math.min(...filteredArray); // 最小值
      }
    }
  }
};

const getCurvedData = (data: HistoricalDataSequence[], value: string) => {
  const listNumber: string[] = [];
  const listString: string[] = [];
  if (data) {
    data.forEach((item) => {
      if (value === 'time') {
        listString.push(item.time.slice(5));
      }
      if (value === 'value') {
        listNumber.push(item.value ? String(item.value) : '-');
      }
    });
  }
  if (value === 'time') {
    return listString;
  } else if (value === 'value') {
    return listNumber;
  } else {
    return [];
  }
};

const temperatureHumidity = () => {
  return degreeValue.value === '1' ? t('envMonitor.temperature') : t('envMonitor.humidity');
};

const option = computed(() => {
  if (!curvedDataList.value) return {};
  return {
    color: ['#1F8FFB', '#32BAC0'],
    title: {
      subtext: t('setupProtocol.protocolParamFields.unit') + ': ' + (degreeValue.value === '1' ? ' °C' : ' %'),
      padding: [0, 0, 0, 30], // 标题内边距
      subtextStyle: {
        color: '#999', // 设置副标题颜色
        fontSize: 10, // 设置副标题字体大小
      },
    },
    tooltip: {
      trigger: 'axis',
      formatter(params: FormatterData[]) {
        let result = params[0].name + '<br/>';
        params.forEach(function (item) {
          // 创建一个圆形的 HTML 元素
          const circle = `<span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: ${item.color}; margin-right: 5px;"></span>`;
          result +=
            circle +
            item.seriesName +
            ':&nbsp;&nbsp;' +
            item.value +
            (degreeValue.value === '1' ? ' °C' : ' %') +
            '<br/>';
        });
        return result;
      },
      backgroundColor: 'rgba(255, 255, 255, 0.75)',
    },
    legend: {
      bottom: -5,
      data: [
        {
          name:
            t('envMonitor.indoor') +
            temperatureHumidity() +
            t('envMonitor.setValue') +
            '：' +
            (degreeValue.value === '1'
              ? curvedDataList.value.tempPreset + '℃'
              : curvedDataList.value.humidityPreset + '%'),
          icon: 'path://M128 501.333v64H0v-64zm213.333 0v64h-128v-64zm213.334 0v64h-128v-64zm234.666 0v64h-128v-64zm234.667 0v64H896v-64z',
          itemStyle: {
            color: '#67C23A',
          },
          selectedMode: false,
        },
        {
          name:
            t('envMonitor.indoor') +
            temperatureHumidity() +
            t('envMonitor.upperLimitValue') +
            '：' +
            (degreeValue.value === '1'
              ? curvedDataList.value.tempUpper + '℃'
              : curvedDataList.value.humidityUpper + '%'),
          icon: 'path://M128 501.333v64H0v-64zm213.333 0v64h-128v-64zm213.334 0v64h-128v-64zm234.666 0v64h-128v-64zm234.667 0v64H896v-64z',
          itemStyle: {
            color: '#F56C6C',
          },
        },
        {
          name: t('envMonitor.indoor') + temperatureHumidity(),
          itemStyle: {
            color: '#1F8FFB',
          },
        },
        {
          name: t('envMonitor.supplyAir') + temperatureHumidity(),
          itemStyle: {
            color: '#32BAC0',
          },
        },
      ],
      itemGap: 20, // 图例间距
      // 文本样式配置
      textStyle: {
        fontWeight: 400,
        fontSize: 12,
        color: '#000000',
        lineHeight: 22, // 需要配合 itemHeight 使用
      },
    },
    xAxis: {
      type: 'category',
      data:
        degreeValue.value === '1'
          ? getCurvedData(curvedDataList.value.tempData, 'time')
          : getCurvedData(curvedDataList.value.humidityData, 'time'),
      axisLine: {
        lineStyle: {
          type: 'dashed', // 虚线样式
          color: '#EBEBEB', // 轴线颜色
        },
      },
      // X轴文本颜色配置
      axisLabel: {
        color: '#999', // 文本颜色
      },
      axisTick: {
        show: false, // 隐藏刻度线
      },
    },
    yAxis: {
      type: 'value',
      min: getMaximumScale(degreeValue.value, 'min'),
      max: getMaximumScale(degreeValue.value, 'max'),
      axisLine: {
        lineStyle: {
          color: '#999999', // Y轴线颜色
        },
      },
      splitLine: {
        lineStyle: {
          type: 'dashed', // 设置为虚线
          color: '#EBEBEB', // 指定颜色
        },
      },
    },
    dataZoom: [
      {
        type: 'inside',
        start: 0,
        end: 100,
        bottom: 35,
        // 关键配置：隐藏手柄标签
        handleStyle: {
          label: { show: false }, // 关闭手柄上的文字提示
        },
        // 可选：关闭滑动时的详细数值提示
        showDetail: false,
      },
      {
        start: 0,
        end: 100,
        bottom: 35,
        // 关键配置：隐藏手柄标签
        handleStyle: {
          label: { show: false }, // 关闭手柄上的文字提示
        },
        // 可选：关闭滑动时的详细数值提示
        showDetail: false,
      },
    ],
    series: [
      // 室内温度设定值虚线
      {
        name:
          t('envMonitor.indoor') +
          temperatureHumidity() +
          t('envMonitor.setValue') +
          '：' +
          (degreeValue.value === '1'
            ? curvedDataList.value.tempPreset + '℃'
            : curvedDataList.value.humidityPreset + '%'),
        type: 'line',
        silent: true, // 设置该系列不响应事件，图例不可点击
        lineStyle: {
          color: '#67C23A',
          width: 0, // 隐藏实际线条
        },
        markLine: {
          symbol: 'none',
          lineStyle: {
            type: 'dashed',
            color: '#67C23A',
          },
          data: [
            {
              yAxis: degreeValue.value === '1' ? curvedDataList.value.tempPreset : curvedDataList.value.humidityPreset,
            },
          ],
          label: { show: false },
        },
      },
      // 室内温度上限值虚线
      {
        name:
          t('envMonitor.indoor') +
          temperatureHumidity() +
          t('envMonitor.upperLimitValue') +
          '：' +
          (degreeValue.value === '1' ? curvedDataList.value.tempUpper + '℃' : curvedDataList.value.humidityUpper + '%'),
        type: 'line',
        silent: true, // 设置该系列不响应事件，图例不可点击
        lineStyle: {
          color: '#F56C6C',
          width: 0,
        },
        markLine: {
          symbol: 'none',
          lineStyle: {
            type: 'dashed',
            color: '#F56C6C',
          },
          data: [
            { yAxis: degreeValue.value === '1' ? curvedDataList.value.tempUpper : curvedDataList.value.humidityUpper },
          ],
          label: { show: false },
        },
      },

      // 室内温度折线
      {
        name: t('envMonitor.indoor') + temperatureHumidity(),
        type: 'line',
        data:
          degreeValue.value === '1'
            ? getCurvedData(curvedDataList.value.tempData, 'value')
            : getCurvedData(curvedDataList.value.humidityData, 'value'),
        smooth: true,
        lineStyle: {
          color: '#1F8FFB',
        },
        showSymbol: true, // 启用数据点
        symbolSize: 0, // 默认隐藏数据点（大小为0）
        legendHoverLink: false, //  阻断图例悬停联动
        // 关键修复：emphasis 配置需独立声明
        emphasis: {
          symbolSize: 20, //  悬停时显示
          itemStyle: {
            color: '#fff',
            borderColor: '#1F8FFB',
            borderWidth: 8,
          },
        },
      },
      // 送风温度折线
      {
        name: t('envMonitor.supplyAir') + temperatureHumidity(),
        type: 'line',
        data:
          degreeValue.value === '1'
            ? getCurvedData(curvedDataList.value.supplyTempData, 'value')
            : getCurvedData(curvedDataList.value.supplyHumidityData, 'value'),
        smooth: true,
        lineStyle: {
          color: '#32BAC0',
        },
        showSymbol: true, // 启用数据点
        symbolSize: 0, // 默认隐藏数据点（大小为0）
        legendHoverLink: false, //  阻断图例悬停联动
        // 关键修复：emphasis 配置需独立声明
        emphasis: {
          symbolSize: 20, //  悬停时显示
          itemStyle: {
            color: '#fff',
            borderColor: '#32BAC0',
            borderWidth: 8,
          },
        },
      },
    ],
    grid: {
      top: 30, // 上边距为0
      right: 30, // 右边距为0
      bottom: 90, // 下边距为0
      left: 30, // 左边距为0
    },
  };
});

const setClick = () => {
  getPointTimeSeriesList();
};

defineExpose({
  getPointTimeSeriesList,
});

watch(
  () => props.monitoringId,
  (count) => {
    if (count) {
      getPointTimeSeriesList();
    }
  },
);

onMounted(() => {
  getPointTimeSeriesList();
});
</script>

<template>
  <div>
    <AFlex justify="space-between" align="center">
      <div class="segmented-style">
        <ASegmented v-model:value="degreeValue" :options="degreeData" :block="true">
          <template #label="{ payload }">
            <SvgIcon :name="payload.icon" />
            {{ payload.label }}
          </template>
        </ASegmented>
      </div>
      <SetTempHumidityModal
        v-if="setShow"
        :monitoring-id="monitoringId"
        :monitoring-data="monitoringData"
        @setClick="setClick"
      />
      <AFlex v-else>
        <ASelect
          v-model:value="dateShortcut"
          :placeholder="$t('common.plzSelect')"
          class="date-shortcut"
          @change="handleShortcutChange"
        >
          <ASelectOption :value="0">{{ $t('common.recentlyOneDay') }}</ASelectOption>
          <ASelectOption :value="1">{{ $t('common.recentlySevenDays') }}</ASelectOption>
          <ASelectOption :value="2">{{ $t('common.recentlyThirtyDays') }}</ASelectOption>
          <ASelectOption :value="3">{{ $t('common.custom') }}</ASelectOption>
        </ASelect>
        <ARangePicker
          v-model:value="historicalDataValue"
          :disabled-date="disabledDate"
          :allow-clear="false"
          :separator="$t('common.to')"
          @openChange="addCustomizedTime"
        />
      </AFlex>
    </AFlex>
    <AFlex v-if="setShow" class="date-selection-div">
      <ASelect
        v-model:value="dateShortcut"
        :placeholder="$t('common.plzSelect')"
        class="date-shortcut"
        @change="handleShortcutChange"
      >
        <ASelectOption :value="0">{{ $t('common.recentlyOneDay') }}</ASelectOption>
        <ASelectOption :value="1">{{ $t('common.recentlySevenDays') }}</ASelectOption>
        <ASelectOption :value="2">{{ $t('common.recentlyThirtyDays') }}</ASelectOption>
        <ASelectOption :value="3">{{ $t('common.custom') }}</ASelectOption>
      </ASelect>
      <ARangePicker
        v-model:value="historicalDataValue"
        :disabled-date="disabledDate"
        :allow-clear="false"
        :separator="$t('common.to')"
        @openChange="addCustomizedTime"
      />
    </AFlex>

    <VChart class="chart" :style="chartStyle" :option="option" />
  </div>
</template>

<style lang="scss" scoped>
.segmented-style {
  width: 160px;
}

:deep(.segmented-style) {
  .ant-segmented {
    background-color: var(--antd-color-primary-opacity-15);
  }

  .ant-segmented .ant-segmented-item-label {
    color: var(--antd-color-primary-hover);
  }
}

.chart {
  width: 560px;
  height: 700px;
}

.date-selection-div {
  margin-top: 16px;
}

.date-shortcut {
  width: 96px;
  margin-right: 12px;
}

.check-box {
  margin-top: 8px;
}
</style>
