import * as React from 'react';
import * as PropTypes from 'prop-types';
import dayjs from 'dayjs';

import weui from '../../../utils/weui';
import classNames from '../../../utils/classnames';
import isObjectEqual from '../../../utils/isObjectEqual';
import FormCell from '../formcell';
import { timePicker } from './time';
import { regionPicker } from './region';

export default function Select({
  // 系统属性
  id,
  className,
  style,
  events,
  // 组件属性
  label,
  labelVisible,
  name,
  placeholder,
  layout,
  mode,
  disabled = false,
  requiredFlag,
  // selector mode
  range,
  defaultValue,
  // date mode
  startDate,
  endDate,
  defaultDate,
  // time mode
  startTime,
  endTime,
  defaultTime,
  // region mode
  defaultRegion,
  separator,
}) {
  const [date, setDate] = React.useState(
    decodeIsoDatetime(defaultDate, 'date')
  );
  const [time, setTime] = React.useState(
    decodeIsoDatetime(defaultTime, 'time')
  );
  const [region, setRegion] = React.useState(defaultRegion);
  const [selectedValue, setSelectedValue] = React.useState(defaultValue);

  // 两次默认值不同, 需要刷新
  const prevDefaultRef = React.useRef();
  React.useEffect(() => {
    let hasChange = false;
    if (prevDefaultRef.current?.defaultValue !== defaultValue) {
      setSelectedValue(defaultValue);
      hasChange = true;
    }
    if (prevDefaultRef.current?.defaultDate !== defaultDate) {
      setDate(decodeIsoDatetime(defaultDate, 'date'));
      hasChange = true;
    }
    if (prevDefaultRef.current?.defaultTime !== defaultTime) {
      setTime(decodeIsoDatetime(defaultTime, 'time'));
      hasChange = true;
    }
    if (!isObjectEqual(prevDefaultRef.current?.defaultRegion, defaultRegion)) {
      setRegion(defaultRegion?.join(separator) || '');
      hasChange = true;
    }
    if (hasChange) {
      prevDefaultRef.current = {
        defaultDate,
        defaultTime,
        defaultRegion,
      };
    }
  });

  const isFlex = layout !== 'vertical';
  const cls = classNames({
    'weda-ui': true,
    'weda-select': true,
    [className]: className,
  });
  const subCls = classNames({
    'weui-cell': true,
    'weui-cell_active': true,
    'weui-cell_form': true,
    'weui-flex__item': isFlex,
    'weui-cell_disabled': disabled,
  });

  const onDateclick = function () {
    const options = {
      className: 'weda-ui weda-picker',
    };
    !!date && (options.defaultDate = date);
    !!startDate && (options.start = decodeIsoDatetime(startDate, 'date'));
    !!endDate && (options.end = decodeIsoDatetime(endDate, 'date'));

    weui.datePicker({
      ...options,
      onConfirm(result) {
        const value = dayjs()
          .year(result[0].value)
          .month(result[1].value - 1)
          .date(result[2].value)
          .format('YYYY-MM-DD');
        setDate(value);
        events.change({ value: new Date(value).getTime() });
      },
    });
  };

  const onTimeClick = function () {
    const options = {
      className: 'weda-ui weda-picker',
    };
    !!time && (options.defaultTime = time);
    !!startTime && (options.start = decodeIsoDatetime(startTime, 'time'));
    !!endTime && (options.end = decodeIsoDatetime(endTime, 'time'));

    timePicker({
      ...options,
      onConfirm(result) {
        const date = dayjs().hour(result[0].value).minute(result[1].value);
        const value = date.format('HH:mm');
        setTime(value);
        events.change({
          value: (date.hour() * 60 * 60 + date.minute() * 60) * 1000,
        });
      },
    });
  };

  const onSelect = function () {
    weui.picker(range, {
      defaultValue: [selectedValue || range[0].value],
      onConfirm(result) {
        const item = result[0];
        setSelectedValue(item?.value);
        events.change({ value: item?.value });
      },
      className: 'weda-ui weda-picker',
    });
  };

  const onRegionClick = function () {
    regionPicker({
      defaultValue:
        defaultRegion && defaultRegion.length <= 0
          ? ['北京市', '北京市', '东城区']
          : defaultRegion,
      onConfirm(result) {
        const value = result.map((item) => item.value);
        setRegion(value.join(separator));
        events.change({ value });
      },
      className: 'weda-ui weda-picker',
    });
  };

  const onClick = function () {
    if (disabled) {
      return;
    }

    switch (mode) {
      case 'date': {
        onDateclick();
        break;
      }
      case 'time': {
        onTimeClick();
        break;
      }
      case 'selector': {
        onSelect();
        break;
      }
      case 'region': {
        onRegionClick();
        break;
      }
      default: {
        break;
      }
    }
  };

  const result = {
    selector: range.find((item) => item.value === selectedValue)?.label,
    date: date,
    time: time,
    region,
  };

  return (
    <FormCell
      id={id}
      className={cls}
      style={style}
      label={labelVisible ? label : null}
      layout={layout}
      multiCell={false}
      requiredFlag={requiredFlag}
    >
      <div className={subCls}>
        <div className="weui-cell__bd weui-flex">
          <input
            onClick={onClick}
            className="weui-input"
            type="select"
            name={name}
            placeholder={placeholder}
            value={result[mode]}
            disabled={disabled}
            autoComplete={'off'}
            readOnly={true}
          />
        </div>
      </div>
    </FormCell>
  );
}

export function decodeIsoDatetime(isoStringOrTimesnap, type) {
  if (!isoStringOrTimesnap) {
    return null;
  }

  if (
    typeof isoStringOrTimesnap === 'string' &&
    /^[0-9]*$/.test(isoStringOrTimesnap)
  ) {
    const timeSnap = Number(isoStringOrTimesnap);
    if (!isNaN(timeSnap)) {
      isoStringOrTimesnap = timeSnap;
    }
  }

  if (type === 'time') {
    const time =
      isoStringOrTimesnap.match &&
      isoStringOrTimesnap.match(/^(\d{2}):(\d{2})$/);
    if (time && time[1] < 24 && time[2] < 60) {
      return dayjs().hour(time[1]).minute(time[2]).format('HH:mm');
    } else if (typeof isoStringOrTimesnap === 'number') {
      const timeSnap = Number(isoStringOrTimesnap);
      let day;
      try {
        day = dayjs()
          .hour(Math.floor(timeSnap / 3600000) % 24)
          .minute(Math.floor((timeSnap % 3600000) / 60000));
      } catch (e) {
        day = dayjs(timeSnap);
      }
      return day.format('HH:mm');
    } else {
      return dayjs(isoStringOrTimesnap).format('HH:mm');
    }
  } else {
    return dayjs(isoStringOrTimesnap).format('YYYY-MM-DD');
  }
}
