<script setup lang="ts">
import TimeArea from './component/TimeArea.vue';
import DhcpServer from './component/DhcpServer.vue';
import { getNtpData, setNtpConfig } from '@/services/ntp-service';
import { INtpData, ITimeArea, IDHCPData, IPolling } from './models/ntp.datatype';
import { computed, reactive, ref } from 'vue';
import FileUpload from '@/components/FileUpload/FileUpload.vue';
import { UploadFile } from 'element-plus/es/components/upload/src/upload';
import { getErrorTranslate, traduction } from '@/utils/language';
import useStore from '@/stores';
import { ElForm } from 'element-plus';
import { maxPollingIntervalValid, minPollingIntervalValid } from './util/ntp.util';
import { UI_REST_NTP_IMPORTKEY } from '@/api/api';
import { IUploadConfig } from '@/model/base-interface';
import { IconCaretDown } from '@computing/opendesign-icons';
import { UserPrivil } from '@/model/base-enum';
import { checkPrivil } from '@/apps/app-bmc/router/routes';
import { loading, showFailedMessage, showSuccessMessage } from '@/utils/composition';
import { escapeHeader } from '@/utils/utils';

loading(true);
const store = useStore();
const loct = localStorage.getItem('loct');
const timeAreaData = reactive({} as ITimeArea);
const ntpData = reactive({} as INtpData);
const dhcpServerData = reactive({} as IDHCPData);
const isShow = ref(false);
const pollingList = ref([] as IPolling[]);
const ntpFormRef = ref<InstanceType<typeof ElForm>>();
const hasError = ref(false);
const sendParam = reactive({ value: {} } as any);
const dialogRef = ref();
let originData = null as any;
let timeAreaParam = {};
let ntpServerParam = {};
let ntpConfigParam = {};
let hasServerError = false;
let hasConfigError = false;
const keyRef = ref();
const isSystemLock = computed(() => {
  return store.state.glob.systemLocked;
});
const hasBasicConfig = checkPrivil(UserPrivil.baseConfig);
const dialogConfig = reactive({
  id: 'saveTipMessage',
  content: traduction('NTP_SAVE_TIP'),
  title: traduction('COMMON_CONFIRM'),
  closeOnEsc: true,
});

const formRules = reactive({
  minPollingInterval: [minPollingIntervalValid(ntpData)], // 传ntpData里的属性值为undefined，只能将整个ntpData传入
  maxPollingInterval: [maxPollingIntervalValid(ntpData)],
} as any);

const uploadConfig = reactive({
  data: {
    id: 'ntpUpload',
    action: UI_REST_NTP_IMPORTKEY,
    headers: {
      From: 'WebUI',
      'X-CSRF-Token': escapeHeader(loct ? JSON.parse(loct).to : ''),
    },
    method: 'POST',
    name: 'Content',
    data: { Type: 'URI' } as any,
    isAutoUpload: true,
    disabled: !hasBasicConfig || isSystemLock,
    accept: '.keys',
    type: 'button',
    onAddItem: (file: UploadFile, list: UploadFile[], msg?: any, upload?: any): void => {
      const lastDotIndex = file.name.lastIndexOf('.');
      const baseName = lastDotIndex !== -1 ? file.name.substring(0, lastDotIndex) : file.name;
      const type = lastDotIndex !== -1 ? file.name.substring(lastDotIndex + 1) : '';
      if (type === 'keys' && baseName.length > 0 && (file.size as any) <= 2048 * 1024) {
        return;
      }

      if (type !== 'keys' || baseName.length === 0) {
        showFailedMessage(traduction('NTP_UPLOAD_TYPE'));
      } else {
        showFailedMessage(traduction('COMMON_UPLOAD_FILE_MORN_1M_ERROR3'));
      }
      keyRef.value.clear();
    },
    onBeforeUpload: (file: UploadFile): boolean => {
      const lastDotIndex = file.name.lastIndexOf('.');
      const baseName = lastDotIndex !== -1 ? file.name.substring(0, lastDotIndex) : file.name;
      const type = lastDotIndex !== -1 ? file.name.substring(lastDotIndex + 1) : '';
      if (type === 'keys' && baseName.length > 0 && (file.size as any) <= 2048 * 1024) {
        return false;
      }
      return true;
    },
    onError: (error: any, file: UploadFile, list: UploadFile[]): void => {
      const errorCode = JSON.parse(error.message).error[0].code;
      showFailedMessage(getErrorTranslate(errorCode));
    },
    onSuccess: (response: any, file: UploadFile, list: UploadFile[]): void => {
      keyRef.value.clear();
      showSuccessMessage();

      getNtpData().then(res => {
        ntpData.keyStatus = res.KeyStatus;
      });
    },
  },
} as IUploadConfig);

