<script setup lang="ts">
import { traduction, getErrorTranslate } from '@/utils/language';
import { cutStr, getBytes, showElMessage } from '@/utils/utils';
import { computed, nextTick, reactive, ref } from 'vue';
import useStore from '@/stores';
import { UserPrivil } from '@/model/base-enum';
import { checkPrivil } from '@/apps/app-bmc/router/routes';
import { IconUser, IconAlarm } from '@computing/opendesign-icons';
import Dialog from '@/components/Dialog/Dialog.vue';
import { getStoreData, loading, showFailedMessage, showSuccessMessage } from '@/utils/composition';
import SecondPassword from '@/components/SecondPassword/SecondPassword.vue';
import { assetRetire, retireProcess } from '../asset.service';
import { SecondAuthorityFail } from '@/model/base-enum';
import { ProgressBar, ProgressBarStatus } from '@/components/ProgressBar';
import { onMounted, onUnmounted } from 'vue';

enum EntryState {
  COMPLETED = 'Completed',
  RUNNING = 'Running',
  NEW = 'New',
  STARTING = 'Starting',
  EXCEPTION = 'Exception',
}

enum TaskStatus {
  SUCCESSFUL = 'Successful',
  TIMEOUT = 'Timeout',
  IDLE = 'Idle',
  EXECUTING = 'Executing',
  FAILED = 'Failed',
}

interface TaskDetailEntry {
  scope: 'RAID' | 'Disk' | 'Bios' | 'BMC';
  state: EntryState;
}

interface TaskData {
  details: TaskDetailEntry[];
  progress: number;
  status: TaskStatus;
}

const preserveLog = ref(true);
const store = useStore();
const systemLock = computed(() => {
  return store.state.glob.systemLocked;
});
const isPrivileges = checkPrivil(UserPrivil.userConfig);
const dialogRef = ref();
const dialogConfig = reactive({
  title: traduction('ASSET_MAINTANCE_SCAPPING_BTN'),
  content: ``,
  id: 'confirmAssetRetire'
});
const secondRef = ref();
const nopwd = getStoreData('loct', 'nopwd');
const taskData = ref<TaskData>();
const partFailed = ref<boolean>(false);
const timeoutHandler = ref<ReturnType<typeof setTimeout>>();
const asyncOperation = ref<boolean>(true);

const progressBarStatusMapping = new Map<TaskStatus, ProgressBarStatus>([
  [TaskStatus.EXECUTING, ProgressBarStatus.PROCESSING],
  [TaskStatus.IDLE, ProgressBarStatus.PREPARING],
  [TaskStatus.FAILED, ProgressBarStatus.ERROR],
  [TaskStatus.TIMEOUT, ProgressBarStatus.ERROR],
  [TaskStatus.SUCCESSFUL, ProgressBarStatus.PROCESSING],
]);

const entryStateTextMapping = new Map<EntryState, string>([
  [EntryState.STARTING, 'ASSET_MAINTANCE_RETIRE_MODULE_RUNNING'],
  [EntryState.NEW, 'ASSET_MAINTANCE_RETIRE_MODULE_RUNNING'],
  [EntryState.RUNNING, 'ASSET_MAINTANCE_RETIRE_MODULE_RUNNING'],
  [EntryState.COMPLETED, 'ASSET_MAINTANCE_RETIRE_MODULE_COMPLETED'],
  [EntryState.EXCEPTION, 'ASSET_MAINTANCE_RETIRE_MODULE_EXCEPTION'],
]);

const statusTextMapping = new Map<TaskStatus, string>([
  [TaskStatus.SUCCESSFUL, 'ASSET_MAINTANCE_RETIRE_STATUS_OK'],
  [TaskStatus.FAILED, 'ASSET_MAINTANCE_RETIRE_STATUS_CRITICAL'],
  [TaskStatus.EXECUTING, 'ASSET_MAINTANCE_RETIRE_STATUS_MAJOR'],
  [TaskStatus.TIMEOUT, 'ASSET_MAINTANCE_RETIRE_STATUS_TIMEOUT'],
]);

onMounted(() => {
  requestProgress();
});

onUnmounted(() => {
  asyncOperation.value = false;
  if (timeoutHandler.value) {
    clearTimeout(timeoutHandler.value);
  }
});

function dialogClose(reason: boolean) {
  dialogRef.value.hide();
  if (reason) {
    if (!nopwd) {
      secondRef.value.show();
    } else {
      loading(true);
      const params = {
        ReauthKey: '',
        PreserveLog: preserveLog.value
      };
      assetRetire(params)
        .then(() => {
          showSuccessMessage();
        })
        .catch((error: any) => {
          const errorCode = error?.data.error[0].code;
          showFailedMessage(getErrorTranslate(errorCode));
        })
        .finally(() => {
          loading(false);
        });
    }
  }
}

function getProgressBarStatus(status: TaskStatus) {
  if (partFailed.value) {
    return ProgressBarStatus.ERROR;
  }
  return progressBarStatusMapping.get(status)!;
}

function getEntryStateText(state: EntryState) {
  return entryStateTextMapping.get(state)!;
}

