<script setup lang="ts">
import { computed, ref } from 'vue';

import { showElMessage } from '@/utils/utils';
import { getStoreData } from '@/utils/composition';
import { getErrorTranslate, traduction } from '@/utils/language';
import TableNoData from '@/components/TableNoData/TableNoData.vue';
import SecondPassword from '@/components/SecondPassword/SecondPassword.vue';

import { CurrDataEntry, UpdateVmDigestParams, VmComponent, VmDataEntry } from '../tpcm.datatype';
import { setStandardDigest, updateSwitches } from '../tpcm.service';

interface ColumnProps {
  label: string;
  prop: string;
}

const props = defineProps<{
  srcData: {
    data: VmDataEntry[];
    [k: string]: any;
  };
}>();

const emits = defineEmits(['refresh']);

const nopwd = getStoreData('loct', 'nopwd');
const secondRef = ref();
const updateSecondRef = ref();
const updateModalVisible = ref(false);
const saveTarget = ref<CurrDataEntry | null>(null);
const refreshTarget = ref<VmComponent | null>(null);
const refreshInput = ref();
const syncAll = ref(false);
const currentPage = ref(1);
const pageSizeCount = ref(10);
const totalSize = computed(() => props.srcData.data.length);

let currData = computed(() => {
  const start = (currentPage.value - 1) * pageSizeCount.value;
  const end = start + pageSizeCount.value;
  return props.srcData.data.map(item => ({
    ...item,
    editData: {
      isEditing: false,
      measureEnabled: item.measureEnabled,
      measureControlAllowed: item.measureControlAllowed,
    },
  })).slice(start, end);
});

const alertTitle = traduction('TPCM_BASELINE_TIP');
const columns: ColumnProps[] = [
  {
    label: traduction('TPCM_VM_HOSTNAME'),
    prop: 'name',
  },
  {
    label: traduction('TPCM_VM_UUID'),
    prop: 'uuid',
  },
  {
    label: traduction('TPCM_VM_METRIC_STATUS'),
    prop: 'measureEnabled',
  },
  {
    label: traduction('TPCM_VM_CONTROL_STATUS'),
    prop: 'measureControlAllowed',
  },
  {
    label: traduction('TPCM_VM_CONSISTENCY'),
    prop: 'isMatch',
  },
  {
    label: traduction('TPCM_VM_OPERATION'),
    prop: 'operation',
  },
];

const subColumns: ColumnProps[] = [
  {
    label: traduction('TPCM_MEASURED_TARGET'),
    prop: 'measuredObject',
  },
  {
    label: traduction('TPCM_VERSION'),
    prop: 'version',
  },
  {
    label: traduction('TPCM_PLATFORM_STATUS_REGISTER'),
    prop: 'vpcr',
  },
  {
    label: traduction('TPCM_ACTUAL_MEASUREMENT_VALUE'),
    prop: 'actualDigest',
  },
  {
    label: traduction('TPCM_BASE_VALUE'),
    prop: 'standardDigest',
  },
  {
    label: traduction('TPCM_VM_CONSISTENCY'),
    prop: 'isMatch',
  },
  {
    label: traduction('TPCM_VM_OPERATION'),
    prop: 'operation',
  },
];

function entryHasChanged(row: CurrDataEntry): boolean {
  return row.measureEnabled !== row.editData.measureEnabled ||
    row.measureControlAllowed !== row.editData.measureControlAllowed;
}

function updateEditing(row: CurrDataEntry, isEditing: boolean): void {
  row.editData.isEditing = isEditing;
}

function handleRowCancel(row: CurrDataEntry): void {
  row.editData = {
    isEditing: false,
    measureEnabled: row.measureEnabled,
    measureControlAllowed: row.measureControlAllowed,
  };
}

async function entrySaveService(password?: string): Promise<void> {
  const st = saveTarget.value as CurrDataEntry;
  try {
    await updateSwitches(st, password);
    st.measureEnabled = st.editData.measureEnabled;
    st.measureControlAllowed = st.editData.measureControlAllowed;
    showElMessage('success', traduction('COMMON_SUCCESS'));
  } catch (e: any) {
    showElMessage('error', getErrorTranslate(e.data?.error?.[0]?.code ?? 'COMMON_FAILED'));
    handleRowCancel(st);
  } finally {
    st.editData.isEditing = false;
  }
}