getNtpData().then(res => {
  init(res);
});

function init(res: any) {
  isShow.value = false;
  originData = res;
  sendParam.value = {};
  timeAreaData.dateTimeLocalOffset = res.DateTimeLocalOffset;
  timeAreaData.timeZone = res.TimeZone;
  timeAreaData.timeZoneConfigurable = res.TimeZoneConfigurable;

  dhcpServerData.addressMode = res.AddressMode;
  dhcpServerData.alternateServer = res.AlternateServer;
  dhcpServerData.dhcpv4Enable = res.DHCPv4Enable;
  dhcpServerData.dhcpv6Enable = res.DHCPv6Enable;
  dhcpServerData.extraServer = res.ExtraServer;
  dhcpServerData.preferredServer = res.PreferredServer;
  dhcpServerData.serverCount = res.ServerCount;

  ntpData.authEnabled = res.AuthEnabled;
  ntpData.enabled = res.Enabled;
  ntpData.keyStatus = res.KeyStatus;
  ntpData.maxPollingInterval = res.MaxPollingInterval;
  ntpData.minPollingInterval = res.MinPollingInterval;
  initPollingList();
  setTimeout(() => {
    isShow.value = true;
    loading(false);
  }, 0);
}

function initPollingList() {
  pollingList.value = [];
  for (let i = 0; i < 15; i++) {
    pollingList.value.push({
      id: i + 3,
      label: 'NTP_TIME' + i,
    });
  }
}

function timeAreaChange(param: any) {
  timeAreaParam = param;
  sendParam.value = { ...timeAreaParam, ...ntpServerParam, ...ntpConfigParam };
}

function dhcpServerChange(noError: boolean, param: any) {
  if (noError) {
    ntpServerParam = param;
    sendParam.value = { ...timeAreaParam, ...ntpServerParam, ...ntpConfigParam };
  }
  hasServerError = !noError;
  hasError.value = hasConfigError || hasServerError;
}

function getParam(result: boolean) {
  hasConfigError = !result;
  hasError.value = hasConfigError || hasServerError;
  if (hasError.value) {
    return;
  }
  const params = {};
  if (ntpData.enabled !== originData.Enabled) {
    params['Enabled'] = ntpData.enabled;
  }

  if (ntpData.minPollingInterval !== originData.MinPollingInterval) {
    params['MinPollingInterval'] = ntpData.minPollingInterval;
  }
  if (ntpData.maxPollingInterval !== originData.MaxPollingInterval) {
    params['MaxPollingInterval'] = ntpData.maxPollingInterval;
  }
  if (ntpData.authEnabled !== originData.AuthEnabled) {
    params['AuthEnabled'] = ntpData.authEnabled;
  }

  ntpConfigParam = params;
  sendParam.value = { ...timeAreaParam, ...ntpServerParam, ...ntpConfigParam };
}

function change(id: string) {
  if (id === 'ntpTimeMin') {
    ntpFormRef.value?.clearValidate(['minPollingInterval', 'maxPollingInterval']);
    ntpFormRef.value?.validateField('minPollingInterval', result => {
      getParam(result);
    });
  } else if (id === 'ntpTimeMax') {
    ntpFormRef.value?.clearValidate(['minPollingInterval', 'maxPollingInterval']);
    ntpFormRef.value?.validateField('maxPollingInterval', result => {
      getParam(result);
    });
  } else {
    getParam(!hasConfigError);
  }
}

function save() {
  dialogRef.value.show();
}

function dialogClose(reason: boolean) {
  dialogRef.value.hide();
  if (reason) {
    setNtpConfig(sendParam.value).then(
      res => {
        if (res?.data?.error) {
          showFailedMessage(getErrorTranslate(res.data.error[0].code));
          init(res.data.data);
        } else {
          showSuccessMessage();
          init(res.data);
        }
        timeAreaParam = {};
        ntpServerParam = {};
        ntpConfigParam = {};
      },
      error => {
        const errorCode = error?.data?.error[0]?.code;
        if (errorCode) {
          showFailedMessage(getErrorTranslate(errorCode));
        }
        if (error?.data?.data) {
          init(error.data.data);
        }
      },
    );
  }
}
</script>

