import { ComponentOptions, h, resolveComponent } from 'vue';
import { VxeColumnPropTypes, VxeGlobalRendererHandles } from 'vxe-table';
import { Select, SelectOption, SelectOptGroup } from 'ant-design-vue';
import XEUtils from 'xe-utils';
import { cellText, createCellRender, createEvents, createProps, isEmptyValue, createExportMethod, createFormItemRender } from './common';

function renderOptions(options: any[], optionProps: VxeGlobalRendererHandles.RenderOptionProps) {
  const labelProp = optionProps.label || 'label';
  const valueProp = optionProps.value || 'value';
  return XEUtils.map(options, (item, oIndex) => {
    return h(
      SelectOption,
      {
        key: oIndex,
        value: item[valueProp],
        disabled: item.disabled,
      },
      {
        default: () => cellText(item[labelProp]),
      },
    );
  });
}

function createEditRender() {
  return function (renderOpts: VxeColumnPropTypes.EditRender, params: VxeGlobalRendererHandles.RenderEditParams) {
    const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
    const { row, column, $table } = params;
    const { attrs } = renderOpts;
    const cellValue = XEUtils.get(row, column.field as string);
    const props = createProps(renderOpts, cellValue);
    const ons = createEvents(
      renderOpts,
      params,
      (value: any) => {
        // 处理 model 值双向绑定
        XEUtils.set(row, column.field as string, value);
      },
      () => {
        // 处理 change 事件相关逻辑
        $table.updateStatus(params);
      },
    );
    if (optionGroups) {
      const groupOptions = optionGroupProps.options || 'options';
      const groupLabel = optionGroupProps.label || 'label';
      return [
        h(
          Select,
          {
            ...attrs,
            ...props,
            ...ons,
          },
          {
            default: () => {
              return XEUtils.map(optionGroups, (group, gIndex) => {
                return h(
                  SelectOptGroup,
                  {
                    key: gIndex,
                  },
                  {
                    label: () => {
                      return h('span', {}, group[groupLabel]);
                    },
                    default: () => renderOptions(group[groupOptions], optionProps),
                  },
                );
              });
            },
          },
        ),
      ];
    }
    return [
      h(
        Select,
        {
          ...props,
          ...attrs,
          ...ons,
        },
        {
          default: () => renderOptions(options, optionProps),
        },
      ),
    ];
  };
}

function getSelectCellValue(renderOpts: VxeGlobalRendererHandles.RenderCellOptions, params: VxeGlobalRendererHandles.RenderCellParams) {
  const { options = [], optionGroups, props = {}, optionProps = {}, optionGroupProps = {} } = renderOpts;
  const { row, column } = params;
  const labelProp = optionProps.label || 'label';
  const valueProp = optionProps.value || 'value';
  const groupOptions = optionGroupProps.options || 'options';
  const cellValue = XEUtils.get(row, column.field as string);
  if (!isEmptyValue(cellValue)) {
    return XEUtils.map(
      props.mode === 'multiple' ? cellValue : [cellValue],
      optionGroups
        ? value => {
          let selectItem;
          for (let index = 0; index < optionGroups.length; index++) {
            selectItem = XEUtils.find(optionGroups[index][groupOptions], item => item[valueProp] === value);
            if (selectItem) {
              break;
            }
          }
          return selectItem ? selectItem[labelProp] : value;
        }
        : value => {
          const selectItem = XEUtils.find(options, item => item[valueProp] === value);
          return selectItem ? selectItem[labelProp] : value;
        },
    ).join(', ');
  }
  return '';
}

function createFilterRender() {
  return function (renderOpts: VxeColumnPropTypes.FilterRender, params: VxeGlobalRendererHandles.RenderFilterParams) {
    const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
    const groupOptions = optionGroupProps.options || 'options';
    const groupLabel = optionGroupProps.label || 'label';
    const { column } = params;
    const { attrs } = renderOpts;

    return [
      h(
        'div',
        {
          class: 'vxe-table--filter-antd-wrapper',
        },
        optionGroups
          ? column.filters.map((option, oIndex) => {
            const optionValue = option.data;
            const props = createProps(renderOpts, optionValue);

            return h(
              Select,
              {
                key: oIndex,
                ...attrs,
                ...props,
                ...createEvents(
                  renderOpts,
                  params,
                  (value: any) => {
                    // 处理 model 值双向绑定
                    option.data = value;
                  },
                  () => {
                    // 处理 change 事件相关逻辑
                    const { $panel } = params;
                    $panel.changeOption(
                      null,
                      props.mode === 'multiple' ? option.data && option.data.length > 0 : !XEUtils.eqNull(option.data),
                      option,
                    );
                  },
                ),
              },
              {
                default: () => {
                  return XEUtils.map(optionGroups, (group, gIndex) => {
                    return h(
                      SelectOptGroup,
                      {
                        key: gIndex,
                      },
                      {
                        label: () => {
                          return h('span', {}, group[groupLabel]);
                        },
                        default: () => renderOptions(group[groupOptions], optionProps),
                      },
                    );
                  });
                },
              },
            );
          })
          : column.filters.map((option, oIndex) => {
            const optionValue = option.data;
            const props = createProps(renderOpts, optionValue);
            return h(
              Select,
              {
                key: oIndex,
                ...attrs,
                ...props,
                ...createEvents(
                  renderOpts,
                  params,
                  (value: any) => {
                    // 处理 model 值双向绑定
                    option.data = value;
                  },
                  () => {
                    // 处理 change 事件相关逻辑
                    const { $panel } = params;
                    $panel.changeOption(
                      null,
                      props.mode === 'multiple' ? option.data && option.data.length > 0 : !XEUtils.eqNull(option.data),
                      option,
                    );
                  },
                ),
              },
              {
                default: () => renderOptions(options, optionProps),
              },
            );
          }),
      ),
    ];
  };
}

export default {
  renderEdit: createEditRender(),
  renderCell: createCellRender(getSelectCellValue),
  renderFilter: createFilterRender(),
  defaultFilterMethod(params) {
    const { option, row, column } = params;
    const { data } = option;
    const { field, filterRender: renderOpts } = column;
    const { props = {} } = renderOpts;
    const cellValue = XEUtils.get(row, field);
    if (props.mode === 'multiple') {
      if (XEUtils.isArray(cellValue)) {
        return XEUtils.includeArrays(cellValue, data);
      }
      return data.indexOf(cellValue) > -1;
    }
    return cellValue == data;
  },
  renderItemContent: createFormItemRender(),
  exportMethod: createExportMethod(getSelectCellValue),
};
