<script setup lang="ts">
import useStore from '@/stores';
import { traduction } from '@/utils/language';
import { ref, reactive, computed, nextTick, onMounted } from 'vue';

import { UserPrivil } from '@/model/base-enum';
import { checkPrivil } from '@/apps/app-bmc/router/routes';
import { IUsersInfo } from '@/pages/User/models/type';
import { strVerification } from '@/validators/validation-functions';
import {
  initPasswordRules,
  userNameVerification,
  computeRepeatTimes,
  errorTip,
} from '../utils/utils';

import { getAddParams, getEditParams } from '../utils/drawerFunctions';

import {
  roleList as rawRoleList,
  modifyPwdStrategy,
  interfaceList,
  authorityOptions,
  authorityOptions2,
  encrypOptions,
  userErrorList,
  pwdErrorList,
} from '../utils/data';

import Dialog from '@/components/Dialog/Dialog.vue';
import HelpIcon from '@/components/HelpIcon/HelpIcon.vue';
import ErrorIcon from '@/components/ErrorIcon/ErrorIcon.vue';
import ClearableIcon from '@/components/ClearableIcon/ClearableIcon.vue';
import LoginRules from '@/components/LoginRules/LoginRules.vue';
import PullDownTriangle from '@/components/PullDownTriangle/PullDownTriangle.vue';

import GlobalStoreService from '@/services/gloabal-store-service';
import LocaluserService from '../../../../services/localuser.service';
import { compareObjectEqual, deepClone, showElMessage } from '@/utils/utils';
import { getStoreData, setStoreData } from '@/utils/composition';
import { getPermissionManagementData } from '../../Security/securtyPages/PermissionManagement/permission-management.server';
import { LDAP_PAGE_ENABLED } from '@/model/configure';

const roleList = ref<typeof rawRoleList>([]);
const emits = defineEmits(['cancel']);

const props = defineProps({
  isTrap: {
    type: Boolean,
    required: false,
    default: false,
  }
});

defineExpose({
  // 打开 或者 关闭抽屉 进行展示数据加工
  changeVisible(value: boolean, checkItem?: IUsersInfo, edit?: boolean) {
    // 如果是打开抽屉
    if (value) {
      interfaceList.forEach((item: string, index: number) => {
        showInterfaceChecks[index] = false;
      });
      drawerShow.value = true;
      isEdit.value = edit ? edit : false;
      globalStoreService.setValue('isLoading', true);
      initEditData();
      // 编辑
      if (edit && checkItem) {
        isLastAdmin.value = checkItem.unDeletedReason === traduction('USER_UNDELETED_LAST');
        editInit(checkItem);
      } else {
        // 添加
        isLastAdmin.value = false;
        addInit();
      }
    } else {
      drawerShow.value = false;
    }
  },
});

const showAuthorityOptions: any = reactive([]);
const pwdMaxLen = getStoreData('loct', 'pml');
const globalStoreService = new GlobalStoreService();
const store = useStore();

// 用户配置权限
const hasConfigUsers = checkPrivil(UserPrivil.userConfig);
// 配置自身权限
const hasConfigSelf = checkPrivil(UserPrivil.configSelf);
// 锁定状态
const isSystemLock = computed(() => {
  return store.state.glob.systemLocked;
});

const disableState = computed(() => {
  return !hasConfigUsers || isSystemLock.value;
});

// 点击的是确认(save)还是取消(cancal)
let action = '';

const dialog = ref();
let dialogConfig = reactive({
  title: traduction('COMMON_CONFIRM'),
  content: '',
});

const trapDialog = ref();
let trapDialogConfig = reactive({
  title: traduction('COMMON_CONFIRM'),
  content: traduction('USER_EDIT_TRAP_TIPS'),
});
const saveBtnState = ref(false);
const formRefObj = ref();
const snmpPwdFormRef = ref();
let isLastAdmin = ref(false);
let baseEditData: any = {};
const editData: any = reactive({
  id: 0,
  userName: '',
  roleId: '',
  loginInterface: [],
  loginRole: [],
  validate: 0,
  sshPublicKeyHash: '',
  state: false,
  canDeleted: false,
  canDisabled: false,
  canDisbledTipSHow: false,
  unDeletedReason: '',
  unDisabledReason: '',
  userPwd1: '',
  userPwd2: '',
  forceModify: '',
  interfaceChecks: [],
  snmpPwd1: '',
  snmpPwd2: '',
  authProtocol: '',
  encryProtocol: '',
  userLoginPwd: '',
});
const isEdit = ref(false);
const rules: any = reactive({
  userName: {},
  userPwd1: {},
  userPwd2: {
    type: 'password',
    required: false,
    containsEmptyString: true,
    equals: {
      aimObj: editData,
      aimObjKey: 'userPwd1',
    },
    validator: (rule: any, value: any, callback: any): boolean => {
      if (rule.required && !value && !editData.userPwd1) {
        callback(new Error());
        return false;
      } else if (rule.required && !value && editData.userPwd1) {
        callback(new Error(rule.errorMsg));
        return false;
      }

      return strVerification(rule, value, callback);
    },
    errorMsg: traduction('COMMON_PASSWORDS_DIFFERENT'),
    trigger: 'blur',
  },
  forceModify: {
    required: false,
  },
  snmpPwd1: {
    required: false,
  },
  snmpPwd2: {
    type: 'password',
    required: false,
    containsEmptyString: true,
    equals: {
      aimObj: editData,
      aimObjKey: 'snmpPwd1',
    },
    validator: (rule: any, value: any, callback: any): boolean => {
      if (rule.required && !value && !editData.snmpPwd1) {
        callback(new Error());
        return false;
      } else if (rule.required && !value && editData.snmpPwd1) {
        callback(new Error(rule.errorMsg));
        return false;
      }
      return strVerification(rule, value, callback);
    },
    errorMsg: traduction('COMMON_PASSWORDS_DIFFERENT'),
    trigger: 'blur',
  },
  userLoginPwd: {
    required: true,
    message: '',
    validator: (rule: any, value: string, callback: any) => {
      if (!value) {
        callback(new Error());
        return false;
      } else {
        callback();
        return true;
      }
    },
  },
});
const drawerShow = ref(false);
const userIdList: any[] = reactive([]);
// 是否开启密码检查
const pwdCheck = ref(false);
const firstLoginEnabled = ref(true);
// 首次登录策略
const pwdResetPolicySupport = ref(false);
const user = {
  customizedId: getStoreData('loct', 'customizedId'),
  loginWithoutPassword: getStoreData('loct', 'nopwd') || false,
  ID: getStoreData('loct', 'uid'),
};
let minPwdLength: number = 8;
const loginWithoutPassword = ref(user.loginWithoutPassword);
const snmpv3PwdInitTip = ref(traduction('SNMP_PWD_INIT_TIP_2'));

