import useUrlState from '@ahooksjs/use-url-state';
import { DrawerForm } from '@ant-design/pro-form';
import type { DrawerProps } from 'antd';
import { Alert, Col, Form, Row, message } from 'antd';
import _ from 'lodash';
import { cloneElement, useEffect, useRef, useState } from 'react';
import { FormattedMessage, useIntl } from 'umi';
import useAppDetail, { AppDetailContext, useUserData } from '../utils/hooks';
import Detail from './detail';
import './index.less';
import type { NavRef } from './nav';
import Nav from './nav';

export interface ApplyDetailProps {
  open?: boolean;
  setOpen?: (val: boolean) => void;
  id: number;
  onFinish: (values: any) => void;
  children?: any;
  initialValues?: any;
  /**  operation: 运营端配置 multiple: 多应用申请 single: 单人应用申请 */
  useType?: 'multiple' | 'single' | 'operation';
}

const ApplyDetail = (props: ApplyDetailProps) => {
  const {
    open: drawOpen,
    setOpen: setDrawOpen,
    id,
    onFinish,
    children,
    initialValues,
    useType = 'single',
  } = props;
  const ref = useRef<NavRef>(null);
  const { currentUser } = useUserData();
  const { formatMessage } = useIntl();
  const [form] = Form.useForm();

  const [query] = useUrlState();
  const { dataDefined } = query ?? {};

  const [tagKey, setTagKey] = useState<string | undefined>(dataDefined ? '3' : undefined);
  const [value, setValue] = useState<1 | 2>(1);
  const [open, setOpen] = useState<boolean>(false);

  const [defaultFlagIds] = useState<string[]>(() => {
    if (Array.isArray(dataDefined)) {
      return dataDefined.map((item) => String(item));
    } else if (dataDefined) {
      return String(dataDefined)
        .split(',')
        .map((item) => String(item));
    }
    return [];
  });
  const [featureCityIds, setFeatureCityIds] = useState<API.FeatureCityId[]>([]);

  const { appDetail } = useAppDetail(id);
  const { isAllowApplyFlag, roleApprovalForData, applyPolicy } = appDetail || {};

  useEffect(() => {
    if (applyPolicy && currentUser) {
      if (applyPolicy.type === 'dept_blacklist') {
        // 部门 黑名单
        const some = applyPolicy.departs?.some((v: any) =>
          currentUser.departPath?.includes(v.name),
        );
        if (some) {
          // 直接关闭抽屉
          message.error(
            formatMessage({ id: 'component.ApplyDetail.detail.applyPolicy.depart.tips' }),
          );
          setDrawOpen?.(false);
          setOpen(false);
        }
      } else if (applyPolicy.type === 'user_whitelist') {
        // 用户 白名单
        if (!applyPolicy.userIds?.includes(currentUser.id)) {
          message.error(
            formatMessage({ id: 'component.ApplyDetail.detail.applyPolicy.user.tips' }),
          );
          setDrawOpen?.(false);
          setOpen(false);
        }
      }
    }
  }, [applyPolicy, currentUser, formatMessage, setDrawOpen]);

  const triggerRender = () => {
    if (!children) {
      return children;
    }
    return cloneElement(children, {
      onClick: () => {
        setDrawOpen?.(true);
        setOpen(true);
      },
    });
  };

  useEffect(() => {
    if (!_.isUndefined(drawOpen)) {
      setOpen(drawOpen);
    }
  }, [drawOpen]);

  const drawerProps: Omit<DrawerProps, 'visible'> = {
    open,
    width: 1300,
    destroyOnClose: false,
    keyboard: false,
    maskClosable: false,
    bodyStyle: {
      paddingTop: 14,
    },
    onClose: () => {
      setDrawOpen?.(false);
      setOpen(false);
    },
    afterOpenChange: (val: boolean) => {
      if (!val) {
        ref?.current?.reset();
      }
    },
  };

  return (
    <AppDetailContext.Provider value={appDetail}>
      <DrawerForm
        drawerProps={drawerProps}
        title={<FormattedMessage id={'component.ApplyDetail.title'} />}
        form={form}
        trigger={triggerRender()}
        onFinish={async (values: any) => {
          const otherUsers = ref?.current?.getOtherUsers();
          const type = ref?.current?.getType();
          const { flags, policies, roles, features, role, cities } = values;
          const featureIds = features?.data?.filter((item: any) =>
            useType === 'operation' ? item.id : _.isString(item.id),
          );
          const policieIds = policies?.data?.filter((item: any) =>
            useType === 'operation' ? item.id : _.isString(item.id),
          );
          const roleIds = roles?.data?.filter((item: any) =>
            useType === 'operation' ? item.id : _.isString(item.id),
          );
          const cityIds = cities?.data?.filter((item: any) =>
            useType === 'operation' ? item.id : _.isString(item.id),
          );
          const featureCity = featureCityIds.filter((item) =>
            featureIds?.some((element: any) => String(element.id) === String(item.featureId)),
          );
          const flagsIds: any = {};
          // 代理申请，目标用户只有一个用户且为发起人时，申请失败，提示“本人申请权限，请使用本人申请”。
          // 当前用户 currentUser
          if (
            type === 2 &&
            otherUsers?.length === 1 &&
            otherUsers[0].account === currentUser?.account
          ) {
            message.error(formatMessage({ id: 'component.ApplyDetail.apply.for.self.alert' }));
            return;
          }
          _.forEach(
            _.keys(flags),
            (k) =>
              (flagsIds[k] = {
                data: flags[k].data.filter((item: any) => _.isString(item.id)),
              }),
          );
          // 如果有数据权限申请，并且roleApprovalForData 为 2，而且选中了数据，则需要选择角色
          if (
            useType !== 'operation' &&
            isAllowApplyFlag &&
            roleApprovalForData === 2 &&
            _.flatten(_.values(flagsIds).map((item: any) => item?.data || [])).length > 0 &&
            !role?.id
          ) {
            message.error(formatMessage({ id: 'component.ApplyDetail.role.permission.require' }));
            setTagKey('3');
            return;
          } else {
            if (ref?.current?.getType() === 2 && !otherUsers?.length) {
              message.error(formatMessage({ id: 'component.ApplyDetail.apply.for.others.alert' }));
              return;
            }
          }
          const options: any[] = [];
          _.values(flagsIds).forEach((item: any) => {
            options.push(...(item?.data || []));
          });
          if (
            !featureIds?.length &&
            !policieIds?.length &&
            !roleIds?.length &&
            !options?.length &&
            !cityIds?.length
          ) {
            message.error(formatMessage({ id: 'component.ApplyDetail.select.permission.alert' }));
            return;
          }
          onFinish({
            flags: flagsIds,
            policies: { data: policieIds || [] },
            roles: { data: roleIds || [] },
            features: { data: featureIds || [] },
            role,
            roleIdForData: role?.id,
            applyType: ref?.current?.getType(),
            otherUsers,
            cities: { data: cityIds || [] },
            featureCityIds: featureCity,
          });
          return true;
        }}
      >
        {useType !== 'operation' && (
          <Alert
            style={{ marginBottom: 10 }}
            message={
              <span style={{ color: 'red' }}>
                <FormattedMessage id={'component.ApplyDetail.number.alert'} />
              </span>
            }
            type={'warning'}
            showIcon
            closable
          />
        )}

        <Row wrap={false}>
          {useType !== 'operation' && (
            <Col span={8}>
              <Nav
                ref={ref}
                value={value}
                setValue={setValue}
                currentUser={currentUser}
                type={useType}
              />
            </Col>
          )}

          <Col
            span={useType === 'operation' ? 24 : 16}
            style={
              useType !== 'operation'
                ? { borderLeft: '1px solid #e8e8e8', paddingLeft: 10 }
                : undefined
            }
          >
            <Detail
              open={open}
              type={value}
              form={form}
              id={id}
              tagKey={tagKey}
              defaultFlagIds={defaultFlagIds}
              setTagKey={setTagKey}
              initialValues={initialValues}
              currentUser={currentUser}
              useType={useType}
              featureCityIds={featureCityIds}
              setFeatureCityIds={setFeatureCityIds}
            />
          </Col>
        </Row>
      </DrawerForm>
    </AppDetailContext.Provider>
  );
};

export default ApplyDetail;
