import React, { useContext, useEffect, useRef, useState } from 'react';
import { ConfigProvider, Modal, Radio, Slider, InputNumber, Input, Button, Checkbox } from 'antd';
import classNames from 'classnames';
import moment from 'moment';
import { BasicChart } from '@wisdom-components/basicchart';
import { getHistoryInfo } from '../../apis';
import { std } from 'mathjs';
import skmeans from 'skmeans';
import { outlierArr, timeArr, chartArr, average, markArr, median } from '../utils';
import './index.less';

const IntellectDraw = (props) => {
  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  const prefixCls = getPrefixCls('intellect-draw');
  const { deviceCode, sensors, deviceType, changeSpin } = props;
  const [open, setOpen] = useState(false);
  const [outlier, setOutlier] = useState(3); // 过滤异常

  const [sensorData, setSensorData] = useState([]); // 所有数据
  const [chartData, setChartData] = useState([]); // 图表数据
  const [timeCycle, setTimeCycle] = useState(60);
  const [timeDan, setTimeDan] = useState(1);
  const [foldData, setFoldData] = useState([]);
  const [options, setOptions] = useState({});
  const [selectCheck, setSelectCheck] = useState([]);

  const chartRef = useRef(null);

  // 获取历史数据
  const getSensorsData = async () => {
    changeSpin(true);
    const params = {
      isDilute: true,
      zoom: '5',
      unit: 'min',
      dateFrom: moment().subtract(8, 'day').format('YYYY-MM-DD 00:00:00'),
      dateTo: moment().subtract(1, 'day').format('YYYY-MM-DD 23:59:59'),
      acrossTables: [{ deviceCode: deviceCode, sensors: sensors, deviceType: deviceType }],
      isBoxPlots: true,
      ignoreOutliers: true,
    };
    const results = await getHistoryInfo(params);
    changeSpin(false);
    const historyData = results?.data?.[0] || {};

    setSensorData(() => {
      return historyData;
    });
  };

  // 图表数据处理
  const chartDataHandle = (data) => {
    const times = moment().subtract(1, 'day').format('YYYY-MM-DD');
    const chart = data.map((item) => {
      return {
        ...item,
        time: moment(item.pt).format(times + ' HH:mm:ss'),
      };
    });
    return chart;
  };

  // 聚集方法
  const clusteredMothod = (clustered, num) => {
    // console.log(clustered);
    let foldLine = [];
    const arr = [];
    const times = moment().subtract(1, 'day').format('YYYY-MM-DD');
    const data = clustered.map((item) => {
      return item[1];
    });
    const medianVal = median([...data]);
    // console.log(data, medianVal);
    if (timeDan === 1) {
      return [
        [new Date(moment(times + ' 00:00:00')).getTime(), medianVal],
        [new Date(moment(times + ' 23:59:59')).getTime(), medianVal],
      ];
    }
    data.forEach((item, index) => {
      if (
        index === 0 ||
        (medianVal < item && medianVal > data[index - 1] && index > 0) ||
        (medianVal > item && medianVal < data[index - 1] && index > 0)
      ) {
        arr.push([
          {
            x: clustered[index][0],
            y: clustered[index][1],
            l: item,
          },
        ]);
      } else {
        arr[arr.length - 1].push({
          x: clustered[index][0],
          y: clustered[index][1],
          l: item,
        });
      }
    });
    // console.log(arr);
    arr.forEach((list, index) => {
      const _list = list.map((item) => {
        return item['y'];
      });
      const _medianVal = median([..._list]);
      if (index === 0) {
        foldLine = foldLine.concat([
          [new Date(moment(times + ' 00:00:00')).getTime(), _medianVal],
          [list[list.length - 1].x, _medianVal],
        ]);
      } else if (index === arr.length - 1) {
        foldLine = foldLine.concat([
          [arr[index - 1].at(-1).x, _medianVal],
          [new Date(moment(times + ' 23:59:59')).getTime(), _medianVal],
        ]);
      } else {
        foldLine = foldLine.concat([
          [arr[index - 1].at(-1).x, _medianVal],
          [list[list.length - 1].x, _medianVal],
        ]);
      }
    });
    // console.log(foldLine, 'foldLine');
    if (arr.length === timeDan || arr.length === num) {
      return foldLine;
    } else {
      return clusteredMothod(foldLine, arr.length);
    }
  };

  // 渲染图表
  const renderChart = (_chartData, _clustered) => {
    const chartDatas = _chartData.map((item) => {
      return [new Date(item.time).getTime(), item.pv];
    });
    const clustered = skmeans(chartDatas, 24);
    const { centroids = [] } = clustered;
    const _centroids = centroids.sort((a, b) => {
      return a[0] - b[0];
    });
    // console.log(_centroids);
    const foldLine = clusteredMothod(_centroids, 0);
    // console.log(foldLine);
    const option = {
      xAxis: {
        type: 'time',
        axisTick: {
          alignWithLabel: true,
        },
        boundaryGap: false,
        splitLine: {
          show: true,
          lineStyle: {
            type: 'dashed',
          },
        },
      },
      yAxis: {
        type: 'value',
        name: sensorData?.unit || '',
        position: 'left',
        alignTicks: true,
        axisLine: {
          show: true,
        },
        axisLabel: {
          formatter: '{value}',
        },
      },
      series: [
        {
          type: 'scatter',
          name: sensors,
          sampling: 'average',
          large: true,
          symbolSize: 5,
          data: _chartData.map((item) => {
            return [new Date(item.time).getTime(), item.pv];
          }),
        },
        {
          type: 'line',
          name: '趋势',
          sampling: 'average',
          large: true,
          data: _centroids.map((item) => {
            return [Math.floor(item[0]), item[1]];
          }),
        },
        {
          type: 'line',
          name: '限值',
          data: foldLine.map((item) => {
            return [Math.floor(item[0]), item[1]];
          }),
        },
      ],
    };
    setOptions(option);
    setFoldData(foldDataMethod(foldLine));
  };

  // 限值数据处理
  const foldDataMethod = (data) => {
    let _data = [];
    data.forEach((item, index) => {
      if (index % 2 === 0) {
        _data = _data.concat([[item]]);
      } else {
        _data[Math.floor(index / 2)].push([...item]);
      }
    });
    // console.log(_data);

    return _data.map((list) => {
      return {
        start: moment(list[0][0]).format('HH:mm'),
        end: moment(list[1][0]).format('HH:mm'),
        value: list[0][1],
        wave: 10,
      };
    });
  };

  const onCheckChange = (checkedValues) => {
    setSelectCheck(checkedValues);
  };

  const proposeRender = () => {
    return (
      <div className={classNames(`${prefixCls}-propose-box`)}>
        <Checkbox.Group onChange={onCheckChange}>
          {foldData.map((list, index) => {
            const decimalPoint = sensorData?.decimalPoint || 2;
            const lower1 = (list.value * (1 - list.wave / 100) * (1 - list.wave / 100)).toFixed(decimalPoint) * 1;
            const lower2 = (list.value * (1 - list.wave / 100)).toFixed(decimalPoint) * 1;
            const high1 = (list.value * (1 + list.wave / 100)).toFixed(decimalPoint) * 1;
            const high2 = (list.value * (1 + list.wave / 100) * (1 + list.wave / 100)).toFixed(decimalPoint) * 1;
            return (
              <div className={classNames(`${prefixCls}-propose-list`)} key={index}>
                <div className={classNames(`${prefixCls}-propose-select`)}>
                  <Checkbox value={index}>
                    {list.start}-{list.end}
                  </Checkbox>
                </div>
                <div className={classNames(`${prefixCls}-propose-value`)}>
                  <div className={classNames(`${prefixCls}-value-list`)}>
                    <Input
                      style={{
                        width: '150px',
                      }}
                      addonBefore="低低限"
                      value={lower1}
                      disabled
                    />
                  </div>
                  <div className={classNames(`${prefixCls}-value-list`)}>
                    <Input
                      style={{
                        width: '150px',
                      }}
                      addonBefore="低限"
                      value={lower2}
                      disabled
                    />
                  </div>
                  <div className={classNames(`${prefixCls}-value-list`)}>
                    <Input
                      style={{
                        width: '150px',
                      }}
                      addonBefore="高限"
                      value={high1}
                      disabled
                    />
                  </div>
                  <div className={classNames(`${prefixCls}-value-list`)}>
                    <Input
                      style={{
                        width: '150px',
                      }}
                      addonBefore="高高限"
                      value={high2}
                      disabled
                    />
                  </div>
                </div>
                <div className={classNames(`${prefixCls}-propose-range`)}>
                  <span className={classNames(`${prefixCls}-label`)}>允许浮动范围:</span>
                  <Slider
                    min={0}
                    max={100}
                    style={{ width: '100px' }}
                    onChange={(value) => {
                      const _foldData = structuredClone(foldData);
                      _foldData[index].wave = value;
                      setFoldData(_foldData);
                    }}
                    value={typeof list.wave === 'number' ? list.wave : 0}
                  />
                  <InputNumber
                    min={1}
                    max={100}
                    style={{
                      margin: '0 16px',
                      width: '100px',
                    }}
                    formatter={(value) => `${value}%`}
                    value={list.wave}
                    onChange={(value) => {
                      const _foldData = structuredClone(foldData);
                      _foldData[index].wave = value;
                      setFoldData(_foldData);
                    }}
                  />
                </div>
              </div>
            );
          })}
        </Checkbox.Group>
      </div>
    );
  };

  useEffect(() => {
    const data = [];
    const decimalPoint = sensorData?.decimalPoint || 2;
    selectCheck.forEach((index) => {
      const value = foldData[index]?.value || 0;
      const wave = foldData[index]?.wave || 0;
      const lower1 = (value * (1 - wave / 100) * (1 - wave / 100)).toFixed(decimalPoint) * 1;
      const lower2 = (value * (1 - wave / 100)).toFixed(decimalPoint) * 1;
      const high1 = (value * (1 + wave / 100)).toFixed(decimalPoint) * 1;
      const high2 = (value * (1 + wave / 100) * (1 + wave / 100)).toFixed(decimalPoint) * 1;
      data.push({
        ...foldData[index],
        lower1,
        lower2,
        high1,
        high2,
      })
    })
    if (data.length) return props.backData([data[0].lower1, data[0].lower2, data[0].high1, data[0].high2]);
    return props.backData([]);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectCheck, foldData]);

  useEffect(() => {
    open && getSensorsData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  useEffect(() => {
    const { dataModel = [] } = sensorData;
    if (!dataModel.length) return setChartData([]);
    const count = Math.floor((24 * 60) / timeCycle);
    const times = moment().subtract(1, 'day').format('YYYY-MM-DD');
    const _dataModel = dataModel.map((item) => {
      return {
        ...item,
        time: moment(item.pt).format(times + ' HH:mm:ss'),
      };
    });
    const _chartData = [];
    const _clustered = [];
    for (let i = 0; i < count; i++) {
      const data = _dataModel.filter((item) => {
        const time = new Date(item.time).getTime();
        const min = new Date(moment(times + ' 00:00:00').add(i * timeCycle, 'minute')).getTime();
        const max = new Date(
          moment(times + ' 00:00:00').add((i + 1) * timeCycle, 'minute'),
        ).getTime();
        return time && time >= min && max >= time;
      });
      let dataArr = [];
      const pvArr = data.map((item) => {
        return item.pv || 0;
      });
      const stdVal = pvArr.length ? std(pvArr) : 0;
      const medianVal = pvArr.length ? average(pvArr) : 0;
      const range = {
        min: medianVal - outlier * stdVal,
        max: medianVal + outlier * stdVal,
      };
      data.forEach((item) => {
        if (item.pv >= range.min && item.pv <= range.max) dataArr.push(item);
      });
      if (!outlier) dataArr = [].concat([...data]);
      _chartData.push(...dataArr);
    }
    renderChart(_chartData, _clustered);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sensorData, outlier, timeDan]);

  useEffect(() => {
    setOpen(props.open);
  }, [props.open]);

  return (
    <>
      <div className={classNames(`${prefixCls}`)}>
        <div className={classNames(`${prefixCls}-header`)}>
          <div className={classNames(`${prefixCls}-list`)}>
            <span className={classNames(`${prefixCls}-item`)}>
              <span className={classNames(`${prefixCls}-label`)}>异常值剔除:</span>
              <Slider
                marks={markArr}
                step={null}
                style={{
                  width: '200px',
                }}
                defaultValue={1}
                onChange={(value) => {
                  setOutlier(outlierArr[value]?.value || 0);
                }}
                min={0}
                max={3}
                tooltip={{
                  formatter: (value) => {
                    return markArr[value];
                  },
                }}
              />
            </span>
            <span className={classNames(`${prefixCls}-item`)}>
              <span className={classNames(`${prefixCls}-label`)}>限值时段个数:</span>
              <InputNumber
                min={1}
                max={10}
                style={{
                  width: '100px',
                }}
                value={timeDan}
                onChange={(value) => {
                  setTimeDan(value);
                }}
              />
            </span>
          </div>
          <div className={classNames(`${prefixCls}-propose`)}>
            <span className={classNames(`${prefixCls}-label`)}>建议限值:</span>
            {proposeRender()}
          </div>
        </div>
        <div className={classNames(`${prefixCls}-chart`)}>
          <BasicChart
            ref={chartRef}
            option={options}
            notMerge
            style={{ width: '100%', height: '100%' }}
          />
        </div>
      </div>
    </>
  );
};

export default IntellectDraw;