async function requestProgress() {
  if (!asyncOperation.value) {
    return;
  }
  const data = (await retireProcess()).data;
  taskData.value = {
    status: data.Status,
    details: data.Details.map((entry: any) => ({
      scope: entry.Scope,
      state: entry.State,
    })),
    progress: data.Progress,
  };
  partFailed.value = taskData.value.details.some(entry => entry.state === EntryState.EXCEPTION);
  const allSettled = [TaskStatus.SUCCESSFUL, TaskStatus.FAILED, TaskStatus.TIMEOUT].includes(taskData.value.status);
  if (!allSettled) {
    timeoutHandler.value = setTimeout(requestProgress, 1000);
  } else if (timeoutHandler.value) {
    clearTimeout(timeoutHandler.value);
  } else {}
}

function confirmReset(param: { reason: boolean; password: string }) {
  if (param.reason) {
    const params = {
      ReauthKey: window.btoa(param.password),
      PreserveLog: preserveLog.value
    };
    loading(true);
    assetRetire(params)
      .then(
        () => {
          showSuccessMessage();
          secondRef.value.hide();
          requestProgress();
        },
        (error: any) => {
          const errorCode = error.data.error[0].code;
          if (
            errorCode === SecondAuthorityFail.REAUTHFAILED ||
            errorCode === SecondAuthorityFail.AUTHORIZATIONFAILED
          ) {
            secondRef.value.setErrorId();
            secondRef.value.clearPassword();
          } else {
            showFailedMessage(getErrorTranslate(errorCode));
          }
        }
      )
      .finally(() => {
        loading(false);
      });
  } else {
    secondRef.value.hide();
  }
}

function click(): void {
  // 重置是否保留日志
  preserveLog.value = true;
  dialogRef.value.show();
}
</script>
<template>
  <div class="asset-retire-container">
    <el-button
      id="addWorkNoteBtn"
      :disabled="systemLock || !isPrivileges || 
        (taskData && [TaskStatus.EXECUTING, TaskStatus.SUCCESSFUL, TaskStatus.TIMEOUT].includes(taskData.status))"
      type="primary"
      style="width: max-content"
      @click="click"
    >
      {{ $t('ASSET_MAINTANCE_SCAPPING_BTN') }}
    </el-button>
    <div v-if="taskData && taskData.status !== TaskStatus.IDLE">
      <div v-if="taskData" class="task-status">{{ $t(statusTextMapping.get(taskData.status)!) }}</div>
      <div class="asset-retire-progress-panel">
        <div class="status-text">
          <div class="total-progress">{{ $t('ASSET_MAINTAIN_SCAPPING_TOTAL_PROGRESS') }}</div>
          <div class="percentage-text">
            <span class="percentage-value">{{ taskData?.progress }}</span>
            <span class="perc-symbol">%</span>
          </div>
        </div>
        <ProgressBar 
          :status="getProgressBarStatus(taskData?.status ?? TaskStatus.IDLE)" 
          :percentage="taskData?.progress"
        />
        <ul class="entry-list">
          <li v-for="entry in (taskData?.details ?? [])" :key="entry.scope">
            <img v-if="entry.state === EntryState.EXCEPTION" src="@/assets/common/image/failed.svg" />
            <img v-else-if="entry.state === EntryState.COMPLETED" src="@/assets/common/image/succeed.svg" />
            <img class="rotation" v-else src="@/assets/common/image/running.svg" />
            <span>{{ traduction(getEntryStateText(entry.state), [entry.scope]) }}</span>
          </li>
        </ul>
      </div>
    </div>
  </div>
  
  <Dialog ref="dialogRef" :config="dialogConfig" @close="dialogClose">
    <template #other>
      <div class="asset-dialog">
        <el-icon :size="24">
          <IconAlarm />
        </el-icon>
        <div class="asset-content">
          <p>{{ $t('ASSET_MAINTANCE_SCAPPING_TIP1') }}</p>
          <p>{{ $t('ASSET_MAINTANCE_SCAPPING_TIP2') }}</p>
          <!-- 选择框 -->
          <el-checkbox
            v-model="preserveLog"
            v-addId.checkbox="'logCheckbox'"
            :label="$t('ASSET_MAINTANCE_PRESERVE_LOG')"
            size="large"
          ></el-checkbox>
        </div>
      </div>
    </template>
  </Dialog>
  <SecondPassword ref="secondRef" @close="confirmReset" />
</template>
<style lang="scss" scoped>
.asset-retire-container {
  flex: 1;
  background-color: var(--o-bg-color-base);
  border-radius: 4px;
  padding: 16px;
  display: flex;
  flex-direction: column;
}

.asset-content {
  margin-left: 16px;
}

.asset-dialog {
  display: flex;
}

.asset-retire-progress-panel {
  width: 401px;
}

.task-status {
  margin-top: 24px;
  margin-bottom: 24px;
  font-size: 16px;
  line-height: 24px;
  font-weight: bold;
}

.status-text {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
  .total-progress {
    font-size: 16px;
    line-height: 24px;
    color: #4E5865;
  }

  .percentage-value {
    font-size: 40px;
    line-height: 48px;
  }

  .perc-symbol {
    font-size: 12px;
    margin-left: 4px;
    margin-bottom: 6px;
    color: #4E5865;
  }
}

.entry-list {
  @keyframes rotate {
    from {
      transform: rotate(0);
    }

    to {
      transform: rotate(360deg);
    }
  }
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;

  li {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .rotation {
    animation: 1s linear rotate infinite;
  }
}
</style>