const showInterfaceChecks = reactive([true, true, true, true, true, true, true]);

// 页面报错信息，输入框的后端校验报错
const pageError: { [key: string]: any } = reactive({
  userName: {
    asyncError: {
      show: false,
      message: '',
    },
  },
  userPwd1: {
    asyncError: {
      show: false,
      message: '',
    },
    forceReset: {
      author: false,
      ipmi: false,
    },
  },
  snmpPwd1: {
    asyncError: {
      show: false,
      message: '',
    },
    forceReset: {
      author: false,
    },
  },
});

// 角色是否必传
const roleIdRequired = ref(false);

const validateResult: any = reactive({});

const localNamePattern = ref('');

let showCheckList = reactive([] as any[]);

// popover显示状态
const popoverVisible: any = reactive({
  userName: false,
  userPwd1: false,
  snmpPwd1: false,
});

const initUserData: any = {};

// 设置校验规则
function setAddFormRule() {
  const errorMessage = [
    // 这里不能是''，否则错误信息会展示为英文的：提示必填
    ' ',
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
  ];
  // 这里的校验：开启密码检查的时候可以为有空格，没有开启密码检查的时候不能有空格，所以最后一个参数是： pwdCheck.value || false
  rules.userPwd1 = initPasswordRules(
    pwdCheck.value,
    minPwdLength,
    editData,
    true,
    errorMessage,
    'blur',
    true,
  );
  rules.snmpPwd1 = initPasswordRules(
    pwdCheck.value,
    minPwdLength,
    editData,
    true,
    errorMessage,
    'blur',
    true,
  );
  if (localNamePattern.value) {
    rules.userName = {
      type: 'text',
      required: true,
      validator: userNameVerification,
      pattern: localNamePattern.value,
      trigger: 'blur',
    };
  } else {
    rules.userName = {
      type: 'text',
      required: true,
      validator: userNameVerification,
      trigger: 'blur',
    };
  }
  rules.userName.required = true;
  rules.userPwd2.required = true;
  rules.forceModify.required = true;
  roleIdRequired.value = true;
}

// 初始化数据
function initEditData() {
  saveBtnState.value = false;

  // 初始化校验状态
  for (let key in validateResult) {
    if ({}.hasOwnProperty.call(validateResult, key)) {
      validateResult[key] = true;
    }
  }

  // 初始化后台错误显示
  pageError.userName.asyncError.show = false;
  pageError.userName.asyncError.message = '';
  pageError.userPwd1.asyncError.show = false;
  pageError.userPwd1.asyncError.message = '';
  pageError.snmpPwd1.asyncError.show = false;
  pageError.snmpPwd1.asyncError.message = '';

  // 编辑的数据置空然后方便重新赋值
  Object.assign(editData, {
    id: 0,
    userName: '',
    roleId: '',
    loginInterface: [],
    loginRole: [],
    validate: 0,
    sshPublicKeyHash: '',
    state: false,
    canDeleted: false,
    canDisabled: false,
    canDisbledTipSHow: false,
    unDeletedReason: '',
    unDisabledReason: '',
    userPwd1: '',
    userPwd2: '',
    forceModify: '',
    interfaceChecks: [],
    snmpPwd1: '',
    snmpPwd2: '',
    authProtocol: '',
    encryProtocol: '',
    userLoginPwd: '',
  });
}

// 添加时的数据初始化
function addInit() {
  LocaluserService.getAddUserParams()
    .then((res: any) => {
      // 设置剩余ID，角色
      userIdList.splice(0);
      userIdList.push(...res.userIdList);
      editData.id = userIdList[0].label;
      editData.roleId = rawRoleList[7].id;
      // 密码检查
      pwdCheck.value = res.pwdCheck;
      firstLoginEnabled.value = res.firstLoginEnabled;
      minPwdLength = res.minPwdLen;
      // 用户名校验
      localNamePattern.value = res.localNamePattern;
      // 设置首次登录密码修改策略, 只有支持该功能时才设置
      if (res.firstLoginResetSupport) {
        pwdResetPolicySupport.value = true;
        editData.forceModify = modifyPwdStrategy[1].value;
      }
      // 新增时，接口全部选中
      editData.interfaceChecks.splice(0);
      if (res?.allowedLoginInterfaces?.LocalAccount) {
        interfaceList.forEach((item: string, index: number) => {
          if (res.allowedLoginInterfaces.LocalAccount.indexOf(item) > -1) {
            editData.interfaceChecks.push(item);
            showInterfaceChecks[index] = true;
          } else {
            showInterfaceChecks[index] = false;
          }
        });
      }

      // 设置校验规则
      setAddFormRule();

      baseEditData = deepClone(editData);
      globalStoreService.setValue('isLoading', false);
    })
    .catch(() => {
      globalStoreService.setValue('isLoading', false);
    });
}

// 鉴权算法、加密算法发生修改
function selectChange(key: string, value: string) {
  // 如果是鉴权算法发生改变，需要强制修改密码和snmpv3密码。
  if (key === 'authProtocol') {
    if (value === initUserData.userInfo.authProtocol) {
      forceUpdatePwd(false, 'author');
    } else {
      forceUpdatePwd(true, 'author');
    }

    if (value === 'MD5' || value === 'SHA') {
      const msg = traduction('INSECURE_AUTHENTICATION_ALGORITHM_' + value);
      showElMessage('warning', msg);
    }
  }

  if (key === 'encryProtocol') {
    updateAuthorityList(value);
    if (value === 'DES') {
      const msg = traduction('INSECURE_ENCRYPTION_ALGORITHM');
      showElMessage('warning', msg);
    }
  }

  nextTick(() => {
    setSaveBtnState();
  });
}

