<script lang="ts" setup>
import { ref, reactive, toRefs, watch, onMounted, computed, nextTick } from 'vue';
import useStore from '@/stores';
import { traduction, getErrorTranslate } from '@/utils/language';
import { BaseValidators } from '@/validators/base-validators';
import { UploadFile } from 'element-plus/es/components/upload/src/upload';
import FileUpload from '@/components/FileUpload/FileUpload.vue';
import {
  saveKerberos,
  getKerberos,
  uploadKrbFile,
  importKrbFile,
} from '../services/kerberos.services';
import { checkPrivil } from '@/apps/app-bmc/router/routes';
import { UserPrivil } from '@/model/base-enum';
import { getStoreData } from '@/utils/composition';
import { reqPath } from '@/api/reqPath';
import { loading } from '@/utils/composition';
import { DomainValidators } from '@/validators/domain-validators';
import { STR_MATCH_0_255 } from '@/utils/regular';
import ErrorIcon from '@/components/ErrorIcon/ErrorIcon.vue';
import ClearableIcon from '@/components/ClearableIcon/ClearableIcon.vue';
import Schema from 'async-validator';
import { showElMessage, getMessageId, compareObjectEqual, escapeHeader } from '@/utils/utils';

const store = useStore();
// 系统锁定状态
const isSystemLock = computed(() => {
  return store.state.glob.systemLocked;
});
const isPrivileges = checkPrivil(UserPrivil.userConfig);
const props = defineProps({
  data: {
    required: true,
    type: Object,
    default: () => {
      return {};
    },
  },
});

const { data } = toRefs(props);
const loct = localStorage.getItem('loct');
const pwdMaxLen = getStoreData('loct', 'pml');
const uploadRef = ref();
const formRef = ref();
let fileItem: any = null;
const saveBtnState = ref(false);
const systemLocked = ref(false);
const hasConfigUsers = ref(false);
// 是否免密登录
const nopwd = getStoreData('loct', 'nopwd');
const formData = reactive({
  realm: '',
  server: '',
  port: '',
  userPassword: '',
});
const userPasswordMsg = ref('');
let paramData = {};
let oldFormData: any;
// 上传密钥
const uploadConfig = reactive({
  action: reqPath.userAndSecurity.ImportKeyTab,
  headers: {
    'X-CSRF-Token': escapeHeader(loct ? JSON.parse(loct).to : ''),
    From: 'WebUI',
    Accept: '*/*',
  },
  id: 'krbSecret',
  disabled: !isPrivileges,
  isCustomUpload: true,
  method: 'POST',
  name: 'Content',
  isAutoUpload: false,
  accept: '.keytab',
  width: 320,
  onAddItem: (file: UploadFile, list: UploadFile[], msg?: any, upload?: any): boolean => {
    let type = file.name.substring(file.name.lastIndexOf('.') + 1);
    fileItem = file;
    computedState();
    if (type === 'keytab') {
      msg.value = '';
      return true;
    } else {
      msg.value = traduction('SERVICE_UPLOADIN_CORRECT');
      return false;
    }
  },
  onRemove: (file: UploadFile, list: UploadFile[]) => {
    fileItem = null;
  },
});
function uploadKrbCert(param: { secPwd?: string; formData?: FormData }): Promise<any> {
  return new Promise((resolve, reject) => {
    if (param.formData === null) {
      resolve('nochange');
    } else {
      uploadKrbFile(param.formData as FormData).then(
        () => {
          importKrbFile(fileItem.name).then(
            () => {
              resolve('success');
            },
            error => {
              reject(error);
            },
          );
        },
        error => {
          reject(error);
        },
      );
    }
  });
}

