import { CalendarOutlined } from '@ant-design/icons';
import moment, { Moment } from 'moment';
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
import styled from '@emotion/styled';
import { useDisclosure } from '@chakra-ui/react';
import Button from '../button';
import Checkbox from '../checkbox';
import Col from '../col';
import DatePicker, { RangePickerProps } from '../date-picker';
import Divider from '../divider';
import Input from '../input';
import Popover, { PopoverProps } from '../popover';
import Row from '../row';
import Select from '../select';
import defaultLocale from '../locale/en_US';
import { ConfigContext } from '../config-provider';

const { Option } = Select;
const { RangePicker } = DatePicker;

const SelectWrapper = styled.div`
  margin: 20px 0;
`;

export type CompareType = 'lastTerm' | 'yesterDay' | 'lastWeek' | 'lastMonth' | 'lastYear';
export type DateType = 'dateTime' | 'date' | 'all';
export type DateValue = 'dateTime' | 'date';

export type RangeType =
  | 'custom'
  | 'currentHour'
  | 'lastHour'
  | 'lastThreeHours'
  | 'today'
  | 'yesterday'
  | 'sevenDaysAgo'
  | 'thirtyDaysAgo'
  | 'ninetyDaysAgo'
  | 'lastMonth'
  | 'lastYear'
  | 'thisWeek'
  | 'thisMonth'
  | 'thisQuarter'
  | 'thisYear';

const formatShowTime = (type: DateType) => {
  if (type === 'dateTime') {
    return 'YYYY-MM-DD HH:mm:ss';
  }
  return 'YYYY-MM-DD';
};

// 根据范围返回时间
const changeRangeType = (value: RangeType) => {
  let newPickerValue: [Moment, Moment];
  switch (value) {
    case 'currentHour':
      newPickerValue = [moment().startOf('hour'), moment().endOf('hour')];
      break;
    case 'lastHour':
      newPickerValue = [
        moment().subtract(1, 'hour').startOf('hour'),
        moment().subtract(1, 'hour').endOf('hour'),
      ];
      break;

    case 'lastThreeHours':
      newPickerValue = [
        moment().subtract(3, 'hour').startOf('hour'),
        moment().subtract(1, 'hour').endOf('hour'),
      ];
      break;

    case 'today':
      newPickerValue = [moment().startOf('day'), moment().endOf('day')];
      break;
    case 'yesterday':
      newPickerValue = [
        moment().subtract(1, 'days').startOf('days'),
        moment().subtract(1, 'days').endOf('days'),
      ];
      break;

    case 'sevenDaysAgo':
      newPickerValue = [
        moment().subtract(7, 'days').startOf('days'),
        moment().subtract(1, 'days').endOf('days'),
      ];
      break;
    case 'thirtyDaysAgo':
      newPickerValue = [
        moment().subtract(30, 'days').startOf('days'),
        moment().subtract(1, 'days').endOf('days'),
      ];
      break;
    case 'ninetyDaysAgo':
      newPickerValue = [
        moment().subtract(90, 'days').startOf('days'),
        moment().subtract(1, 'days').endOf('days'),
      ];
      break;

    case 'lastMonth':
      newPickerValue = [
        moment()
          .month(moment().month() - 1)
          .startOf('month'),
        moment()
          .month(moment().month() - 1)
          .endOf('month'),
      ];
      break;
    case 'lastYear':
      newPickerValue = [
        moment()
          .year(moment().year() - 1)
          .startOf('year'),
        moment()
          .year(moment().year() - 1)
          .endOf('year'),
      ];
      break;

    case 'thisWeek':
      newPickerValue = [moment().weekday(1).startOf('day'), moment().endOf('day')];
      break;
    case 'thisMonth':
      newPickerValue = [moment().startOf('month'), moment().endOf('day')];
      break;
    case 'thisQuarter':
      newPickerValue = [moment().startOf('quarter'), moment().endOf('day')];
      break;
    case 'thisYear':
      newPickerValue = [moment().startOf('year'), moment().endOf('day')];
      break;

    default:
      newPickerValue = [moment().startOf('day'), moment().endOf('day')];
      break;
  }

  return newPickerValue;
};
interface OkProps {
  dateType: DateType;
  dateValue: DateValue;
  value: [Moment, Moment];
  compareType: CompareType | boolean;
  compareValue?: [Moment, Moment] | null;
}

