import type { FormInstance } from 'antd';
import { Empty, Tabs } from 'antd';
import _ from 'lodash';
import type { Dispatch, Key, SetStateAction } from 'react';
import { createContext, useContext, useEffect, useMemo } from 'react';
import { useIntl, useRequest } from 'umi';
import { filterTreeByIds } from '../utils';
import { leafBuildTree, treeCreateId } from '../utils/array';
import {
  AppDetailContext,
  useCityList,
  useDomLayoutEffect,
  useFeatureTree,
  useFlagList,
  usePolicyList,
  useRoleList,
} from '../utils/hooks';
import CityTab from './components/cityTab';
import FeatureTab from './components/featureTab';
import FlagTab from './components/flagTab';
import PolicyTab from './components/policyTab';
import RoleTab from './components/roleTab';
import {
  bindFilter,
  filterFeatureCityIds,
  formatFeatureFullList,
  formatFlagList,
  formatMergedVal,
  formatOptionEmptyList,
  formatOptionFullList,
} from './util';

export type DetailProps = {
  /** 1为自己申请, 2为别人申请 */
  type: number;
  open: boolean;
  id: number;
  tagKey?: string;
  setTagKey?: Dispatch<SetStateAction<string | undefined>>;
  form?: FormInstance<any>;
  defaultFlagIds?: string[];
  currentUser?: API.CurrentUser;
  initialValues?: any;
  /** operation: 运营端配置 multiple: 多应用申请 single: 单应用申请 */
  useType?: 'multiple' | 'single' | 'operation';
  featureCityIds?: API.FeatureCityId[];
  setFeatureCityIds?: Dispatch<SetStateAction<API.FeatureCityId[]>>;
  /** 城市权限选中同步事件 */
  onSyncCitySelect?: (v: any) => void;
};

type ContextValueType = DetailProps & { detailData?: any };

export const DetailContext = createContext<ContextValueType>({
  type: 0,
  open: false,
  id: 0,
});

