/* eslint-disable prefer-destructuring */
import * as React from 'react';
import {
  useEffect,
  useMemo,
  useState,
  useCallback,
} from 'react';
import * as moment from "moment";
import {
  FastForm,
} from 'components/ui';
import Action from 'components/basic/Action';
import { Component } from 'components/types';
import { App } from 'utils/types';
import { setDefaultValue } from 'utils/tool';
import { isArray } from 'utils/isType';
import { FormTypes } from './types';

const useForm = (props: FormTypes.FormProps) => {
  const {
    loaderUuid,
    config,
    handle,
    compRef,
    dict,
  } = props;

  const {
    uuid,
    forms,
    action = [],
    // ajax,
  } = config;

  // 生成表单初始值
  const initialValues = useMemo(() => {
    const defaultData = {};
    for (let i = 0, len = forms.length; i < len; i += 1) {
      const item = forms[i];
      const { key, type, defaultValue } = item;
      if (type === 'multuploadimage') {
        defaultData[key] = ((defaultValue as string[]) || [])
          .map((_item: string) => ({ url: _item }));
      } else {
        defaultData[key] = setDefaultValue(defaultValue);
      }
    }
    return defaultData;
  }, [forms]);

  const [formInstance] = FastForm.useForm();
  const [values, setValues] = useState(initialValues);
  const [formList, setFormList] = useState(forms);

  // 格式化输出数据
  const formatData = (rawData: App.Dict) => {
    const newData: App.Dict = {};
    for (let i = 0, len = forms.length; i < len; i += 1) {
      const item = forms[i];
      const {
        notSubmit,
        key,
        type,
        exportFormat,
        ajaxKey,
        notSwitchArrToStr,
        switchArrToStrSeparator = ",",
        keys,
      } = item;
      if (!notSubmit && !keys) {
        if (isArray(rawData[key]) && !notSwitchArrToStr) {
          newData[ajaxKey || key] = rawData[key].join(switchArrToStrSeparator);
        } else {
          newData[ajaxKey || key] = rawData[key];
        }
        if (type === "multuploadimage") {
          newData[key] = rawData[key]
            .map((_item: any) => _item.url)
            .join(switchArrToStrSeparator);
        }
        if (exportFormat === "expand") {
          if (rawData[key]) {
            Object.keys(rawData[key]).forEach((childKey: string) => {
              newData[childKey] = rawData[key][childKey];
            });
            delete newData[key];
          }
        }
        if (exportFormat === "json2Str") {
          newData[key] = JSON.stringify(rawData[key]);
        }
      }
      if (keys?.length) {
        newData[keys[0]] = rawData[key] ? rawData[key][0] : "";
        newData[keys[1]] = rawData[key] ? rawData[key][1] : "";
        // delete rawData[key];
      }
    }
    return newData;
  };

  // 格式化输入数据
  const formatImportData = (rawData: App.Dict) => {
    const newData = {};
    for (let i = 0, len = forms.length; i < len; i += 1) {
      const item = forms[i];
      const { key, resKey, defaultValue, dataSrc, importFormat, format, keys } =
        item;
      if (dataSrc === "default") {
        newData[key] = defaultValue;
      } else {
        newData[key] = rawData[resKey || key];
      }

      // importFormat 格式化
      if (importFormat === "number") {
        newData[key] = Number(newData[key]);
      } else if (importFormat === "string") {
        newData[key] = newData[key].toString();
      } else if (importFormat === "json2Str") {
        newData[key] = JSON.stringify(newData[key]);
      } else if (importFormat === "str2Json") {
        newData[key] = JSON.parse(newData[key]);
      } else if (importFormat === "str2arr") {
        newData[key] = newData[key] ? newData[key].split(",") : [];
      } else if (importFormat === "time") {
        newData[key] = newData[key] ? moment(newData[key]).format(format) : "";
      }

      if (keys?.length) {
        newData[key] = [rawData[keys[0]], rawData[keys[1]]];
        newData[keys[0]] = rawData[keys[0]];
        newData[keys[1]] = rawData[keys[1]];
      }
    }
    return newData;
  };

  // 获取表单详情
  const handleFetchData = useCallback((data: App.Dict) => {
    const formatedData = formatImportData(data);
    setValues(formatedData);
    formInstance.setFieldsValue(formatedData);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // 重置表单
  const resetHandler = () => {
    setValues(initialValues);
  };

  // 更新form列表
  const updateFormList = () => {
    const newForms = [];
    for (let i = 0, len = forms.length; i < len; i += 1) {
      const item = forms[i];
      const { interact } = item;
      if (interact) {
        const { type, trigger, triggerKey } = interact;
        if (trigger === "contain") {
          const { triggerValue = [] } = interact;
          if (type === "show") {
            if (isArray(triggerKey)) {
              const isShow = (triggerKey as string[]).every((triggerKeyItem: string, index: number) => {
                return (
                  triggerValue[index].includes(values[triggerKeyItem as string]) ||
                  (values[triggerKeyItem] === undefined &&
                    triggerValue[index].includes("undefined"))
                )
              });
              if (isShow) {
                newForms.push(item);
              }
            } else {
              if (
                triggerValue.includes(values[triggerKey as string]) ||
                (values[triggerKey as string] === undefined &&
                  triggerValue.includes("undefined"))
              ) {
                newForms.push(item);
              }
            }
          } else if (type === "disabled") {
            if (triggerValue.includes(values[triggerKey as string])) {
              newForms.push({ ...item, notModify: true });
            } else {
              newForms.push(item);
            }
          }
        } else if (trigger === "notContain") {
          const { triggerValue = [] } = interact;
          if (type === "show") {
            if (isArray(triggerKey)) {
              const isShow = (triggerKey as string[]).every((triggerKeyItem: string, index: number) => {
                return (
                  !triggerValue[index].includes(values[triggerKeyItem as string]) &&
                  !(
                    values[triggerKeyItem] === undefined &&
                    triggerValue[index].includes("undefined")
                  )
                )
              });
              if (isShow) {
                newForms.push(item);
              }
            } else {
              if (
                !triggerValue.includes(values[triggerKey as string]) &&
                !(
                  values[triggerKey as string] === undefined &&
                  (triggerValue as string[]).includes("undefined")
                )
              ) {
                newForms.push(item);
              }
            }
          } else if (type === "disabled") {
            if (!triggerValue.includes(values[triggerKey as string])) {
              newForms.push({ ...item, notModify: true });
            } else {
              newForms.push(item);
            }
          }
        } else {
          newForms.push(item);
        }
      } else {
        newForms.push(item);
      }
    }
    setFormList(newForms);
  };

  useEffect(updateFormList, [forms, values]);

  // 生成行为按钮
  const createActionBtns = (
    actionList: Component.Business.Action[],
    data?: App.Dict
  ) =>
    actionList.map((actionItem: Component.Business.Action) => {
      const { type } = actionItem;
      let handleActionClick = null;
      let bindActionClick = null;
      let formatedData = data;

      if (type === Component.Business.TriggerType.reset) {
        handleActionClick = resetHandler;
      }
      if (type === Component.Business.TriggerType.submit) {
        bindActionClick = () => formInstance.validateFields();
        formatedData = formatData(values);
      }
      return (
        <Action
          moduleUuid={uuid}
          loaderUuid={loaderUuid}
          action={actionItem}
          handle={handle}
          data={formatedData}
          onActionClick={handleActionClick}
          bindActionClick={bindActionClick}
        />
      );
    });

  // 向父组件暴露实例方法
  const getInstance = () => {
    compRef.current = {
      ...compRef.current,
      [uuid]: {
        fetchData: handleFetchData,
      },
    };
  };

  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(getInstance, []);

  return {
    formList,
    dict,
    actionList: action,
    formInstance,
    initialValues,
    values,
    setValues,
    createActionBtns,
  };
};

export default useForm;