<template>
  <div id="ntp">
    <!-- 时区 -->
    <TimeArea
      v-if="isShow"
      :data="timeAreaData"
      :disabled="!hasBasicConfig || isSystemLock"
      @change="timeAreaChange"
    ></TimeArea>

    <!-- NTP -->
    <div id="ntpFunction">
      <div>
        <p v-t="'NTP_FUNCTION'" class="form-title"></p>
      </div>
      <el-form
        ref="ntpFormRef"
        :model="ntpData"
        :rules="formRules"
        label-width="auto"
        label-position="left"
        :validate-on-rule-change="false"
      >
        <el-form-item :label="$t('NTP_ENABLE')" :class="'small-height'">
          <el-switch
            id="ntpSwitch"
            v-model="ntpData.enabled"
            :disabled="!hasBasicConfig || isSystemLock"
            @change="change('ntpSwitch')"
          ></el-switch>
        </el-form-item>
        <el-form-item :label="$t('NTP_DHCP_AUTOGET')" class="dhcp">
          <DhcpServer
            v-if="isShow"
            :data="dhcpServerData"
            :disabled="!hasBasicConfig || isSystemLock"
            @change="dhcpServerChange"
          ></DhcpServer>
        </el-form-item>
        <el-form-item :label="$t('NTP_TIME_MIN')" prop="minPollingInterval">
          <el-select
            id="ntpTimeMin"
            v-model="ntpData.minPollingInterval"
            v-addId.select="'ntpTimeMin'"
            :suffix-icon="IconCaretDown"
            :disabled="!hasBasicConfig || isSystemLock"
            @change="change('ntpTimeMin')"
          >
            <el-option
              v-for="item in pollingList"
              :key="item.id"
              :label="$t(item.label)"
              :value="item.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item :label="$t('NTP_TIME_MAX')" prop="maxPollingInterval">
          <el-select
            id="ntpTimeMax"
            v-model="ntpData.maxPollingInterval"
            v-addId.select="'ntpTimeMax'"
            :suffix-icon="IconCaretDown"
            :disabled="!hasBasicConfig || isSystemLock"
            @change="change('ntpTimeMax')"
          >
            <el-option
              v-for="item in pollingList"
              :key="item.id"
              :label="$t(item.label)"
              :value="item.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item :label="$t('NTP_AUTHEN')" :class="'small-height'">
          <el-switch
            id="authenSwitch"
            v-model="ntpData.authEnabled"
            :disabled="!hasBasicConfig || isSystemLock"
            @change="change('authenSwitch')"
          ></el-switch>
        </el-form-item>
        <el-form-item
          :label="$t('NTP_UPLOAD')"
          class="ntp-key"
          :class="'small-height'"
        >
          <span
            v-t="ntpData.keyStatus !== 0 ? 'COMMON_UPLOADED' : 'COMMON_NOT_UPLOADED'"
            class="key-status"
            :class="{ uploaded: ntpData.keyStatus !== 0 }"
          ></span>
          <FileUpload ref="keyRef" class="upload" :data="uploadConfig.data"></FileUpload>
        </el-form-item>
        <el-form-item label=" ">
          <el-button
            id="ntpButton"
            type="primary"
            :disabled="hasError || JSON.stringify(sendParam.value) === '{}'"
            @click="save"
          >
            {{ $t('COMMON_SAVE') }}
          </el-button>
        </el-form-item>
      </el-form>
      <Dialog ref="dialogRef" :config="dialogConfig" @close="dialogClose" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
#ntp {
  margin-right: 24px;
  padding: 0 24px;
  background: var(--o-bg-color-base);
  border-radius: 4px;

  .upload {
    width: fit-content;
    display: inline-block;
  }

  .key-status {
    background: var(--o-text-color-tertiary);
    border-radius: var(--i-button-border-radius);
    color: var(--o-bg-color-base);
    height: 16px;
    padding: 0 14px;
    text-align: center;
    white-space: nowrap;
  }
  .uploaded {
    background: var(--o-color-success);
  }
}
</style>

<style lang="scss">
#ntp {
  .el-input {
    width: 320px;
  }
  .el-select {
    width: 320px;
  }
  .form-title {
    font-size: 16px;
    margin: 24px 0 16px;
    font-weight: 600;
  }
  .small-height {
    height: 16px;
    .el-form-item__content {
      line-height: 16px;
    }
    .el-form-item__label {
      padding-top: 0;
      padding-bottom: 0;
    }

    .el-radio {
      height: 16px;
      margin-bottom: 8px;
    }
  }
  .dhcp {
    .el-radio {
      height: 16px;
    }
    .server {
      margin-top: -8px;
    }
  }

  .ntp-key {
    .el-form-item__content {
      display: flex;
    }

    .upload-button {
      padding-top: 4px;
    }
  }
}
</style>