// input事件
function input(key: string, value: string) {
  // 调用校验方法校验数据是否能通过，因为当前校验方式是blur，在input事件触发时不会触发校验，
  // 但是为了在输入的时候控制保存按钮的状态，需要手动去触发校验函数获取校验结果，进而控制保存按钮状态
  validateResult[key] = rules[key].validator(rules[key], value, () => {});

  /**
   * 用户密码 或者 被动校验确认密码,下面是需要校验的情形:
   * 1. 当确认密码输入框有值时
   * 2. 当用户密码输入框与确认密码 / 加密密码语确认密码输入框都没有值
   */
  if (key === 'userPwd1' && (editData.userPwd2 || (!editData.userPwd1 && !editData.userPwd2))) {
    formRefObj.value.validateField('userPwd2');
  } else if (
    key === 'snmpPwd1' &&
    (editData.snmpPwd2 || (!editData.snmpPwd1 && !editData.snmpPwd2))
  ) {
    snmpPwdFormRef.value.validateField('snmpPwd2');
  }

  if (key === 'userName' || key === 'userPwd1' || key === 'snmpPwd1') {
    // 清除后台设置的错误提示信息
    pageError[key].asyncError.show = false;
    // el-form-item 的 error为空值的时候就OK了，有值的时候就展示错误状态的输入框
    pageError[key].asyncError.message = '';
  }

  if (key === 'userPwd1' || key === 'snmpPwd1') {
    changeTipOver20(value.length, key);
  }

  nextTick(() => {
    setSaveBtnState();
  });
}

// 加密算法变更时，更新鉴权算法的列表
function updateAuthorityList(value: string): void {
  let curValue = editData.authProtocol;
  // 当选中项的id是 AES256 时
  if (value === encrypOptions[2].id) {
    showAuthorityOptions.splice(0);
    showAuthorityOptions.push(...authorityOptions2);
  } else {
    showAuthorityOptions.splice(0);
    showAuthorityOptions.push(...authorityOptions);
  }
  // 如果当前值在修改后的列表中，则继续选中，如果不在，则选中修改后的列表的第一项
  const isExists = showAuthorityOptions.filter((item: { label: string; id: string }) => {
    if (item.id === curValue) {
      curValue = item.id;
      return true;
    }
    return false;
  });
  if (!isExists.length) {
    curValue = showAuthorityOptions[0].id;
    // 当鉴权算法的值发生改变时，需要重置登录密码和加密密码
    selectChange('authProtocol', curValue);
  }
  editData.authProtocol = curValue;
}

// 强制触发与取消触发（修重置密码和snmpv3密码）
function forceUpdatePwd(force: boolean, reason: 'ipmi' | 'author'): void {
  const targets = reason === 'ipmi' ? ['userPwd1'] : ['userPwd1', 'snmpPwd1'];
  targets.forEach(target => {
    pageError[target].forceReset[reason] = force;
  });

  // 如果是强制重置密码
  if (force) {
    if (reason === 'ipmi') {
      resetForceValidator('userPwd1', 'add');
    } else {
      resetForceValidator('userPwd1', 'add');
      resetForceValidator('snmpPwd1', 'add');
    }
  } else {
    // 如果是取消强制重置密码
    if (reason === 'ipmi') {
      if (!pageError.userPwd1.forceReset.author) {
        resetForceValidator('userPwd1', 'delete');
      }
    } else {
      // 如果是鉴权算法导致的要删除强制密码提示的,1 可以直接删除snmpv3的强制提示。2需要判断IPMI是否也存在强制重置
      resetForceValidator('snmpPwd1', 'delete');
      if (!pageError.userPwd1.forceReset.ipmi) {
        resetForceValidator('userPwd1', 'delete');
      }
    }
  }
}

// 重置用户密码和V3密码的校验规则（用于提示强制密码重置功能）
function resetForceValidator(key: string, type: 'add' | 'delete'): void {
  const msg = key === 'snmpPwd1' ? 'SNMP_RESET_ENCRY_PASSWORD' : 'SNMP_RESET_PASSWORD';
  // 设置校验规则
  const errorMessage = [
    traduction(msg),
    traduction('VALIDTOR_INVALID_PASSWORD'),
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
  ];
  const key2 = key === 'userPwd1' ? 'userPwd2' : 'snmpPwd2';
  if (type === 'delete') {
    rules[key] = initPasswordRules(pwdCheck.value, minPwdLength, editData, false, errorMessage);
    rules[key2].required = false;
    if (key === 'userPwd1') {
      formRefObj.value.validateField('userPwd2');
    } else if (key === 'snmpPwd1') {
      snmpPwdFormRef.value.validateField('snmpPwd2');
    }
  } else {
    rules[key] = initPasswordRules(pwdCheck.value, minPwdLength, editData, true, errorMessage);
    rules[key2].required = true;
  }

  if (key === 'userPwd1') {
    formRefObj.value.validateField('userPwd1');
  } else if (key === 'snmpPwd1') {
    snmpPwdFormRef.value.validateField('snmpPwd1');
  }
}

// 根据密码的当前长度，修改提示信息
function changeTipOver20(length: number, key: string) {
  if (pwdCheck.value) {
    if (length >= 20) {
      rules[key].verificationList[0].label = traduction('VALIDATOR_MAX_LIMIT');
    } else {
      rules[key].verificationList[0].label = traduction('VALIDATOR_PWD_VALIDATOR1', [
        minPwdLength,
        20,
      ]);
    }
  } else {
    if (length >= 20) {
      rules[key].tipText = traduction('VALIDATOR_MAX_LIMIT');
    } else {
      rules[key].tipText = traduction('VALIDATOR_PWD_STANDARD', [1, 20]);
    }
  }
}

// clear事件
function clear(key: string) {
  // 如果没有focus，那么这个地方需要手动调用一次校验
  if (!popoverVisible[key]) {
    if (key === 'userName' || key === 'userPwd1' || key === 'userPwd2') {
      formRefObj.value.validateField(key);
    } else if (key === 'snmpPwd1' || key === 'snmpPwd2') {
      snmpPwdFormRef.value.validateField(key);
    }
  }
}