export interface DateValueType {
  type: DateType;
  value?: DateValue;
}

export interface PopoverPickerProps {
  /** 确定回调，回调参数: type value compareType compareValue */
  onOk?: (values: OkProps) => void;
  /** False 禁用, true 开启, CompareType 开启比较并设置对应值 */
  defaultCompareType?: CompareType | boolean;
  /** 选择器类型 */
  defaultDateValueType?: DateValueType;
  /** 继承 RangePickerProps */
  rangePickerProps?: Omit<RangePickerProps, 'onChange' | 'showTime' | 'format' | 'allowClear'>;
  /** 继承 RangePickerProps */
  popoverProps?: PopoverProps;
}

export const PopoverRangePicker: FC<PopoverPickerProps> = ({
  onOk,
  defaultDateValueType,
  defaultCompareType,
  rangePickerProps,
  popoverProps,
}) => {
  const {
    locale: { PopoverRangePicker: locale } = {
      PopoverRangePicker: defaultLocale.PopoverRangePicker,
    },
  } = React.useContext(ConfigContext);
  const { isOpen, onOpen, onClose } = useDisclosure();

  const [showTime, setShowTime] = useState<DateValue>('date');
  const [defaultDateType, setDefaultDateType] = useState<DateType>('date');
  const [rangeType, setRangeType] = useState<RangeType>('custom');

  const [pickerValue, setPickerValue] = useState<[Moment, Moment] | null>([
    moment().startOf('day'),
    moment().endOf('day'),
  ]);

  // 显示比较
  const [compareChecked, setCompareChecked] = useState(true);

  const [compareType, setCompareType] = useState<CompareType | boolean>('lastTerm');

  // 计算比较时间
  const pickerCompareValue = useMemo(() => {
    if (compareType && pickerValue) {
      let compareValue: [Moment, Moment];
      const diffValue = moment(pickerValue[1]).valueOf() - moment(pickerValue[0]).valueOf();
      switch (compareType) {
        case 'lastTerm':
          compareValue = [
            moment(moment(pickerValue[0]).valueOf() - diffValue - 1),
            moment(moment(pickerValue[0]).valueOf() - 1),
          ];
          break;
        case 'yesterDay':
          compareValue = [
            moment(pickerValue[0]).subtract(1, 'days'),
            moment(moment(pickerValue[0]).subtract(1, 'days').valueOf() + diffValue),
          ];
          break;
        case 'lastWeek':
          compareValue = [
            moment(pickerValue[0]).subtract(1, 'weeks'),
            moment(moment(pickerValue[0]).subtract(1, 'weeks').valueOf() + diffValue),
          ];
          break;
        case 'lastMonth':
          compareValue = [
            moment(pickerValue[0]).subtract(1, 'months'),
            moment(moment(pickerValue[0]).subtract(1, 'months').valueOf() + diffValue),
          ];
          break;
        case 'lastYear':
          compareValue = [
            moment(pickerValue[0]).subtract(1, 'years'),
            moment(moment(pickerValue[0]).subtract(1, 'years').valueOf() + diffValue),
          ];
          break;

        default:
          compareValue = [
            moment(moment(pickerValue[0]).valueOf() - diffValue),
            moment(moment(pickerValue[0]).valueOf() - 1),
          ];
          break;
      }
      return compareValue;
    }
  }, [compareType, pickerValue]);

  // 禁用对比的时间
  const compareSelectDisable = useCallback(
    (value: CompareType) => {
      if (pickerValue) {
        let flag = true;
        const diffValue = pickerValue[1]?.diff(pickerValue[0], 'day');
        switch (value) {
          case 'yesterDay':
            if (diffValue <= 1) {
              flag = false;
            }
            break;
          case 'lastWeek':
            if (diffValue <= 7) {
              flag = false;
            }
            break;
          case 'lastMonth':
            if (diffValue <= 31) {
              flag = false;
            }
            break;
          case 'lastYear':
            if (diffValue <= 365) {
              flag = false;
            }
            break;

          default:
            flag = true;
            break;
        }
        return flag;
      }
      return false;
    },
    [pickerValue],
  );

  const handleChangePickerValue = useCallback(
    value => {
      if (typeof compareType !== 'boolean') setCompareType('lastTerm');

      setRangeType('custom');

      if (showTime === 'date') {
        setPickerValue([value[0], value[1].endOf('day')]);
      } else {
        setPickerValue(value);
      }
    },
    [showTime, compareType],
  );

  // 提交
  const handleOnOK = useCallback(() => {
    if (pickerValue && onOk) {
      onOk({
        dateType: defaultDateType,
        dateValue: showTime,
        value: pickerValue,
        compareType,
        compareValue: compareChecked ? pickerCompareValue : null,
      });
    }
  }, [
    compareChecked,
    compareType,
    defaultDateType,
    onOk,
    pickerCompareValue,
    pickerValue,
    showTime,
  ]);

  const Footer = useMemo(
    () => (
      <>
        <Divider />
        <Row justify="space-between">
          <Col span={4}>
            <Button onClick={onClose}>{locale?.cancel}</Button>
          </Col>
          <Col span={3.5}>
            <Button
              type="primary"
              onClick={() => {
                onClose();
                handleOnOK();
              }}
            >
              {locale?.ok}
            </Button>
          </Col>
        </Row>
      </>
    ),
    [handleOnOK, locale?.cancel, locale?.ok, onClose],
  );

  // 处理初始化比较类型 对象 ｜ 布尔
  useEffect(() => {
    if (typeof defaultCompareType === 'boolean') {
      setCompareChecked(false);

      if (defaultCompareType) {
        setCompareType(true);
        return;
      }
      setCompareType(false);
      return;
    }
    if (typeof defaultCompareType === 'string') {
      setCompareType(defaultCompareType);
    }
  }, [defaultCompareType]);

  useEffect(() => {
    if (rangePickerProps?.value) setPickerValue(rangePickerProps?.value as [Moment, Moment]);
  }, [rangePickerProps?.value]);

  useEffect(() => {
    if (typeof defaultDateValueType === 'object') {
      setDefaultDateType(defaultDateValueType.type);
      if (defaultDateValueType.type === 'date') {
        return setShowTime('date');
      }
      if (defaultDateValueType.type === 'dateTime') {
        return setShowTime('dateTime');
      }
      if (defaultDateValueType.type === 'all') {
        if (defaultDateValueType?.value) setShowTime(defaultDateValueType?.value);
      }
    }
  }, [defaultDateValueType]);

  return (
    <Popover
      content={
        <>
          {locale?.type}
          {defaultDateType === 'all' ? (
            <Select
              style={{ width: '100%' }}
              value={showTime}
              onChange={value => {
                if (
                  value === 'date' &&
                  ['currentHour', 'lastHour', 'lastThreeHours'].includes(rangeType)
                ) {
                  setRangeType('custom');
                }
                setShowTime(value);
              }}
            >
              <Option value="date"> {locale?.date}</Option>
              <Option value="dateTime"> {locale?.dateTime}</Option>
            </Select>
          ) : (
            <Input readOnly value={defaultDateType === 'dateTime' ? '日期时间' : '日期'} />
          )}

          <SelectWrapper>
            {locale?.range}
            <Select
              style={{ width: '100%' }}
              value={rangeType}
              onChange={value => {
                setRangeType(value);
                if (typeof compareType !== 'boolean') setCompareType('lastTerm');
                setPickerValue(changeRangeType(value));
              }}
            >
              <Option value="custom"> {locale?.custom}</Option>

              {showTime === 'dateTime' && defaultDateType !== 'date' && (
                <>
                  <Option value="currentHour"> {locale?.currentHour}</Option>
                  <Option value="lastHour"> {locale?.lastHour}</Option>
                  <Option value="lastThreeHours"> {locale?.lastThreeHours}</Option>
                </>
              )}

              <Option value="today"> {locale?.Today}</Option>
              <Option value="yesterday"> {locale?.yesterday}</Option>

              <Option value="sevenDaysAgo"> {locale?.sevenDaysAgo}</Option>
              <Option value="thirtyDaysAgo"> {locale?.thirtyDaysAgo}</Option>
              <Option value="ninetyDaysAgo"> {locale?.ninetyDaysAgo}</Option>

              <Option value="lastMonth"> {locale?.lastMonth}</Option>
              <Option value="lastYear"> {locale?.lastYear}</Option>

              <Option value="thisWeek"> {locale?.thisWeek}</Option>
              <Option value="thisMonth"> {locale?.thisMonth}</Option>
              <Option value="thisQuarter"> {locale?.thisQuarter}</Option>
              <Option value="thisYear"> {locale?.thisYear}</Option>
            </Select>
          </SelectWrapper>

          {locale?.date}
          <RangePicker
            {...rangePickerProps}
            value={pickerValue}
            format={formatShowTime(showTime)}
            showTime={showTime === 'dateTime'}
            style={{ width: '100%' }}
            onChange={handleChangePickerValue}
            allowClear={false}
          />
          {compareType && (
            <SelectWrapper>
              <Checkbox
                checked={compareChecked}
                onChange={e => {
                  if (e.target.checked) {
                    setCompareType('lastTerm');
                  } else {
                    setCompareType(true);
                  }

                  setCompareChecked(e.target.checked);
                }}
              >
                {locale?.compare}
                {/* {compareChecked && pickerCompareValue && (
                  <div>
                    {`(${pickerCompareValue[0].format(
                      formatShowTime(showTime),
                    )} ~ ${pickerCompareValue[1].format(formatShowTime(showTime))})`}
                  </div>
                )} */}
              </Checkbox>
              {compareChecked && (
                <SelectWrapper>
                  <Select
                    disabled={pickerValue?.length !== 2}
                    placeholder={locale?.comparePlaceholder}
                    style={{ width: '100%' }}
                    value={compareType as CompareType}
                    onChange={(value: CompareType) => setCompareType(value)}
                  >
                    <Option value="lastTerm"> {locale?.lastTerm}</Option>
                    {!compareSelectDisable('yesterDay') && (
                      <Option value="yesterDay">{locale?.yesterday}</Option>
                    )}

                    {!compareSelectDisable('lastWeek') && (
                      <Option value="lastWeek">{locale?.lastWeek}</Option>
                    )}

                    {!compareSelectDisable('lastMonth') && (
                      <Option value="lastMonth">{locale?.lastMonth}</Option>
                    )}

                    {!compareSelectDisable('lastYear') && (
                      <Option value="lastYear">{locale?.lastYear}</Option>
                    )}
                  </Select>
                </SelectWrapper>
              )}
            </SelectWrapper>
          )}
          {Footer}
        </>
      }
      visible={isOpen}
      onVisibleChange={vis => {
        if (vis) {
          onOpen();
        } else {
          onClose();
        }
      }}
      placement="bottomLeft"
      {...popoverProps}
    >
      {pickerValue && (
        <Button icon={<CalendarOutlined />}>
          {`${pickerValue[0].format(formatShowTime(showTime))} ~ ${pickerValue[1].format(
            formatShowTime(showTime),
          )}`}
        </Button>
      )}
    </Popover>
  );
};