// 校验规则
const kerRules: any = reactive({
  server: [DomainValidators.ipv46AndDomin('blur', traduction('VALIDTOR_FORMAT_ERROR'))],
  port: [
    BaseValidators.Required({ message: traduction('VALIDTOR_RANGE') }),
    BaseValidators.Integer({ message: traduction('VALIDTOR_RANGE') }),
    BaseValidators.Range({
      message: traduction('VALID_RANGE_VALUE_ERR_MSG', [1, 65535]),
      range: [1, 65535],
    }),
  ],
  realm: [BaseValidators.Pattern({ pattern: STR_MATCH_0_255 })],
});
const formSchema = new Schema(kerRules);
const kerPoperState = reactive({
  domain: false,
  address: false,
});
// 激活或隐藏poper
function togglePopper(target: string, value: boolean) {
  kerPoperState[target] = value;
}
// 领域
function domainChange() {
  computedState();
}
// 服务器地址
function addrChange() {
  computedState();
}
// 端口
function portChange() {
  oldFormData.port = oldFormData.port.toString();
  computedState();
}

function triggerValidator(filed: string) {
  formRef.value.validateField(filed);
}

function pwdChange() {
  userPasswordMsg.value = '';
  computedState();
}
// 保存按钮的状态
function computedState() {
  let hasError = false;
  formSchema.validate(formData, (errors, fields) => {
    if (errors) {
      hasError = true;
    } else {
      hasError = false;
    }
  });
  // 表单是否修改
  const isChange = !compareObjectEqual(oldFormData, formData, 'userPassword');
  // 是否输入密码
  const hasPwd = formData.userPassword !== '' || nopwd ? true : false;
  saveBtnState.value = !hasError && hasPwd && (fileItem || isChange);
}
// 保存基本信息
function save() {
  if (!saveBtnState.value) {
    return;
  }
  loading(true);
  if (hasConfigUsers.value || systemLocked.value) {
    return;
  }
  if (!nopwd && formData.userPassword === '') {
    return;
  }
  paramData = {};
  if (oldFormData['realm'] !== formData.realm) {
    paramData['Domain'] = formData.realm;
  }
  if (oldFormData['server'] !== formData.server) {
    paramData['IPAddress'] = formData.server;
  }
  if (oldFormData['port'] !== formData.port) {
    paramData['Port'] = parseInt(formData.port);
  }
  let krbCert: FormData | null = null;
  if (fileItem && Object.keys(fileItem).length !== 0) {
    krbCert = new FormData();
    krbCert.append('imgfile', fileItem.raw, fileItem.name);
  }
  saveData(krbCert);
}
// 发送表单
function saveData(krbCert: any) {
  Promise.all([
    saveKerberos(paramData, formData.userPassword),
    uploadKrbCert({ secPwd: formData.userPassword, formData: krbCert as FormData }),
  ])
    .then(res => {
      showElMessage('success', traduction('COMMON_SUCCESS'));
    })
    .catch(error => {
      const errorId = getMessageId(error.data);
      if (errorId instanceof Array && errorId.length > 0) {
        const errorMsg = getErrorTranslate(errorId[0].code as string);
        if (errorId[0].code === 'ReauthFailed' || errorId[0].code === 'AuthorizationFailed') {
          userPasswordMsg.value = traduction('COMMON_SECONDPWD_ERROR');
        } else {
          showElMessage('error', errorMsg);
        }
      } else {
        showElMessage('error', traduction('COMMON_FAILED'));
      }
    })
    .finally(() => {
      getKer();
      loading(false);
      uploadRef.value.clear();
      formData.userPassword = '';
      computedState();
    });
}

function getKer() {
  getKerberos().then(res => {
    const item = {
      realm: res[1].realm,
      server: res[1].kerberosServerAddress,
      port: res[1].kerberosPort,
    };
    init(item);
  });
}

function init(val: any) {
  Object.assign(formData, val);
  oldFormData = JSON.parse(JSON.stringify(formData));
}