// 登录规则发生修改
function loginRuleChange(res: any) {
  let { loginRole } = editData;
  if (loginRole) {
    loginRole.splice(0);
    for (let key in res) {
      if (res[key]) {
        loginRole.push(key);
      }
    }
  }
  setSaveBtnState();
}

// 设置校验规则
function setEditFormRule() {
  const errorMessage = [
    ' ',
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
    traduction('VALIDTOR_FORMAT_ERROR'),
  ];
  rules.userPwd1 = initPasswordRules(pwdCheck.value, minPwdLength, editData, false, errorMessage, '', true);
  rules.snmpPwd1 = initPasswordRules(pwdCheck.value, minPwdLength, editData, false, errorMessage, '', true);
  rules.userPwd2.required = false;
  rules.snmpPwd2.required = false;
  rules.forceModify.required = false;
  roleIdRequired.value = false;
  if (localNamePattern.value) {
    rules.userName = {
      type: 'text',
      required: true,
      validator: userNameVerification,
      pattern: localNamePattern.value,
      trigger: 'blur',
    };
  } else {
    rules.userName = {
      type: 'text',
      required: true,
      validator: userNameVerification,
      trigger: 'blur',
    };
  }
  rules.userName.required = false;
}

// 编辑时的数据初始化
/* eslint-disable-next-line max-lines-per-function*/
function editInit(checkItem: IUsersInfo) {
  LocaluserService.getEditUserParams(checkItem.id)
    /* eslint-disable-next-line max-lines-per-function*/
    .then((res: any) => {
      const loginRole = [];
      let loginRule = res?.userInfo?.loginRule;
      if (loginRule && loginRule.length && loginRule instanceof Array) {
        for (let i = 0; i < loginRule.length; i++) {
          const item = loginRule[i].split('/').reverse().shift()?.[0];
          loginRole.push('Rule' + item);
        }
      }

      Object.assign(initUserData, res);
      if (!res.userInfo.roleId) {
        showElMessage('error', traduction('USER_MODIFY_NOT_EXIST'));
        drawerShow.value = false;
        globalStoreService.setValue('isLoading', false);
        return;
      }
      // 设置用户ID,设置用户名
      userIdList.splice(0);
      userIdList.push({ id: checkItem.id, label: String(checkItem.id) });
      Object.assign(editData, deepClone(checkItem));
      editData.loginRole = loginRole;
      pwdCheck.value = res.pwdCheck;
      firstLoginEnabled.value = res.firstLoginEnabled;
      minPwdLength = res.minPwdLen;
      snmpv3PwdInitTip.value = res.snmpv3PwdInit
        ? traduction('SNMP_PWD_INIT_TIP_1')
        : traduction('SNMP_PWD_INIT_TIP_2');
      // 用户名校验
      localNamePattern.value = res.localNamePattern;

      // 设置首次登录密码修改策略
      if (res.userInfo.firstLoginPolicy !== undefined) {
        pwdResetPolicySupport.value = true;
        const selectStrategyArr = modifyPwdStrategy.filter((item: any) => {
          return item.value === res.userInfo.firstLoginPolicy;
        });
        editData.forceModify =
          selectStrategyArr.length > 0 ? selectStrategyArr[0].value : modifyPwdStrategy[1].value;
      }

      // 设置用户的角色
      roleList.value.forEach((item: any) => {
        if (item.id === res.userInfo.roleId) {
          editData.roleId = item.id;
        }
      });

      // 根据用户的接口配置，确定哪些被选中
      editData.interfaceChecks.splice(0);
      interfaceList.forEach((item: string, index: number) => {
        if (res.userInfo.interfaceList.indexOf(item) > -1) {
          editData.interfaceChecks.push(item);
          showInterfaceChecks[index] = true;
        } else {
          showInterfaceChecks[index] = false;
        }
      });
      // 设置用户密码校验
      setEditFormRule();
      editData.authProtocol = res.userInfo.authProtocol;
      editData.encryProtocol = res.userInfo.encryProtocol;
      showAuthorityOptions.splice(0);
      if (editData.encryProtocol === 'AES256') {
        showAuthorityOptions.push(...authorityOptions2);
      } else {
        showAuthorityOptions.push(...authorityOptions);
      }
      baseEditData = deepClone(editData);
      globalStoreService.setValue('isLoading', false);
    })
    .catch(() => {
      globalStoreService.setValue('isLoading', false);
    });
}

// 计算后端校验密码错误信息和强制修改密码提示信息是否显示
function computePasswordState(target: 'userPwd1' | 'snmpPwd1'): boolean {
  // 显示逻辑 1. 优先显示强制修改密码。 2.该控件上的异步信息要支持显示。
  if (pageError[target].forceReset.author || pageError[target].forceReset.ipmi) {
    const value = editData[target];
    if (value.length > 0) {
      return pageError[target].asyncError.show;
    }
    return false;
  } else {
    return pageError[target].asyncError.show;
  }
}

// SNMP关闭开启事件, 开启时增加校验，关闭时删除校验
function snmpChange(): void {
  if (editData.interfaceChecks.indexOf('SNMP') > -1) {
    pageError.snmpPwd1.asyncError.show = false;
  } else {
    // 除由于鉴权算法变更导致的强制修改密码的功能
    forceUpdatePwd(false, 'author');
  }
}

// 登录接口变更时事件
function interfaceChanged(): void {
  // 开启SNMP不需要强制修改密码，开启IPMI，则需要强制修改密码
  const baseIpmiEnabled = baseEditData.interfaceChecks.indexOf('IPMI') > -1;
  const newIpmiEnabled = editData.interfaceChecks.indexOf('IPMI') > -1;
  const newSnmpEnabled = editData.interfaceChecks.indexOf('SNMP') > -1;

  // IPMI变化从关闭到开启时，强制修改密码
  if (!baseIpmiEnabled) {
    if (newIpmiEnabled) {
      forceUpdatePwd(true, 'ipmi');
    } else {
      forceUpdatePwd(false, 'ipmi');
    }
  }
  if (newSnmpEnabled && isEdit.value) {
    snmpChange();
  }
  nextTick(() => {
    setSaveBtnState();
  });
}

