import { isValidElement, useRef } from 'react';
import { isImmutable } from 'immutable';
import {
  get,
  map,
  join,
  set,
  mapKeys,
  forEach,
  sortBy,
  isArray,
  find,
  isEqual,
  mergeWith,
} from 'lodash';
import { ColProps } from 'antd/lib/col';

import warning from 'warning';
import { stringAndFunc } from './ItemsType';
import { KeyValue, ParamsType } from './Form';
import { FormatFieldsValue, YFormItemProps } from './Items';

const nzhcn = require('nzh/cn');

export const layoutMore = {
  labelCol: { xs: { span: 24 }, sm: { span: 4 } },
  wrapperCol: { xs: { span: 24 }, sm: { span: 20 } },
};
export const tailLayout = { wrapperCol: { offset: 8, span: 16 } };

export function replaceMessage(template: string, kv: Record<string, string>): string {
  return template.replace(/\$\{\w+\}/g, (str: string) => {
    const key = str.slice(2, -1);
    return kv[key];
  });
}

export const mergeWithDom = (obj: any, ...params: any[]) => {
  return mergeWith(obj, ...params, (_, srcValue) => {
    // 如果是元素则返回要更改的值,不是则不处理
    if (isValidElement(srcValue)) {
      return srcValue;
    }
    // 如果是不可变数据,不处理合并
    if (isImmutable(srcValue)) {
      return srcValue;
    }
  });
};

// 获取一行多组件的 width
export const oneLineItemStyle = (list?: (number | string)[]) => {
  if (!list || !Array.isArray(list)) return [];
  const _list: { display: string; width: string }[] = [];
  let width = 0;
  let count = 0;
  list.forEach((item) => {
    if (typeof item === 'number') {
      width += item;
    } else {
      count += 1;
    }
  });

  list.forEach((item) => {
    if (typeof item === 'number') {
      _list.push({ display: 'inline-block', width: `${item}px` });
    } else {
      _list.push({ display: 'inline-block', width: `calc(${item} - ${width / count}px)` });
    }
  });
  return _list;
};

export function getFieldKeyValue<T>(record: T, index: number, field: stringAndFunc<T>) {
  const recordKey = typeof field === 'function' ? field(record, index) : get(record, field);
  return recordKey === undefined ? index : recordKey;
}

export const searchSelect = {
  allowClear: true,
  showSearch: true,
  optionFilterProp: 'children',
  filterOption: (input: string, option: any) => {
    const getValue = (dom: React.ReactNode): string => {
      const _value = get(dom, 'props.children');
      if (Array.isArray(_value)) {
        const d = map(_value, (item) => {
          if (isValidElement(item)) {
            return getValue(item);
          }
          return item;
        });
        return join(d, '');
      }
      if (isValidElement(_value)) {
        return getValue(_value);
      }
      return join(_value, '');
    };

    const str = getValue(option);
    return str.toLowerCase().indexOf(input.toLowerCase()) >= 0;
  },
};

// jiesuan 项目中使用的计算中文、全角字符 x2
export const calculateStrLength = (name?: string | number): number => {
  if (name === null || name === void 0) return 0;
  if (typeof name === 'number') {
    // eslint-disable-next-line no-param-reassign
    name = `${name}`;
  }
  let count = 0;
  const strArr = Array.from(name);
  strArr.forEach((c) => {
    // eslint-disable-next-line no-control-regex
    if (/[\x00-\xff]/.test(c)) {
      count += 1;
    } else {
      count += 2;
    }
  });
  return count;
};

export const convertMoney = (money: string | number) => {
  return nzhcn.encodeB(money, { tenMin: true });
};

interface NoLabelLayoutValueProps {
  labelCol?: ColProps;
  wrapperCol?: ColProps;
  offset?: number;
}
// 处理 label 宽度
export const getLabelLayout = ({ labelCol, wrapperCol, offset = 0 }: NoLabelLayoutValueProps) => {
  const labelLayoutValue = {};
  const noLabelLayoutValue = {};
  const labelSpan = get(labelCol, 'span');
  const wrapperSpan = get(wrapperCol, 'span');
  if (labelSpan) {
    set(labelLayoutValue, ['labelCol', 'span'], Number(labelSpan) + offset);
    set(labelLayoutValue, ['wrapperCol', 'span'], Number(wrapperSpan) - offset);
    set(noLabelLayoutValue, ['wrapperCol', 'offset'], Number(labelSpan) + offset);
    set(noLabelLayoutValue, ['wrapperCol', 'span'], Number(wrapperSpan) - offset);
  } else {
    mapKeys(labelCol, (value, key) => {
      set(labelLayoutValue, ['labelCol', key, 'span'], value.span + offset);
      set(noLabelLayoutValue, ['wrapperCol', key, 'offset'], value.span + offset);
    });
    mapKeys(wrapperCol, (value, key) => {
      set(labelLayoutValue, ['wrapperCol', key, 'span'], value.span - offset);
      set(noLabelLayoutValue, ['wrapperCol', key, 'span'], value.span - offset);
    });
  }

  return { noLabelLayoutValue, labelLayoutValue };
};
// 返回上一级 name 的数据
export const getParentNameData = (values: any, name: YFormItemProps['name']) => {
  const _values = { ...values };
  const _name = isArray(name) ? name : [name];
  if (_name.length === 1) {
    return _values;
  }
  return get(_values, _name.slice(0, _name.length - 1));
};

export function submitFormatValues(
  values: KeyValue,
  formatFieldsValue?: FormatFieldsValue[],
): KeyValue {
  const _values = mergeWithDom({}, values);
  const list: FormatFieldsValue[] = sortBy(formatFieldsValue, (item) => {
    if (!item) return;
    if (isArray(item.name)) {
      return -item.name.length;
    }
    return -`${item.name}`.length;
  }).filter((x) => x);
  forEach(list, (item) => {
    const { name, format } = item;
    if (name && format) {
      const parentValue = getParentNameData(values, name);
      // 如果上一级是 undefined,则不处理该字段。(List add 会生成空对象)
      if (parentValue === undefined) return;
      try {
        set(_values, name, format(get(values, name), parentValue, values));
      } catch (error) {
        // 如果 format 代码报错这里抛出异常
        // eslint-disable-next-line no-console
        console.error(error);
        warning(false, error);
      }
    }
  });
  return _values;
}

export const onFormatFieldsValue = (formatFieldsValue: FormatFieldsValue[]) => {
  return (list: FormatFieldsValue[]) => {
    const _formatFields = formatFieldsValue;
    forEach(list, (item) => {
      // 已存在不再注册
      if (!find(_formatFields, { name: item.name })) {
        _formatFields.push(item);
      }
    });
    return _formatFields;
  };
};

export const paramsType = (params?: ParamsType) => {
  const _params = params || ({} as ParamsType);
  const type = {
    id: _params.id,
    edit: _params.type === 'edit',
    create: _params.type === 'create',
    view: _params.type === 'view',
  };
  let typeName = '';
  if (type.create) typeName = '新建';
  if (type.edit) typeName = '编辑';
  if (type.view) typeName = '查看';

  return { ...type, typeName };
};

export const useImmutableValue = (value: any) => {
  const v = useRef(value);
  if (!isEqual(value, v.current)) {
    v.current = value;
  }
  return v.current;
};