function handleEntrySave(row: CurrDataEntry): void {
  saveTarget.value = row;
  saveTarget.value.hostingSystemId = row.hostingSystemId;
  if (!nopwd) {
    secondRef.value.show();
  } else {
    entrySaveService();
  }
}

function handleUpdate(row: VmComponent): void {
  refreshTarget.value = row;
  refreshInput.value = row.actualDigest;
  updateModalVisible.value = true;
}

async function pswSave(res: { reason: boolean; password: string }) {
  if (res.reason) {
    await entrySaveService(btoa(res.password));
    secondRef.value.hide();
  } else {
    secondRef.value.hide();
  }
}

async function updateDigestService(password?: string): Promise<void> {
  const rt = refreshTarget.value as VmComponent;
  const vmIds = syncAll.value ? props.srcData.data.map(item => item.id) : [(rt.parent as VmDataEntry).id];
  const params: UpdateVmDigestParams = {
    hostingSystemId: (rt.parent as VmDataEntry).hostingSystemId,
    measuredObject: rt.measuredObject,
    vmIds,
    standardDigest: refreshInput.value,
    reauthKey: password,
  };
  try {
    await setStandardDigest(params);
    showElMessage('success', traduction('COMMON_SUCCESS'));
    emits('refresh');
  } catch (e: any) {
    showElMessage('error', getErrorTranslate(e.data?.error?.[0]?.code ?? 'COMMON_FAILED'));
  } finally {
    updateModalVisible.value = false;
  }
}

function handleUpdateSave(): void {
  if (!nopwd) {
    updateSecondRef.value.show();
  } else {
    updateDigestService();
  }
}

async function update(res: { reason: boolean; password: string }) {
  if (res.reason) {
    await updateDigestService(btoa(res.password));
    updateSecondRef.value.hide();
  } else {
    updateSecondRef.value.hide();
  }
}

</script>