// 登录接口发生修改
function showInterfaceChange(value: boolean, str: string) {
  if (value) {
    editData.interfaceChecks.push(str);
  } else {
    let num = 0;
    editData.interfaceChecks.forEach((item: string, index: number) => {
      if (item === str) {
        num = index;
      }
    });
    editData.interfaceChecks.splice(num, 1);
  }
  interfaceChanged();
}

// 当前登录密码变化时，清除密码报错信息
function pwdChange(): void {
  formRefObj.value.clearValidate('userLoginPwd');
  validateResult.userLoginPwd = true;
  nextTick(() => {
    setSaveBtnState();
  });
}

// 点击取消
function cancel() {
  action = 'cancel';
  dialogConfig.content = traduction('COMMON_ASK_OK');
  dialog.value.show();
}

// 关闭抽屉
function closeDrower() {
  drawerShow.value = false;
  emits('cancel');
}

// 抽屉发生表单校验
function validate(key: string, state: boolean) {
  validateResult[key] = state;
  nextTick(() => {
    setSaveBtnState();
  });
}

// 点击保存
function save() {
  action = 'save';
  // 如果数据不能进行保存或者被禁用，则不做处理
  if (!saveBtnState.value || isSystemLock.value) {
    return;
  }

  let message: any = '';
  // 检查密码是否为空，不为空则需要验证密码是否有重复
  const pwd = editData.userPwd1;
  if (pwd !== '' && pwd !== null) {
    if (pwd.length < 8) {
      message = traduction('USER_PWD_INSUFFICIENT');
    }
    const count = computeRepeatTimes(pwd);
    if (count > 1) {
      if (message !== '') {
        message = [
          traduction('USER_PWD_INSUFFICIENT_REPEAT1'),
          traduction('USER_PWD_INSUFFICIENT_REPEAT2'),
        ];
      } else {
        message = traduction('USER_PWD_REPEAT');
      }
    }
  }
  dialogConfig.content = message || traduction('COMMON_ASK_OK');
  if (isEdit.value && props.isTrap) {
    if (editData.userName !== baseEditData.userName) {
      trapDialog.value.show();
      return;
    }
  }
  dialog.value.show();
}

// 给对应的属性框附加校验错误的提示,摒弃tiny2时的添加一个校验规则的做法，而是直接在输入框下添加提示
function addErrorValidation(key: string, errorId: string): void {
  let attrMessage = errorId + '.attrMessage';
  attrMessage = traduction(attrMessage);
  let errorMessage = errorId + '.errorMessage';
  errorMessage = traduction(errorMessage);

  pageError[key].asyncError.show = true;
  pageError[key].asyncError.message = attrMessage || errorMessage;
}

// 保存时错误处理，处理的错误是用户、密码、v3密码
function errorHandler(errorMsgArr: { errorId: string; relatedProp: string }[]): void {
  // 用户密码或v3密码错误时，表示是密码还是v3密码错误
  const relatedPops: string[] = ['Password', 'SnmpV3PrivPasswd'];

  // 获取所有的错误属性
  errorMsgArr.forEach((errorItem: { errorId: string; relatedProp: string }) => {
    if (errorItem.errorId === 'ReauthFailed' || errorItem.errorId === 'AuthorizationFailed') {
      nextTick(() => {
        formRefObj.value.validateField('userLoginPwd');
      });
    } else {
      setTimeout(() => {
        formRefObj.value.clearValidate('userLoginPwd');
      }, 0);
    }

    // 用户名信息错误
    if (userErrorList.indexOf(errorItem.errorId) > -1) {
      addErrorValidation('userName', errorItem.errorId);
    }

    // 密码或v3密码信息错误
    if (pwdErrorList.indexOf(errorItem.errorId) > -1) {
      // 用户密码保存失败
      if (relatedPops[0].indexOf(errorItem.relatedProp) > -1) {
        addErrorValidation('userPwd1', errorItem.errorId);
      }

      // v3密码保存失败
      if (relatedPops[1].indexOf(errorItem.relatedProp) > -1) {
        addErrorValidation('snmpPwd1', errorItem.errorId);
      }

      if (errorItem.errorId.indexOf('AddIPMI') > -1) {
        showElMessage('error', traduction('USER_IPMI_SAVE_ERROR'));
      }
    }
  });
}

function trapNotice(flag: boolean) {
  if (flag) {
    dialog.value.show();
  }
  trapDialog.value.hide();
}

// 确认保存 / 取消
/* eslint-disable-next-line max-lines-per-function*/
function sureSave(flag: boolean) {
  if (flag && action === 'save') {
    // Id传字符串
    const param: any = { Id: parseInt(editData.id, 10) };
    // 添加
    if (!isEdit.value) {
      getAddParams(param, editData, baseEditData, pwdResetPolicySupport, firstLoginEnabled);
    } else {
      getEditParams(param, editData, baseEditData, pwdResetPolicySupport);
    }
    dialog.value.hide();
    const method = isEdit.value ? 'editUser' : 'addUser';
    saveBtnState.value = false;
    globalStoreService.setValue('isLoading', true);
    const length = Object.keys(param).length - 1;
    
    LocaluserService[method](param, editData.userLoginPwd)
      .then((res: any) => {
        const isSelf = editData.id.toString() === user.ID.toString();
        if (res.type === 'success') {
          showElMessage('success', traduction('COMMON_SUCCESS'));
          globalStoreService.setValue('isLoading', false);
          closeDrower();
          return;
        }

        const errorMsg = res.type === 'someFailed' ? 'USER_EDIT_PARTIALLY_FAILED' : 'COMMON_FAILED';
        showElMessage('error', traduction(errorMsg));
        errorHandler(res.errors);
        globalStoreService.setValue('isLoading', false);
      })
      .catch(
        (error: { type: string; errors: { errorId: string; relatedProp: string }[] } | null) => {
          // 校验错误信息是规则上的message属性控制的，focus的时候置空，这样blur的时候就不会提示：is required，接口返回密码错误则提示对应的错误信息
          rules.userLoginPwd.message = traduction('COMMON_SECONDPWD_ERROR');
          editData.userLoginPwd = '';
          globalStoreService.setValue('isLoading', false);
          if (error && error.errors) {
            errorHandler(error.errors);
            if (
              error.errors[0].errorId === 'ReauthFailed' ||
              error.errors[0].errorId === 'AuthorizationFailed'
            ) {
              return;
            } else if (error.errors[0].errorId) {
              if (length > error.errors.length && method === 'editUser') {
                showElMessage('error', traduction('USER_EDIT_PARTIALLY_FAILED'));
                return;
              }
              const msg = errorTip(error.errors[0].errorId);
              if (msg) {
                const { type, label } = msg;
                showElMessage(type, label);
              }
              return;
            }
            showElMessage('error', traduction('COMMON_FAILED'));
          }
        },
      );
  } else {
    dialog.value.hide();
    if (flag && action === 'cancel') {
      closeDrower();
    }
  }
}

