import { StepsForm } from '@ant-design/pro-form';
import type { ProFormInstance } from '@ant-design/pro-form';
import { Drawer, Space } from 'antd';
import { Children, cloneElement, isValidElement, memo, useEffect, useRef, useState } from 'react';
import { FormattedMessage, useDispatch, useIntl } from 'umi';

import { useBindFeature } from '../BindFeature/hooks';
import { useBindData } from '../BindData/hooks';
import { useBindRoleOrPolicy } from '../BindRole/hooks';
import _ from 'lodash';
import FeatureStep from './FeatureStep';
import FlagStep from './FlagStep';
import PolicyStep from './PolicyStep';
import RoleStep from './RoleStep';
interface CopyPermissionPrpos {
  /**
   * @description feature 绑定的类型，目前支持如下两种。
   * @type 'feature' | 'option' | 'policy' | 'user'
   */
  type: 'feature' | 'option' | 'policy' | 'user' | 'role'; // 选择类型
  /**
   * @description 绑定的类型的id，如type选了user，就要传入userId。
   */
  id?: number; // 默认参数
  /**
   * @description 标题
   */
  title?: string;
  /**
   * @description 自定义标题
   */
  titleRender?: () => any;
  /**
   * @description 自定义底部说明整体内容
   */
  footerRender?: () => any;
  /**
   * @description 自定义按钮
   */
  linkRender?: () => any;
  /**
   * @description 名称
   */
  name?: string;
  /**
   * @description 需要复制的权限
   */
  copyList?: ('feature' | 'flag' | 'policy' | 'role')[];
  /**
   * @description 是否有有效期。
   */
  isHaveDate?: boolean;
  /**
   * @description 可以自定义触发内容，默认是<a>角色</a>
   */
  children?: React.ReactChildren | React.ReactElement;
  /**
   * @description 结束需要做的事
   */
  onFinish?: (values, ref: ProFormInstance, setOpen, cb: () => void) => void;
  /**
   * @description 点击复制按钮以后的回调函数
   */
  onClick?: () => void;
}
const CopyPermission = ({
  children,
  onClick,
  id,
  type = 'user',
  isHaveDate = false,
  title = '',
  titleRender,
  footerRender,
  linkRender,
  name = '',
  copyList = ['feature', 'flag', 'policy', 'role'],
  onFinish,
}: CopyPermissionPrpos) => {
  const { formatMessage } = useIntl();
  const dispatch = useDispatch();
  const [open, setOpen] = useState(false);
  const baseFormRef = useRef<ProFormInstance>();
  const featureFormRef = useRef<ProFormInstance>();
  const dataFormRef = useRef<ProFormInstance>();
  const roleFormRef = useRef<ProFormInstance>();
  const policyFormRef = useRef<ProFormInstance>();
  const {
    featureTreeData,
    initFetch,
    updateFn: featureUpdateFn,
    loading,
    title: featureTitle,
    list,
  } = useBindFeature({
    name: 'features',
    id,
    type,
    isHaveDate,
    form: featureFormRef,
  });
  const {
    initFetch: dataInitFetch,
    updateFn: dataUpdateFn,
    loading: dataLoading,
    // activeKey: dataActiveKey,
    // setActiveKey: dataSetActiveKey,
    flagList: dataFlagList,
    getSelectOptions: dataGetSelectOptions,
    selectMap: dataSelectMap,
    title: dataTitle,
    appId,
  } = useBindData({ name: 'flags', type, id, isHaveDate, form: dataFormRef });

  const {
    allData: roleAllData,
    loading: roleLoading,
    initFetch: roleInitFetch,
    updateFn: roleUpdateFn,
    title: roleTitle,
    list: roleList,
  } = useBindRoleOrPolicy({
    name: 'roles',
    comType: 'role',
    type,
    id,
    form: roleFormRef,
    isHaveDate,
  });
  const {
    allData: policyAllData,
    loading: policyLoading,
    initFetch: policyInitFetch,
    updateFn: policyUpdateFn,
    title: policyTitle,
    list: policyList,
  } = useBindRoleOrPolicy({
    name: 'policies',
    comType: 'policy',
    type,
    id,
    form: policyFormRef,
    isHaveDate,
  });
  const [values, setValues] = useState({});
  // 使用 React.cloneElement 来给 children 添加属性
  const childrenWithProps = Children.map(children, (child) => {
    // 检查元素类型以防止添加属性到非元素节点
    if (isValidElement(child)) {
      // @ts-ignore
      return cloneElement(child, { formRef: baseFormRef }); // 添加特定的属性
    }
    return child;
  });
  useEffect(() => {
    if (open) {
      baseFormRef?.current?.setFieldsValue(values);
    }
  }, [open, values, baseFormRef, copyList]);
  useEffect(() => {
    if (open && isHaveDate) {
      dispatch({
        type: 'public/fetchAppDetail',
        payload: appId,
      });
    }
  }, [open, appId, isHaveDate, dispatch]);

  const items = [
    {
      title: `${title}${formatMessage({ id: 'component.copy.steps.title' })}`,
    },
  ];
  if (copyList?.includes('feature')) {
    items.push({ title: featureTitle });
  }
  if (copyList?.includes('flag')) {
    items.push({ title: dataTitle });
  }
  if (copyList?.includes('role')) {
    items.push({ title: roleTitle });
  }
  if (copyList?.includes('policy')) {
    items.push({ title: policyTitle });
  }

  return (
    <>
      <StepsForm
        containerStyle={{ width: '100%' }}
        stepsProps={{
          items,
        }}
        stepsFormRender={(dom, submitter) => {
          return (
            <Drawer
              title={
                titleRender
                  ? titleRender?.()
                  : `${title}${formatMessage({
                      id: 'component.copy.container.title',
                    })}（${name}）`
              }
              width="800px"
              open={open}
              keyboard={false}
              maskClosable={false}
              onClose={() => setOpen(false)}
              footer={
                footerRender ? (
                  footerRender?.()
                ) : (
                  <>
                    <div>
                      <strong>
                        <FormattedMessage id="component.copy.footer.title" />
                      </strong>
                    </div>
                    <div>
                      <FormattedMessage id="component.copy.footer.content" />
                    </div>
                  </>
                )
              }
              extra={<Space>{submitter}</Space>}
            >
              {dom}
            </Drawer>
          );
        }}
        onFinish={async (val) => {
          const { features, flags, policies, roles, ...base } = val;
          let options: number[] = [];
          _.keys(flags).forEach((key) => {
            options = [
              ...options,
              ...flags[key]?.data?.map((item: any) => ({
                ...item,
                flagId: parseInt(key?.replace('data', ''), 10),
              })),
            ];
          });
          await onFinish?.(
            {
              base,
              features: features?.data,
              options,
              policies: policies?.data,
              roles: roles?.data,
            },
            baseFormRef,
            setOpen,
            async (createId) => {
              await [
                copyList?.includes('feature') &&
                  featureUpdateFn(features?.data, [], (item: number, map: {}) => ({
                    featureId: item,
                    appId,
                    [`${type}Id`]: createId,
                    expiredAt:
                      (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) ||
                      undefined,
                  })),
                copyList?.includes('flag') &&
                  dataUpdateFn(flags, {}, (item, map) => ({
                    appId,
                    flagId: map?.[item]?.flagId,
                    optionId: item,
                    [`${type}Id`]: createId,
                    expiredAt:
                      (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) ||
                      undefined,
                  })),
                copyList?.includes('role') &&
                  roleUpdateFn(roles?.data, [], (item: number, map: {}) => ({
                    [`roleId`]: item,
                    appId,
                    [`${type}Id`]: createId,
                    expiredAt:
                      (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) ||
                      undefined,
                  })),
                copyList?.includes('policy') &&
                  policyUpdateFn(policies?.data, [], (item: number, map: {}) => ({
                    [`policyId`]: item,
                    appId,
                    [`${type}Id`]: createId,
                    expiredAt:
                      (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) ||
                      undefined,
                  })),
              ];
            },
          );
          setValues({});
          return true;
        }}
      >
        <StepsForm.StepForm
          formRef={baseFormRef}
          onValuesChange={(changeVal, val) => setValues(val)}
          onFinish={async () => {
            return true;
          }}
        >
          {childrenWithProps}
        </StepsForm.StepForm>
        {copyList?.includes('feature') ? (
          <StepsForm.StepForm
            formRef={featureFormRef}
            onFinish={async () => {
              return true;
            }}
          >
            <FeatureStep
              initFetch={initFetch}
              show={copyList?.includes('feature') && open}
              isHaveDate={isHaveDate}
              loading={loading}
              list={list}
              featureTreeData={featureTreeData}
            />
          </StepsForm.StepForm>
        ) : null}
        {copyList?.includes('flag') ? (
          <StepsForm.StepForm
            formRef={dataFormRef}
            onFinish={async () => {
              return true;
            }}
          >
            <FlagStep
              dataInitFetch={dataInitFetch}
              show={copyList?.includes('flag') && open}
              isHaveDate={isHaveDate}
              dataLoading={dataLoading}
              dataSelectMap={dataSelectMap}
              dataFlagList={dataFlagList}
              dataGetSelectOptions={dataGetSelectOptions}
            />
          </StepsForm.StepForm>
        ) : null}
        {copyList?.includes('role') ? (
          <StepsForm.StepForm
            formRef={roleFormRef}
            onFinish={async () => {
              return true;
            }}
          >
            <RoleStep
              show={copyList?.includes('role') && open}
              roleInitFetch={roleInitFetch}
              roleLoading={roleLoading}
              roleAllData={roleAllData}
              isHaveDate={isHaveDate}
              roleList={roleList}
            />
          </StepsForm.StepForm>
        ) : null}
        {copyList?.includes('policy') ? (
          <StepsForm.StepForm
            formRef={policyFormRef}
            onFinish={async () => {
              return true;
            }}
          >
            <PolicyStep
              show={copyList?.includes('policy') && open}
              policyInitFetch={policyInitFetch}
              policyLoading={policyLoading}
              policyAllData={policyAllData}
              isHaveDate={isHaveDate}
              policyList={policyList}
            />
          </StepsForm.StepForm>
        ) : null}
      </StepsForm>
      <a
        onClick={() => {
          onClick?.();
          setOpen(true);
        }}
      >
        {linkRender ? (
          linkRender?.()
        ) : (
          <FormattedMessage id="pages.funcList.copy" defaultMessage="复制" />
        )}
      </a>
    </>
  );
};
export default memo(CopyPermission);