// 监听父组件数据
watch(
  () => props.data,
  newVal => {
    init(newVal);
  },
  { deep: true },
);
</script>
<template>
  <div class="ker-base">
    <h3>{{ $t('COMMON_BASE_ATTR') }}</h3>
    <div class="base-info">
      <el-form
        ref="formRef"
        :model="formData"
        :rules="kerRules"
        label-width="auto"
        label-position="left"
        :validate-on-rule-change="false"
        :disabled="isSystemLock"
      >
        <!-- 领域 -->
        <el-form-item :label="$t('KERBEROS_REALM')" prop="realm">
          <el-popover
            :content="$t('KERBEROS_REALM_TIPS')"
            :visible="kerPoperState.domain"
            :teleported="false"
            popper-class="ker-popover"
            placement="right"
            trigger="focus"
            trigger-keys
          >
            <template #reference>
              <el-input
                v-model="formData.realm"
                v-addId.input="'krbDomain'"
                v-clearable
                clearable
                maxlength="255"
                :disabled="!isPrivileges"
                @input="domainChange"
                @focus="togglePopper('domain', true)"
                @blur="togglePopper('domain', false)"
              >
                <template #suffix>
                  <ErrorIcon />
                  <ClearableIcon />
                </template>
              </el-input>
            </template>
          </el-popover>
        </el-form-item>
        <!-- 服务器地址 -->
        <el-form-item :label="$t('KERBEROS_SERVER_ADDR')" prop="server">
          <el-popover
            :content="$t('KERBEROS_SERVICE_TIPS')"
            :visible="kerPoperState.address"
            :teleported="false"
            popper-class="ker-popover"
            placement="right"
            trigger="focus"
            trigger-keys
          >
            <template #reference>
              <el-input
                v-model="formData.server"
                v-addId.input="'krbServer'"
                v-clearable
                clearable
                maxlength="255"
                :disabled="!isPrivileges"
                @input="addrChange"
                @focus="togglePopper('address', true)"
                @blur="togglePopper('address', false)"
              >
                <template #suffix>
                  <ErrorIcon />
                  <ClearableIcon />
                </template>
              </el-input>
            </template>
          </el-popover>
        </el-form-item>
        <!-- 端口 -->
        <el-form-item :label="$t('KERBEROS_PORT')" prop="port">
          <el-input
            v-model="formData.port"
            v-addId.input="'krbPort'"
            v-clearable
            clearable
            :disabled="!isPrivileges"
            :maxlength="5"
            @input="portChange"
            @clear="triggerValidator('port')"
          >
            <template #suffix>
              <ErrorIcon />
              <ClearableIcon />
            </template>
          </el-input>
        </el-form-item>
        <!-- 密钥表 -->
        <el-form-item :label="$t('KERBEROS_KEY_TABLES')" class="is-required">
          <FileUpload ref="uploadRef" :data="uploadConfig"></FileUpload>
          <span class="uploadTip">{{ $t('KERBEROS_SUPPORTED') }}</span>
        </el-form-item>
        <!-- 登录密码 -->
        <el-form-item
          v-if="!nopwd"
          :label="$t('COMMON_LOGIN_PASSWORD')"
          class="is-required"
          :error="userPasswordMsg"
        >
          <el-input
            v-model="formData.userPassword"
            v-addId.input="'secondPassword'"
            v-clearable
            clearable
            type="password"
            autocomplete="new-password"
            :maxlength="pwdMaxLen"
            :disabled="!isPrivileges"
            :placeholder="$t('COMMON_PASSWORD_PLACEHOLDER')"
            @input="pwdChange"
            @keyup.enter="save"
          >
            <template #suffix>
              <ErrorIcon />
              <ClearableIcon />
            </template>
          </el-input>
        </el-form-item>
        <!-- 保存按钮 -->
        <el-form-item>
          <el-button
            id="saveKrb"
            v-privil.base.userConfig
            :disabled="!saveBtnState || isSystemLock"
            type="primary"
            @click="save"
          >
            {{ $t('COMMON_SAVE') }}
          </el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.ker-base {
  .file-upload {
    display: inline-block;
    min-width: 320px;
    :deep(.el-input) {
      margin-right: 0;
    }
  }
  :deep(.is-required) {
    .el-form-item__label::before {
      content: '*';
      position: absolute;
      font-size: 12px;
      color: var(--o-form-require-color) !important;
      margin-right: 0 !important;
    }
  }
}
.base-info {
  margin-top: 16px;
}
:deep(.el-form-item) {
  &:nth-last-child(1) {
    margin: 0;
  }
  .el-input {
    max-width: 320px;
    margin-right: 8px;
  }
}
.uploadTip {
  margin-left: 16px;
  color: var(--o-text-color-tertiary);
}
</style>
<style>
.ker-popover.el-popover {
  width: auto !important;
  max-width: 382px !important;
}
</style>