/**
 * 获取校验结果和后台提示 对 保存按钮的整体影响，
 *  因为SNMP没有选择的时候 '加密密码和确认密码的校验结果 以及 加密密码的后台提示' 不能成为判断保存按钮状态的条件
 */
function snmpOfSaveBtnState() {
  const flag = editData.interfaceChecks.indexOf('SNMP') > -1;
  for (let key in validateResult) {
    if (!validateResult[key]) {
      if (key !== 'snmpPwd1' && key !== 'snmpPwd2') {
        return false;
      } else if (isEdit.value && flag) {
        return false;
      }
    }
  }

  // 编辑的时候根据是否有选择SNMP接口进行,是否有后台给的错误提示
  if (isEdit.value && flag && pageError.snmpPwd1.asyncError.show) {
    return false;
  }

  return true;
}

// 设置保存按钮的状态
function setSaveBtnState() {
  saveBtnState.value = false;
  // 是否发生了有效的变化，只输入当前登录密码不算有效更改
  if (compareObjectEqual(editData, baseEditData, 'userLoginPwd')) {
    return;
  }

  if (!snmpOfSaveBtnState()) {
    return;
  }

  if (editData.userPwd1 !== editData.userPwd2) {
    return;
  }

  // 添加的时候密码是必传的
  if (!isEdit.value && (editData.userPwd1.length === 0 || editData.userName.length === 0)) {
    return;
  }

  // 编辑的时候根据是否有选择SNMP接口进行 加密密码 和 确认加密密码 相等比较
  if (
    isEdit.value &&
    editData.interfaceChecks.indexOf('SNMP') > -1 &&
    editData.snmpPwd1 !== editData.snmpPwd2
  ) {
    return;
  }

  // 没有开启免密，那么必须输入当前登录密码
  if (!loginWithoutPassword.value && editData.userLoginPwd.length === 0) {
    return;
  }

  // 后台校验的错误提示是否还有
  if (pageError.userName.asyncError.show || pageError.userPwd1.asyncError.show) {
    return;
  }
  saveBtnState.value = true;
}

onMounted(() => {
  getPermissionManagementData()
    .then((res: any) => {
      const supportedRoles = (res?.Members ?? []).map((item: any) => item.Name);
      roleList.value = rawRoleList.filter(item => !item.id.includes('Custom') || supportedRoles.includes(item.id));
    });
});

</script>

