import React from 'react';
import isPlainObject from 'lodash/isPlainObject';
import {
  compileTextExpr2,
  __ds__,
  __record__,
  __urlParams__,
  getDataSourceList,
  handleI18nLabel,
} from '../../util/util';
import {
  __dataSource__,
  __paging__,
  __selectedRowKeys__,
  __step_current__,
  __tableColumns__,
  __tableCurrentRow__,
  __tableData__,
  __tableExtra__,
  __totalCount__,
  tableCurrentRowLabel,
} from '@/common/util/expr-const';
import isString from 'lodash/isString';

import './index.scss';

const { Input, Select, NumberPicker } = window.CNUI || {};

const symbolList2 = ['==', '!=', '>', '<', '>=', '<='];
const typeList = [
  {
    label: '文本',
    value: 'string',
  },
  {
    label: '数字',
    value: 'number',
  },
  {
    label: '布尔',
    value: 'boolean',
  },
  {
    label: '数组',
    value: 'array',
  },
];

export default class ExprSetter extends React.Component {
  static displayName = 'ExprSetter';
  constructor(props) {
    super(props);
    this.state = {
      list: [],
      map: {},
    };
  }

  componentDidMount() {
    const { configList, field, value, onChange } = this.props;
    let state;
    if (configList?.length > 0) {
      const temp = this.getList() || {};
      const { list, map = {} } = temp;
      if (list?.length > 0) {
        state = {
          list,
          map,
        };
      }
    }

    const objectExpr = this.transTextExprToObjectExpr(
      value,
      configList?.[0].groupExprName,
    );
    if (objectExpr) {
      onChange?.(objectExpr);
    }

    if (state) {
      this.setState(state);
    }
  }

  transTextExprToObjectExpr = (str, defaultGroupName) => {
    let expr;
    const { configList = [] } = this.props;
    if (typeof str === 'string' && str.length > 0) {
      const exprObj = compileTextExpr2(str) || {};
      const {
        attr,
        dataSourceName,
        symbol,
        type = 'string',
        urlParamsKey,
        value,
      } = exprObj;
      if (attr && symbol && type) {
        if (attr === __urlParams__) {
          if (urlParamsKey) {
            expr = {
              group: __dataSource__,
              param: 'urlParams',
              symbol,
              type,
              value,
              secondParam: urlParamsKey,
            };
          }
        } else if (this.isDataSource(attr)) {
          if (dataSourceName) {
            expr = {
              group: __dataSource__,
              param: dataSourceName,
              symbol,
              type,
              value,
              secondParam: urlParamsKey,
            };
          }
        } else if (attr?.startsWith(__record__) && configList?.[0]) {
          const key = attr.replace(`${__record__}.`, '');
          if (key && defaultGroupName) {
            expr = {
              group: defaultGroupName,
              param: key,
              symbol,
              type,
              value,
            };
          }
        }
      }
    }
    return expr;
  };

  isDataSource = (str) => {
    if (str) {
      return str === __urlParams__ || str?.startsWith(__ds__);
    }
  };