<template>
  <el-alert type="info" show-icon :title="alertTitle" :closable="false"></el-alert>
  <div id="vmMetricsTable">
    <el-table v-addId.table="'vmTableComponent'" :data="currData" row-key="id">
      <el-table-column type="expand">
        <template #default="ed">
          <div class="subTable" v-if="ed.row.measureEnabled">
            <el-table :data="ed.row.components">
              <el-table-column v-for="col in subColumns" :key="col.label" v-bind="col">
                <template #default="sbr">
                  <span :id="`${col.prop}-${sbr.row.id}`">
                    <el-tag
                      v-if="col.prop === 'isMatch'"
                      :type="sbr.row.isMatch ? 'success' : 'danger'"
                      disable-transitions
                    >
                      {{ $t(sbr.row.isMatch ? 'COMMON_YES' : 'COMMON_NO') }}
                    </el-tag>
                    <el-button
                      v-else-if="col.prop === 'operation'"
                      type="text"
                      class="update-btn"
                      @click="handleUpdate(sbr.row)"
                    >
                      {{ $t('TPCM_UPDATE') }}
                    </el-button>
                    <template v-else>{{ sbr.row[col.prop] || '- -' }}</template>
                  </span>
                </template>
              </el-table-column>
            </el-table>
          </div>
          <div class="noVmMeasurements" v-else>
            <img src="@/assets/common/image/no-data.svg" />
            <div>{{ $t('TPCM_TRUST_MESURE_OFF_TEXT') }}</div>
          </div>
        </template>
      </el-table-column>
      <el-table-column v-for="col in columns" :key="col.label" v-bind="col">
        <template #default="dt">
          <span :id="`${col.prop}-${dt.row.id}`">
            <template v-if="['measureEnabled', 'measureControlAllowed'].includes(col.prop)">
              <el-switch
                v-if="dt.row.editData.isEditing"
                v-model="dt.row.editData[col.prop]"
              ></el-switch>
              <el-tag v-else :type="dt.row[col.prop] ? 'success' : 'danger'" disable-transitions>
                {{ $t(dt.row[col.prop] ? 'COMMON_YES' : 'COMMON_NO') }}
              </el-tag>
            </template>
            <template v-else-if="col.prop === 'isMatch'">
              <template v-if="dt.row.isMatch == null || !dt.row.measureEnabled">{{ '- -' }}</template>
              <el-tag
                v-else
                :type="dt.row.isMatch ? 'success' : 'danger'"
                disable-transitions
              >
                {{ $t(dt.row.isMatch ? 'COMMON_YES' : 'COMMON_NO') }}
              </el-tag>
            </template>
            <div
              v-else-if="col.prop === 'operation'"
              class="btn-panel"
            >
              <el-button
                v-if="dt.row.editData.isEditing"
                :id="`saveBtn-${dt.row.id}`"
                type="text"
                class="update-btn"
                :disabled="!entryHasChanged(dt.row)"
                @click="handleEntrySave(dt.row)"
              >
                {{ $t('COMMON_SAVE') }}
              </el-button>
              <el-button
                v-if="dt.row.editData.isEditing"
                :id="`cancelBtn-${dt.row.id}`"
                type="text"
                class="update-btn"
                @click="handleRowCancel(dt.row)"
              >
                {{ $t('COMMON_CANCEL') }}
              </el-button>
              <el-button
                v-if="!dt.row.editData.isEditing"
                :id="`editBtn-${dt.row.id}`"
                type="text"
                class="update-btn"
                @click="updateEditing(dt.row, true)"
              >
                {{ $t('COMMON_EDIT') }}
              </el-button>
            </div>
            <template v-else>{{ dt.row[col.prop] }}</template>
          </span>
        </template>
      </el-table-column>
      <template #empty>
        <TableNoData />
      </template>
    </el-table>
    <el-pagination
      v-model:current-page="currentPage"
      v-addId.pagination="'vmPage'"
      :page-sizes="[10, 15, 30, 50]"
      :page-size="pageSizeCount"
      layout="total, sizes, prev, pager, next, jumper"
      :total="totalSize"
      @size-change="(e: number) => pageSizeCount = e"
    ></el-pagination>
    <el-dialog
      v-model="updateModalVisible"
      :title="$t('TPCM_UPDATE')"
      width="30%"
    >
      <div>
        <el-alert
          :title="$t('TPCM_UPDATE_VM_TIP')"
          type="info"
          show-icon
          :closable="false"
          class="alertDiv"
        />
        <el-form ref="updateBasicRef" label-width="auto">
          <el-form-item :label="$t('TPCM_BASE_VALUE_LABEL')" prop="baselinePreValue">
            <el-input
              id="baselineVal"
              v-model="refreshInput"
              clearable
              maxlength="64"
            ></el-input>
            <el-checkbox
              v-model="syncAll"
              :label="$t('TPCM_VM_SYNC_TIP')"
            ></el-checkbox>
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
        <span>
          <el-button
            id="webOkBtn"
            type="primary"
            @click="handleUpdateSave()"
          >
            {{ $t('COMMON_SAVE') }}
          </el-button>
          <el-button id="webCancelBut" @click="updateModalVisible = false">
            {{ $t('ALARM_CANCEL') }}
          </el-button>
        </span>
      </template>
    </el-dialog>
    <SecondPassword ref="secondRef" @close="pswSave" />
    <SecondPassword ref="updateSecondRef" @close="update" />
  </div>
</template>

<style lang="scss" scoped>
#vmMetricsTable {
  margin-top: 16px;
}

.subTable {
  padding: 0 24px;
}

.noVmMeasurements {
  text-align: center;
}

.update-btn {
  min-width: unset !important;
}

:deep(.el-button) {
  span {
    min-width: unset !important;
  }
}

.alertDiv {
  margin-bottom: 16px;
}

#vmPage {
  margin-top: 16px;
}

:deep(.el-tag) {
  min-width: unset !important;
  max-width: unset !important;
  padding: 0 14px !important;
}

:deep(.el-dialog__body .el-checkbox) {
  margin-top: 8px;
}

</style>