<template>
  <div v-reqKeepAlive.drawer>
    <el-drawer
      v-if="drawerShow"
      v-model="drawerShow"
      :close-on-click-modal="false"
      :show-close="false"
    >
      <template #title>
        {{ isEdit ? $t('USER_TEMPLATE_TITLE_EDIT') : $t('USER_TEMPLATE_TITLE_ADD') }}
      </template>
      <template #default>
        <div class="content-and-footer">
          <div class="content">
            <el-form
              ref="formRefObj"
              :model="editData"
              :rules="rules"
              label-position="left"
              label-width="auto"
              :validate-on-rule-change="false"
              @validate="validate"
            >
              <!-- 用户id -->
              <el-form-item :label="$t('COMMON_USER_ID')">
                <el-select
                  v-model="editData.id"
                  v-addId.select="'userIdList'"
                  :teleported="false"
                  :disabled="disableState"
                  :suffix-icon="PullDownTriangle"
                  @change="setSaveBtnState"
                >
                  <el-option
                    v-for="item in userIdList"
                    :key="item.id"
                    :label="item.label"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>

              <!-- 用户名 -->
              <el-form-item
                :label="$t('COMMON_USERNAME')"
                prop="userName"
                :error="pageError.userName.asyncError.message"
              >
                <el-popover
                  v-model:visible="popoverVisible.userName"
                  popper-class="wrap-el-popper"
                  width="320px"
                  placement="top"
                  :content="localNamePattern ? $t('USER_NAME_TIPS', { reg: new RegExp(localNamePattern)}) : $t('USER_USERNAME_TIP')"
                  trigger="focus"
                  trigger-keys
                  :persistent="false"
                >
                  <template #reference>
                    <el-input
                      v-model="editData.userName"
                      v-addId.input="'userName'"
                      v-clearable
                      clearable
                      type="text"
                      :maxlength="localNamePattern ? '' : 16"
                      :disabled="disableState"
                      @focus="popoverVisible.userName = true"
                      @blur="popoverVisible.userName = false"
                      @input="input('userName', $event)"
                      @clear="clear('userName')"
                    >
                      <template #suffix>
                        <ErrorIcon />
                        <ClearableIcon />
                      </template>
                    </el-input>
                  </template>
                </el-popover>
              </el-form-item>

              <!-- 用户密码 -->
              <el-form-item
                :label="$t('COMMON_PASSWORD_ALIA')"
                prop="userPwd1"
                :error="
                  computePasswordState('userPwd1') ? pageError.userPwd1.asyncError.message : ''
                "
              >
                <el-popover
                  v-model:visible="popoverVisible.userPwd1"
                  popper-class="no-wrap-popover"
                  :placement="'top'"
                  trigger="focus"
                  trigger-keys
                  :persistent="false"
                >
                  <!-- 没有开启密码检查-popover内容 -->
                  <span v-if="!pwdCheck">
                    {{ rules.userPwd1['tipText'] }}
                  </span>
                  <!-- 开启密码检查-popover内容 -->
                  <ComplexPopoverContentOfList
                    v-if="pwdCheck"
                    :data="rules.userPwd1['verificationList']"
                  />

                  <template #reference>
                    <el-input
                      v-model="editData.userPwd1"
                      v-addId.input="'userPassword'"
                      v-clearable
                      clearable
                      maxlength="20"
                      type="password"
                      autocomplete="new-password"
                      :disabled="isSystemLock"
                      @focus="popoverVisible.userPwd1 = true"
                      @blur="popoverVisible.userPwd1 = false"
                      @input="input('userPwd1', $event)"
                      @clear="clear('userPwd1')"
                    >
                      <template #suffix>
                        <ErrorIcon />
                        <ClearableIcon />
                      </template>
                    </el-input>
                  </template>
                </el-popover>
              </el-form-item>

              <!-- 确认密码 -->
              <el-form-item :label="$t('COMMON_PASSWORD_CONFIRM')" prop="userPwd2">
                <el-input
                  v-model="editData.userPwd2"
                  v-addId.input="'userConfirmPassword'"
                  v-clearable
                  clearable
                  maxlength="20"
                  type="password"
                  autocomplete="new-password"
                  :disabled="isSystemLock"
                  @input="input('userPwd2', $event)"
                  @clear="clear('userPwd2')"
                >
                  <template #suffix>
                    <ErrorIcon />
                    <ClearableIcon />
                  </template>
                </el-input>
              </el-form-item>

              <!-- 首次登录策略 -->
              <el-form-item
                v-if="pwdResetPolicySupport && firstLoginEnabled"
                :label="$t('USER_FIRST_LOGIN_POLICY')"
                prop="forceModify"
              >
                <el-select
                  v-model="editData.forceModify"
                  v-addId.select="'forceResetPwdStrategy'"
                  :teleported="false"
                  :disabled="disableState"
                  :suffix-icon="PullDownTriangle"
                  @change="setSaveBtnState"
                >
                  <el-option
                    v-for="item in modifyPwdStrategy"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>

              <!-- 角色 -->
              <el-form-item
                :label="$t('COMMON_ROLE')"
                :class="[roleIdRequired ? 'roleId-required' : '']"
                :error="isLastAdmin ? $t('USER_UNDELETED_LAST') : ''"
              >
                <el-select
                  v-model="editData.roleId"
                  v-addId.select="'roleList'"
                  :teleported="false"
                  :disabled="!hasConfigUsers || isLastAdmin"
                  :suffix-icon="PullDownTriangle"
                  @change="setSaveBtnState"
                >
                  <el-option
                    v-for="item in roleList"
                    :key="item.id"
                    :label="item.label"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>

              <!--  登录规则 -->
              <el-form-item :label="$t('SERVICE_VNC_LOGIN_RULE')" class="login-rule-item" v-if="LDAP_PAGE_ENABLED">
                <LoginRules
                  :show-type="'pullDown'"
                  :check-list="editData.loginRole"
                  @login-rule-change="loginRuleChange"
                />
              </el-form-item>

              <!-- 登录接口 -->
              <el-form-item :label="$t('COMMON_LOGIN_INTERFACE')" class="login-interface-item">
                <span
                  v-for="(item, index) in interfaceList"
                  :key="index"
                  class="el-checkbox-item-box"
                >
                  <el-checkbox
                    v-model="showInterfaceChecks[index]"
                    v-addId.checkbox="item"
                    :label="item"
                    :disabled="disableState"
                    @change="showInterfaceChange($event, item)"
                  >
                    <span>{{ item }}</span>
                  </el-checkbox>
                  <HelpIcon
                    v-if="item === 'SNMP' && !isEdit"
                    :placement="'top'"
                    :append-to-body="true"
                    :tips="$t('USER_SNMPV3_EDITE')"
                    :pop-class="'wrap-el-popper'"
                  />
                </span>

                <div
                  v-if="isEdit && editData.interfaceChecks.indexOf('SNMP') > -1"
                  class="snmpv3-container"
                >
                  <div class="part-title">
                    <span class="text">{{ $t('USER_SNMPV3_TITLE') }}</span>
                    <HelpIcon
                      :placement="'top'"
                      :append-to-body="true"
                      :tips="snmpv3PwdInitTip"
                      :pop-class="'wrap-el-popper'"
                    />
                  </div>

                  <el-form
                    ref="snmpPwdFormRef"
                    :model="editData"
                    :rules="rules"
                    label-position="left"
                    label-width="auto"
                    :validate-on-rule-change="false"
                    @validate="validate"
                  >
                    <!-- 加密密码 -->
                    <el-form-item
                      :label="$t('USER_SNMPV3_ENCRYP')"
                      prop="snmpPwd1"
                      :error="
                        computePasswordState('snmpPwd1')
                          ? pageError.snmpPwd1.asyncError.message
                          : ''
                      "
                    >
                      <el-popover
                        v-model:visible="popoverVisible.snmpPwd1"
                        popper-class="no-wrap-popover"
                        :placement="'top'"
                        trigger="focus"
                        trigger-keys
                        :persistent="false"
                      >
                        <!-- 没有开启密码检查-popover内容 -->
                        <span v-if="!pwdCheck">
                          {{ rules.snmpPwd1['tipText'] }}
                        </span>
                        <!-- 开启密码检查-popover内容 -->
                        <ComplexPopoverContentOfList
                          v-if="pwdCheck"
                          :data="rules.snmpPwd1['verificationList']"
                        />

                        <template #reference>
                          <el-input
                            v-model="editData.snmpPwd1"
                            v-addId.input="'snmpv3Pwd'"
                            v-clearable
                            clearable
                            maxlength="20"
                            type="password"
                            autocomplete="new-password"
                            :placeholder="$t('USER_SNMPV3_ENCRYP')"
                            :disabled="isSystemLock"
                            @focus="popoverVisible.snmpPwd1 = true"
                            @blur="popoverVisible.snmpPwd1 = false"
                            @input="input('snmpPwd1', $event)"
                            @clear="clear('snmpPwd1')"
                          >
                            <template #suffix>
                              <ErrorIcon />
                              <ClearableIcon />
                            </template>
                          </el-input>
                        </template>
                      </el-popover>
                    </el-form-item>

                    <!-- 确认密码 -->
                    <el-form-item :label="$t('COMMON_PASSWORD_CONFIRM')" prop="snmpPwd2">
                      <el-input
                        v-model="editData.snmpPwd2"
                        v-addId.input="'snmpv3ConfirmPwd'"
                        v-clearable
                        clearable
                        maxlength="20"
                        type="password"
                        autocomplete="new-password"
                        :placeholder="$t('COMMON_PASSWORD_CONFIRM')"
                        :disabled="isSystemLock"
                        @input="input('snmpPwd2', $event)"
                        @clear="clear('snmpPwd2')"
                      >
                        <template #suffix>
                          <ErrorIcon />
                          <ClearableIcon />
                        </template>
                      </el-input>
                    </el-form-item>
                  </el-form>

                  <div class="part-title">
                    <span class="text">{{ $t('USER_SNMPV3_ALGORITHM') }}</span>
                    <HelpIcon
                      :placement="'top'"
                      :append-to-body="true"
                      :tips="$t('SNMP_ALGORITHM_INIT_TIP')"
                      :pop-class="'wrap-el-popper'"
                    />
                  </div>

                  <el-form label-position="left" label-width="auto">
                    <!-- 鉴权算法 -->
                    <el-form-item :label="$t('USER_SNMPV3_AUTHORITY')">
                      <el-select
                        v-model="editData.authProtocol"
                        v-addId.select="'authoritySelect'"
                        :teleported="false"
                        :suffix-icon="PullDownTriangle"
                        @change="selectChange('authProtocol', $event)"
                      >
                        <el-option
                          v-for="item in showAuthorityOptions"
                          :key="item.id"
                          :label="item.label"
                          :value="item.id"
                          :disabled="item.disabled"
                        />
                      </el-select>
                    </el-form-item>

                    <!-- 加密算法 -->
                    <el-form-item :label="$t('USER_SNMPV3_ENCRYPTION')" class="encryProtocol-item">
                      <el-select
                        v-model="editData.encryProtocol"
                        v-addId.select="'encrypSelect'"
                        :teleported="false"
                        :suffix-icon="PullDownTriangle"
                        @change="selectChange('encryProtocol', $event)"
                      >
                        <el-option
                          v-for="item in encrypOptions"
                          :key="item.id"
                          :label="item.label"
                          :value="item.id"
                        />
                      </el-select>
                    </el-form-item>
                  </el-form>
                </div>
              </el-form-item>

              <!-- 登录密码 -->
              <el-form-item
                v-if="!loginWithoutPassword"
                :label="$t('COMMON_LOGIN_PASSWORD')"
                prop="userLoginPwd"
              >
                <el-input
                  v-model="editData.userLoginPwd"
                  v-addId.input="'secondPassword'"
                  v-clearable
                  clearable
                  type="password"
                  :maxlength="pwdMaxLen"
                  autocomplete="new-password"
                  :disabled="isSystemLock"
                  :placeholder="$t('COMMON_PASSWORD_PLACEHOLDER')"
                  @keyup.enter="save"
                  @input="pwdChange"
                  @clear="pwdChange"
                  @focus="rules.userLoginPwd.message = ''"
                >
                  <template #suffix>
                    <ErrorIcon />
                    <ClearableIcon />
                  </template>
                </el-input>
              </el-form-item>
            </el-form>
          </div>

          <div class="footer">
            <el-button
              :id="isEdit ? 'editNoteBtn' : 'addNoteBtn'"
              :disabled="!saveBtnState || isSystemLock"
              type="primary"
              @click="save"
            >
              {{ $t('COMMON_SAVE') }}
            </el-button>
            <el-button id="cancelNoteBtn" @click="cancel">
              {{ $t('COMMON_CANCEL') }}
            </el-button>
          </div>
        </div>
      </template>
    </el-drawer>
  </div>

  <!-- 确认保存的弹窗 -->
  <Dialog ref="dialog" :config="dialogConfig" @close="sureSave" />
  <Dialog ref="trapDialog" :config="trapDialogConfig" @close="trapNotice" />