const Detail = (props: DetailProps) => {
  const {
    type,
    open,
    id: appId,
    tagKey,
    form,
    setTagKey,
    initialValues,
    useType,
    featureCityIds,
    setFeatureCityIds,
    defaultFlagIds,
  } = props;

  const { formatMessage } = useIntl();

  const {
    isAllowApplyFeature,
    isAllowApplyFlag,
    isAllowApplyPolicy,
    isAllowApplyRole,
    isAllowApplyCity,
    applyOrder,
    defaultExpirationTime,
  } = useContext(AppDetailContext);

  const { roleList, refresh: rlRefresh } = useRoleList(appId, 1);
  const { featureTreeData, refresh: ftdRefresh } = useFeatureTree(appId, 1);
  const { policyList, refresh: plRefresh } = usePolicyList(appId, 1);
  const { cityList, refresh: cityRefresh } = useCityList(appId);
  const { flagList, refresh: flagRefresh } = useFlagList(appId, 1);

  const { data: detailData, refresh: detailRefresh } = useRequest(
    () => ({
      url: '/goapi/app/myPermission/detail',
      method: 'POST',
      data: { appId },
    }),
    {
      ready: Boolean(appId && open && useType !== 'operation'),
      refreshDeps: [appId, open, useType],
    },
  );

  const {
    featureTree,
    flagList: oldFlagList,
    policyList: oldPolicyList,
    roleList: oldRoleList,
    userCityList: oldCityList,
    featureCityIds: oldFeatureCityIds,
  } = detailData || {};

  const {
    flags: initFlags,
    roles: initRoles,
    features: initFeatures,
    policies: initPolicies,
    cities: initCities,
    featureCityIds: initFeatureCityIds,
  } = initialValues || {};

  const flagData = useMemo(
    () => formatFlagList(flagList, initFlags, useType),
    [flagList, initFlags, useType],
  );

  const selectedRole = useMemo(
    () => oldRoleList?.filter((v: any) => bindFilter(v, useType)) || [],
    [oldRoleList, useType],
  );

  const roleOptions = useMemo(() => {
    if (useType === 'multiple') {
      const roleIds = initRoles?.data?.map((v: any) => Number(v.id)) || [];
      return roleList?.filter((v: any) => roleIds.includes(v.id));
    }
    return roleList?.map((v: any) => ({ ...v }));
  }, [initRoles, roleList, useType]);

  const selectedPolicy = useMemo(() => {
    return oldPolicyList?.filter((v: any) => bindFilter(v, useType));
  }, [oldPolicyList, useType]);

  const filterFeatureTreeData = useMemo(() => {
    if (useType === 'multiple' && !_.isEmpty(featureTreeData)) {
      const featureIds = initFeatures?.data?.map((v: any) => Number(v.id)) || [];
      return filterTreeByIds(featureTreeData, featureIds);
    }
    return featureTreeData;
  }, [featureTreeData, initFeatures, useType]);

  const policyOptions = useMemo(() => {
    if (useType === 'multiple') {
      const policyIds = initPolicies?.data?.map((v: any) => Number(v.id)) || [];
      return policyList?.filter((v: any) => policyIds.includes(v.id));
    }
    return policyList?.map((v: any) => ({ ...v }));
  }, [policyList, useType, initPolicies]);

  const cityOptions = useMemo(() => {
    const cityOps = treeCreateId(cityList);
    if (useType === 'multiple') {
      const cityIds: Key[] = initCities?.data?.map((v: any) => Number(v.id)) || [];
      return leafBuildTree(cityIds, cityOps);
    }
    return cityOps;
  }, [cityList, useType, initCities]);

  const isShowPolicy = useMemo(
    () =>
      Boolean(
        useType === 'multiple'
          ? !_.isEmpty(policyOptions) && isAllowApplyPolicy
          : isAllowApplyPolicy,
      ),
    [isAllowApplyPolicy, policyOptions, useType],
  );

  const isShowCity = useMemo(
    () =>
      Boolean(
        useType === 'multiple' ? !_.isEmpty(cityOptions) && isAllowApplyCity : isAllowApplyCity,
      ),
    [cityOptions, isAllowApplyCity, useType],
  );

  const isShowRoles = useMemo(
    () =>
      Boolean(
        useType === 'multiple' ? !_.isEmpty(roleOptions) && isAllowApplyRole : isAllowApplyRole,
      ),
    [useType, roleOptions, isAllowApplyRole],
  );

  const isShowFeature = useMemo(
    () =>
      Boolean(
        useType === 'multiple'
          ? !_.isEmpty(filterFeatureTreeData) && isAllowApplyFeature
          : isAllowApplyFeature,
      ),
    [filterFeatureTreeData, isAllowApplyFeature, useType],
  );

  const isShowFlag = useMemo(
    () =>
      Boolean(useType === 'multiple' ? !_.isEmpty(flagData) && isAllowApplyFlag : isAllowApplyFlag),
    [flagData, isAllowApplyFlag, useType],
  );

  const mergedValues = useMemo(() => {
    if (useType === 'operation') return initialValues;
    const baseValues = {
      features: { data: formatFeatureFullList(featureTree, useType) },
      policies: { data: selectedPolicy },
      roles: { data: selectedRole },
      cities: { data: oldCityList?.map((v: any) => ({ ...v, id: v.cityId })) },
      flags: formatOptionFullList(
        flagData,
        oldFlagList,
        useType,
        defaultFlagIds,
        defaultExpirationTime,
      ),
      role: undefined,
    };
    if (type === 2) {
      baseValues.features.data = [];
      baseValues.policies.data = [];
      baseValues.roles.data = [];
      baseValues.cities.data = [];
      baseValues.flags = formatOptionEmptyList(flagData);
    }
    return _.isEmpty(initialValues) ? baseValues : formatMergedVal(baseValues, initialValues);
  }, [
    defaultExpirationTime,
    defaultFlagIds,
    featureTree,
    flagData,
    initialValues,
    oldCityList,
    oldFlagList,
    selectedPolicy,
    selectedRole,
    type,
    useType,
  ]);

  useEffect(() => {
    if (open) {
      rlRefresh();
      ftdRefresh();
      plRefresh();
      cityRefresh();
      flagRefresh();
    }
  }, [open, ftdRefresh, plRefresh, rlRefresh, cityRefresh, flagRefresh]);

  const renderOrder = useMemo(() => {
    const showMap = {
      1: isShowFeature,
      2: isShowRoles,
      3: isShowFlag,
      4: isShowPolicy,
      5: isShowCity && useType !== 'operation',
    };
    return applyOrder?.filter((k) => showMap[Number(k)] ?? true) ?? [];
  }, [applyOrder, isShowCity, isShowFeature, isShowFlag, isShowPolicy, isShowRoles, useType]);

  useEffect(() => {
    if (!tagKey || !renderOrder.includes(Number(tagKey))) {
      const [key] = renderOrder;
      if (key) setTagKey?.(String(key));
    }
  }, [renderOrder, setTagKey, tagKey]);

  useDomLayoutEffect(() => {
    form?.setFieldsValue({
      features: mergedValues.features,
      policies: mergedValues.policies,
      roles: mergedValues.roles,
      cities: mergedValues.cities,
      flags: mergedValues.flags,
      role: mergedValues.role,
    });
  }, [mergedValues, form]);

  useEffect(() => {
    if (useType === 'operation') {
      setFeatureCityIds?.(initFeatureCityIds || []);
    } else if (useType === 'multiple') {
      const filterData = filterFeatureCityIds(initFeatureCityIds, oldFeatureCityIds);
      setFeatureCityIds?.([...(oldFeatureCityIds || []), ...filterData]);
    }
  }, [oldFeatureCityIds, initFeatureCityIds, setFeatureCityIds, useType]);

  if (
    !isAllowApplyFeature &&
    !isAllowApplyFlag &&
    !isAllowApplyPolicy &&
    !isAllowApplyRole &&
    !isAllowApplyCity
  ) {
    return (
      <Empty
        image={Empty.PRESENTED_IMAGE_SIMPLE}
        description={formatMessage({ id: 'component.ApplyDetail.detail.empty' })}
      />
    );
  }

  const tabItemMap = {
    1: () => {
      // 功能权限
      return (
        <Tabs.TabPane
          tab={formatMessage({ id: 'component.ApplyDetail.detail.features.name' })}
          key={'1'}
          forceRender
        >
          <FeatureTab
            filterFeatureTreeData={filterFeatureTreeData}
            featureCityIds={featureCityIds}
            oldFeatureCityIds={oldFeatureCityIds}
            featureTree={featureTree}
            detailRefresh={detailRefresh}
            ftdRefresh={ftdRefresh}
          />
        </Tabs.TabPane>
      );
    },
    2: () => {
      // 角色权限
      return (
        <Tabs.TabPane
          tab={formatMessage({ id: 'component.ApplyDetail.detail.roles.name' })}
          key={'2'}
          forceRender
        >
          <RoleTab
            oldRoleList={oldRoleList}
            roleOptions={roleOptions}
            selectedRole={selectedRole}
            detailRefresh={detailRefresh}
            rlRefresh={rlRefresh}
          />
        </Tabs.TabPane>
      );
    },
    3: () => {
      // 数据权限
      return (
        <Tabs.TabPane
          tab={formatMessage({ id: 'component.ApplyDetail.detail.flags.name' })}
          key={'3'}
          forceRender
        >
          <FlagTab
            flagList={flagList}
            flagData={flagData}
            detailRefresh={detailRefresh}
            flagRefresh={flagRefresh}
          />
        </Tabs.TabPane>
      );
    },
    4: () => {
      // 策略权限
      return (
        <Tabs.TabPane
          tab={formatMessage({ id: 'component.ApplyDetail.detail.policies.name' })}
          key={'4'}
          forceRender
        >
          <PolicyTab
            policyOptions={policyOptions}
            oldPolicyList={oldPolicyList}
            selectedPolicy={selectedPolicy}
            detailRefresh={detailRefresh}
            plRefresh={plRefresh}
          />
        </Tabs.TabPane>
      );
    },
    5: () => {
      // 城市权限
      // 单个应用权限申请暂时隐藏城市权限
      return (
        <Tabs.TabPane
          tab={formatMessage({
            id: 'base.common.city.permission',
            defaultMessage: 'City Permission',
          })}
          key={'5'}
          forceRender
        >
          <CityTab
            cityOptions={cityOptions}
            oldCityList={oldCityList}
            detailRefresh={detailRefresh}
            cityRefresh={cityRefresh}
          />
        </Tabs.TabPane>
      );
    },
  };

  return (
    <DetailContext.Provider value={{ ...props, detailData }}>
      <Tabs tabPosition={'top'} activeKey={tagKey} onChange={setTagKey} style={{ width: '100%' }}>
        {renderOrder.map((k) => tabItemMap[Number(k)]?.())}
      </Tabs>
    </DetailContext.Provider>
  );
};

export default Detail;