  getList = () => {
    const { field, configList } = this.props;
    let result = [];
    const map = {};
    const newList = [];
    if (Array.isArray(configList) && configList.length > 0) {
      configList.forEach((item) => {
        const {
          dataKey,
          labelKey,
          valueKey,
          groupName,
          groupExprName,
          handleCustomGroup,
        } = item;
        if (groupExprName) {
          if (groupExprName === __dataSource__) {
            const extra = {
              label: '其他数据',
              children: [],
            };

            const dsList = getDataSourceList({ typeList: ['URI', 'VALUE'] });
            if (dsList.length > 0) {
              dsList.forEach((item) => {
                if (item) {
                  const { label, value, componentName } = item;
                  extra.children.push({
                    label: handleI18nLabel(label),
                    value: `${groupExprName}.${value}`,
                    componentName,
                  });
                }
              });
            }
            result.push(extra);
          } else if (dataKey === 'arrayTable') {
            const path = field?.path;
            if (Array.isArray(path) && path.length > 3) {
              const arrayTableIndex = path[1];
              if (arrayTableIndex !== undefined) {
                const formConfig = field?.getNode?.()?.getPropValue?.('config');
                const arrayTableConfig = formConfig?.[arrayTableIndex] || {};
                if (
                  arrayTableConfig?.componentName === 'CnFormArrayCard' &&
                  arrayTableConfig?.options?.config?.length > 0
                ) {
                  const tempList = arrayTableConfig?.options?.config;
                  result.push({
                    label: groupName,
                    children: tempList
                      .filter((item2) => item2.name)
                      .map((item2) => {
                        return {
                          label: handleI18nLabel(item2?.[labelKey]),
                          value: `${groupExprName}.${item2?.[valueKey] || ''}`,
                        };
                      }),
                  });
                }
              }
            }
          } else if (typeof handleCustomGroup === 'function') {
            const temp = handleCustomGroup();
            if (isPlainObject(temp)) {
              result.push(temp);
            }
          } else {
            let originList;
            try {
              originList = field?.getNode?.()?.getPropValue?.(dataKey);
            } catch (e) {}
            if (originList?.length > 0) {
              originList.forEach((item) => {
                const value = item[valueKey];
                let label = handleI18nLabel(item[labelKey]) || value;
                label = label && isString(label) ? label : value;
                if (value) {
                  newList.push({
                    label,
                    value: `${groupExprName}.${value}`,
                  });
                }
              });
            }
            if (newList?.length > 0) {
              if (groupName) {
                result.push({
                  label: groupName,
                  children: newList,
                });
              } else {
                result = [...newList];
              }
            }
          }
          map[groupExprName] = {
            ...item,
          };
        }
      });
    }
    return {
      list: result,
      map,
    };
  };

  getValueEditor = (type, v, value) => {
    const { size = 'small' } = this.props;
    const props = {
      size,
      className: 'ctes-input',
      value: v,
      onChange: (v) => {
        this.changeValue(value, {
          value: v,
        });
      },
    };
    switch (type) {
      case 'number':
        return <NumberPicker placeholder={'空'} {...props} />;
      case 'boolean':
        return (
          <Select
            placeholder={'空'}
            hasClear
            dataSource={[
              { label: 'true', value: true },
              { label: 'false', value: false },
            ]}
            {...props}
          />
        );
      default:
        return <Input placeholder={'空'} {...props} />;
    }
  };

  changeValue = (value, newValue) => {
    const { onChange } = this.props;
    const newExprObj = { ...value, ...newValue };
    onChange && onChange(newExprObj);
  };

  findComponentNameByDs = (ds) => {
    const { list } = this.state;
    if (Array.isArray(list)) {
      for (const item of list) {
        if (Array.isArray(item?.children)) {
          for (const item2 of item.children) {
            if (item2?.value === ds) {
              return item2?.componentName;
            }
          }
        }
      }
    }
  };

  getPropKeyInput = (config) => {
    const { secondParam, value, size, currentComponentName } = config;
    if (currentComponentName === 'CnTable') {
      return (
        <Select
          placeholder={'属性名'}
          value={secondParam || ''}
          onChange={(v) => {
            this.changeValue(value, {
              secondParam: v,
              thirdParam: undefined,
            });
          }}
          size={size}
          autoWidth={false}
          className={'ctes-input'}
          dataSource={[
            {
              label: '选中数据主键列表(selectedRowKeys)',
              value: __selectedRowKeys__,
            },
            {
              label: tableCurrentRowLabel,
              value: __tableCurrentRow__,
            },
            {
              label: '请求返回的总条数(paging.totalCount)',
              value: __totalCount__,
            },
            {
              label: '表格请求返回的数据(tableData)',
              value: __tableData__,
            },
            {
              label: '表格的列头(columns)',
              value: __tableColumns__,
            },
            {
              label: '表格请求返回的分页信息(paging)',
              value: __paging__,
            },
            {
              label: '请求返回的额外信息(extra)',
              value: __tableExtra__,
            },
          ]}
        />
      );
    } else if (currentComponentName === 'CnStep') {
      return (
        <Select
          placeholder={'属性名'}
          value={secondParam || ''}
          onChange={(v) => {
            this.changeValue(value, {
              secondParam: v,
              thirdParam: undefined,
            });
          }}
          size={size}
          autoWidth={false}
          className={'ctes-input'}
          dataSource={[
            {
              label: '当前步骤(current)',
              value: __step_current__,
            },
          ]}
        />
      );
    }
    return (
      <Input
        placeholder={'属性名'}
        value={secondParam || ''}
        onChange={(v) => {
          this.changeValue(value, {
            secondParam: v,
          });
        }}
        size={size}
        className={'ctes-input'}
      />
    );
  };