</template>

<style lang="scss" scoped>
.el-drawer {
  .content-and-footer {
    display: flex;
    flex-direction: column;
    justify-content: space-between;

    :deep(.content) {
      flex: 1;
      display: flex;
      padding: 0 24px 48px;

      .el-form {
        width: 100%;

        .el-form-item {
          margin-bottom: 24px;
          .el-form-item__label {
            font-size: 12px;
            color: var(--o-text-color-secondary);
          }

          .el-checkbox-item-box {
            display: flex;
            align-items: center;
            margin-right: 40px;

            .icon-help-container {
              margin-left: 4px;
            }
          }
        }

        .roleId-required .el-form-item__label::before {
          content: '*';
          position: absolute;
          left: -6px;
          font-size: 12px;
          color: var(--o-form-require-color);
        }

        .el-input,
        .el-input__inner {
          width: 320px;
        }
        .el-select{
          width: 320px;
        }
        .login-rule-item {
          margin-bottom: 16px;

          .el-form-item__label-wrap .el-form-item__label {
            padding-top: 0;
          }
        }

        .login-interface-item {
          margin-bottom: 24px;

          .el-form-item__label-wrap .el-form-item__label {
            padding-top: 6px;
          }
        }

        .el-form-item__label {
          position: relative;

          &::before {
            position: absolute;
            left: -6px;
          }
        }

        .el-checkbox__label {
          display: flex;
          align-items: center;

          .icon-help-container {
            margin-left: 4px;
          }
        }

        .snmpv3-container {
          width: 100%;
          border-radius: 4px;
          padding: 24px;
          background-color: var(--o-bg-color-light);

          .el-input,
          .el-select,
          .el-input__inner {
            width: 100%;
          }

          .part-title {
            display: flex;
            align-items: center;
            margin-bottom: 16px;

            .text {
              color: var(--o-text-color-primary);
              margin-right: 4px;
              line-height: 1;
            }
          }

          .el-form-item {
            margin-bottom: 24px;
          }

          .encryProtocol-item {
            margin-bottom: 0;
          }
        }
      }
    }

    .footer {
      position: fixed;
      bottom: 0;
      right: 0;
      z-index: 999999;
      width: 552px;
      background-color: var(--o-bg-color-base) !important;
      padding: 8px 24px;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
    }
  }
}
</style>