  render() {
    const { list, map } = this.state;
    let { value, size = 'small', placeholder } = this.props;
    if (!isPlainObject(value)) {
      value = {};
    }
    const {
      group,
      param,
      symbol,
      type,
      value: v,
      secondParam,
      thirdParam,
    } = value;
    const symbolDom = (
      <Select
        value={symbol || ''}
        hasClear
        size={size}
        className={'ctes-input ctes-symbol-input'}
        dataSource={symbolList2}
        onChange={(v) => {
          this.changeValue(value, {
            symbol: v,
          });
        }}
      />
    );
    const { renderTypeDom, renderValueDom } = map?.[group] || {};
    const showSecondParam = map?.[group]?.needSecondParam;
    const currentDs = group && param ? `${group}.${param}` : '';
    const currentComponentName = this.findComponentNameByDs(currentDs);
    const needThirdParam =
      currentComponentName === 'CnTable' &&
      (secondParam === __tableCurrentRow__ || secondParam === __tableExtra__);
    return (
      <div className='cn-text-expr-setter-wrap'>
        <div className='ctes-first-line'>
          <Select
            placeholder={placeholder || '请选择'}
            hasClear
            value={currentDs}
            autoWidth={false}
            size={size}
            className={'ctes-input'}
            dataSource={list}
            onChange={(v) => {
              const newV = {
                group: undefined,
                param: undefined,
                secondParam: undefined,
                thirdParam: undefined,
              };
              if (v && v?.indexOf('.') !== -1) {
                const tempGroup = v.slice(0, v.indexOf('.')) || '';
                const tempParam = v.replace(`${tempGroup}.`, '');
                if (tempGroup && tempParam) {
                  newV.group = tempGroup;
                  newV.param = tempParam;
                }
              }
              this.changeValue(value, newV);
            }}
          />
          {showSecondParam &&
            this.getPropKeyInput({
              value,
              secondParam,
              size,
              currentComponentName,
            })}
          {needThirdParam && (
            <Input
              placeholder={'属性名'}
              value={thirdParam || ''}
              size={size}
              className={'ctes-input'}
              onChange={(v) => {
                this.changeValue(value, {
                  thirdParam: v,
                });
              }}
            />
          )}
          {!showSecondParam && (
            <Select
              placeholder={'满足'}
              hasClear
              value={symbol || ''}
              size={size}
              className={'ctes-input ctes-symbol-input'}
              dataSource={symbolList2}
              onChange={(v) => {
                this.changeValue(value, {
                  symbol: v,
                });
              }}
            />
          )}
        </div>
        <div className='ctes-second-line'>
          {showSecondParam && symbolDom}
          {typeof renderTypeDom === 'function' ? (
            renderTypeDom({ value })
          ) : (
            <Select
              hasClear
              value={type}
              size={size}
              className={'ctes-input'}
              dataSource={typeList}
              onChange={(v) => {
                this.changeValue(value, {
                  type: v,
                  value: undefined,
                });
              }}
            />
          )}
          {typeof renderValueDom === 'function'
            ? renderValueDom({
                value,
                onChange: this.changeValue,
              })
            : this.getValueEditor(type, v, value)}
        </div>
      </div>
    );
  }
}
