<template>
  <div id="telemetry">
    <div class="syslog-info">
      <h3 class="top-title">{{ $t('TELEMETRY_OBSERVABILITY_SETTINGS') }}</h3>
      <el-form :ref="formRef" :model="formTelemetry" label-width="auto" label-position="left">
        <!-- 可观测使能 -->
        <el-form-item id="observabilityStateItem" :label="$t('TELEMETRY_OBSERVABILITY_ENABLED')" class="small-item">
          <el-switch 
            id="observabilityState" v-model="formTelemetry.state"
            :disabled="isSystemLock || !hasUserConfigPrivil" @change="stateChange"
          ></el-switch>
        </el-form-item>
        <!-- TLS -->
        <el-form-item id="authModeItem" :label="$t('TELEMETRY_TLS_MODE')" class="small-item">
          <el-radio-group
            v-model="formTelemetry.authMode.value" :disabled="isSystemLock || !hasUserConfigPrivil"
            @change="authModeChange"
          >
            <el-radio
              v-for="item in formTelemetry.authMode.list" :id="'observability' + item.id" :key="item.id"
              :label="item.id"
            >
              {{ $t(item.key) }}
            </el-radio>
          </el-radio-group>
        </el-form-item>
        <!-- 服务器根证书 -->
        <el-form-item id="observabilityCerItem" class="cer-item" :label="$t('TELEMETRY_RECEIVER_ROOT_CERTIFICATE')">
          <CertificateRedirect
            ref="redirectComp" :need-save="!isSaveBtnDisabled && !isSystemLock" message="CERTIFICATE_TO_CA"
            @callback="saveBtn(1)" @redirect="redirect()"
          />
        </el-form-item>
        <!-- 本地证书 -->
        <el-form-item
          v-if="formTelemetry.authMode.value === 'mTLS'" id="localCer" class="cer-item"
          :label="$t('ALARM_REPORT_SYSLOG_SERVICE_LOCAL_AUTH')"
        >
          <CertificateRedirect 
            ref="redirectSslComp" :need-save="!isSaveBtnDisabled && !isSystemLock"
            message="CERTIFICATE_TO_SSL" @callback="saveBtn(2)" @redirect="redirectSsl()"
          />
        </el-form-item>
        <el-form-item id="identifier" class="id-item" :label="$t('TELEMETRY_SERVER_IDENTITY')">
          <el-select 
            v-model="formTelemetry.serverIdentity.value" v-addId.select="'serverIdentity'"
            :disabled="isSystemLock || !hasUserConfigPrivil" :teleported="false" :suffix-icon="PullDownTriangle"
            @change="changeBtnStatus"
          >
            <el-option 
              v-for="item in formTelemetry.serverIdentity.options" 
              :key="item.id" 
              :label="item.key"
              :value="item.id"
            ></el-option>
          </el-select>
        </el-form-item>

        <!-- 跟踪数据配置 -->
        <div class="data-config-section">
          <h3 class="top-title">{{ $t('TELEMETRY_TRACE_CONFIG') }}</h3>
          <el-form-item :label="$t('TELEMETRY_TRACE_SAMPLING_POLICY')" class="small-item">
            <el-radio-group
              v-model="formTelemetry.tracePolicy.value" :disabled="isSystemLock || !hasUserConfigPrivil"
              @change="changeBtnStatus"
            >
              <el-radio v-for="item in formTelemetry.tracePolicy.list" :key="item.id" :label="item.id">
                {{ $t(item.label) }}
              </el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item :label="$t('TELEMETRY_TRACE_SAMPLING_LEVEL')" class="input-item">
            <el-select
              v-model="formTelemetry.levelPolicy.value" :disabled="isSystemLock || !hasUserConfigPrivil"
              :teleported="false" :suffix-icon="PullDownTriangle" @change="changeBtnStatus"
            >
              <el-option
                v-for="item in formTelemetry.levelPolicy.options" :key="item.id" :label="$t(item.label)"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-form-item :label="$t('TELEMETRY_TRACE_SAMPLING_RATE')" class="input-item">
            <el-select
              v-model="formTelemetry.samplingRate.left" :disabled="isSystemLock || !hasUserConfigPrivil || formTelemetry.tracePolicy.value === 'Adaptive'"
              v-addId.select="'samplingRate'"
              :teleported="false"
              :suffix-icon="PullDownTriangle"
              @change="changeBtnStatus"
            >
              <el-option
                v-for="item in formTelemetry.samplingRate.options"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-form-item :label="$t('TELEMETRY_EXPORT_PERIOD_SECONDS')" class="input-item" :error="tracePeriodError">
            <el-popover
              :visible="tracePeriodVisible"
              popper-class="no-wrap-popover"
              placement="right"
              :content="tracePeriodTip"
            >
              <template #reference>
                <el-input
                  v-model="formTelemetry.samplingRate.right" :disabled="isSystemLock || !hasUserConfigPrivil"
                  @input="changeBtnStatus"
                  @focus="tracePeriodVisible = true"
                  @blur="validateTraceExportInterval"
                />
              </template>
            </el-popover>
          </el-form-item>
        </div>

        <!-- 指标数据配置 -->
        <div class="data-config-section">
          <h3 class="top-title">{{ $t('TELEMETRY_METRICS_CONFIG') }}</h3>
          <el-form-item :label="$t('TELEMETRY_MONITORING_METRICS')" class="metrics-checkboxes">
            <div class="checkbox-grid">
              <el-checkbox
                v-for="item in formTelemetry.metrics.supportedOptions" :key="item.value"
                :model-value="formTelemetry.metrics.activatedOptions.includes(item.value)"
                :disabled="isSystemLock || !hasUserConfigPrivil"
                @change="(checked: boolean) => handleMetricChange(item.value, checked)"
              >
                {{ $t(item.label) }}
              </el-checkbox>
            </div>
          </el-form-item>
          <el-form-item :label="$t('TELEMETRY_EXPORT_PERIOD_SECONDS')" class="input-item" :error="metricsPeriodError">
            <el-popover
              :visible="metricsPeriodVisible"
              popper-class="no-wrap-popover"
              placement="right"
              :content="metricsPeriodTip"
            >
              <template #reference>
                <el-input
                  v-model="formTelemetry.metricsReportPeriod" :disabled="isSystemLock || !hasUserConfigPrivil"
                  @input="changeBtnStatus"
                  @focus="metricsPeriodVisible = true"
                  @blur="validateMetricsPeriod"
                />
              </template>
            </el-popover>
          </el-form-item>
        </div>

        <!-- 日志数据配置 -->
        <div class="data-config-section">
          <h3 class="top-title">{{ $t('TELEMETRY_LOG_CONFIG') }}</h3>
          <el-form-item :label="$t('TELEMETRY_LOG_COLLECTION_ENABLED')" class="small-item">
            <el-switch
              v-model="formTelemetry.logEnabled" :disabled="isSystemLock || !hasUserConfigPrivil"
              @change="changeBtnStatus"
            ></el-switch>
          </el-form-item>
          <el-form-item :label="$t('TELEMETRY_EXPORT_PERIOD_SECONDS')" class="input-item" :error="logPeriodError">
            <el-popover
              :visible="logPeriodVisible"
              popper-class="no-wrap-popover"
              placement="right"
              :content="logPeriodTip"
            >
              <template #reference>
                <el-input
                  v-model="formTelemetry.logReportPeriod" :disabled="isSystemLock || !hasUserConfigPrivil"
                  @input="changeBtnStatus"
                  @focus="logPeriodVisible = true"
                  @blur="validateLogPeriod"
                />
              </template>
            </el-popover>
          </el-form-item>
        </div>

        <el-form-item class="syslog-btns" :label="' '">
          <!-- 使用 v-if/v-else 强制 el-button 重新渲染，彻底解决响应式失效问题 -->
          <template v-if="!isSaveBtnDisabled">
            <el-button
              id="observabilitySaveBtn"
              type="primary"
              @click="saveBtn(0)"
            >
              {{ $t('COMMON_SAVE') }}
            </el-button>
          </template>
          <template v-else>
            <el-button
              id="observabilitySaveBtn"
              type="primary"
              disabled
            >
              {{ $t('COMMON_SAVE') }}
            </el-button>
          </template>
          <el-button v-show="!isSaveBtnDisabled" id="observabilityCancelBtn" @click="syslogCancelFun">
            {{ $t('COMMON_CANCEL') }}
          </el-button>
        </el-form-item>
      </el-form>
    </div>
    <div id="observabilityTableBox" class="syslog-syntax">
      <h3 id="observabilityTableTitle" class="table-title">{{ $t('TELEMETRY_RECEIVER_INFORMATION') }}</h3>
      <TelemetryTable
        :data="srcData.data" :is-system-lock="isSystemLock" :has-permission="hasUserConfigPrivil"
        :enabled="formTelemetry.state" @operate-change="tableChange"
      />
    </div>
  </div>
  <Dialog ref="commonDialogRef" :config="commonDialogConfig" @close="commonDialogClose" />
</template>

<script lang="ts" setup>
import { getErrorTranslate, traduction } from '@/utils/language';
import { computed, onMounted, reactive, ref, watch } from 'vue';
import {
  telemetrySave,
  getTelemetryInfo,
  telemetrySendTest,
} from '@/pages/Maintance/Telemetry/telemetry.service';
import TelemetryTable from './component/TelemetryTable.vue';
import GlobalStoreService from '@/services/gloabal-store-service';
import useStore from '@/stores';
import { loading, showFailedMessage, showSuccessMessage } from '@/utils/composition';
import { checkPrivil } from '@/apps/app-bmc/router/routes';
import { UserPrivil } from '@/model/base-enum';
import PullDownTriangle from '@/components/PullDownTriangle/PullDownTriangle.vue';
import { useRouter } from 'vue-router';
import CertificateRedirect from '@/pages/User/Certificate/CertificateRedirect.vue';
import Dialog from '@/components/Dialog/Dialog.vue';

enum SamplingPolicy {
  FIXED = 'Fixed',
  ADAPTIVE = 'Adaptive',
}

enum SamplingLevel {
  SYSTEM_LEVEL = 'System',
  COMPONENT_LEVEL = 'Component',
  FUNCTION_LEVEL = 'Function',
}

const DEFAULT_VALUES = {
  SAMPLING_POLICY: SamplingPolicy.FIXED,
  SAMPLING_LEVEL: SamplingLevel.SYSTEM_LEVEL,
  SAMPLING_RATE: 0,
  TRACE_EXPORT_INTERVAL: 20,
  METRICS_EXPORT_INTERVAL: 60,
  LOG_EXPORT_INTERVAL: 20,
} as const;

const SAMPLING_POLICY_OPTIONS = [
  { id: SamplingPolicy.FIXED, label: 'TELEMETRY_SAMPLING_POLICY_FIXED' },
  { id: SamplingPolicy.ADAPTIVE, label: 'TELEMETRY_SAMPLING_POLICY_ADAPTIVE' },
] as const;

const SAMPLING_LEVEL_OPTIONS = [
  { id: SamplingLevel.SYSTEM_LEVEL, label: 'TELEMETRY_SAMPLING_LEVEL_SYSTEM' },
  { id: SamplingLevel.COMPONENT_LEVEL, label: 'TELEMETRY_SAMPLING_LEVEL_COMPONENT' },
  { id: SamplingLevel.FUNCTION_LEVEL, label: 'TELEMETRY_SAMPLING_LEVEL_FUNCTION' },
] as const;

const METRICS_LABEL_MAP: Record<string, string> = {
  'bmc.hw.chip.io': 'TELEMETRY_METRICS_HW_CHIP_IO',
  'bmc.hw.chip.accessor': 'TELEMETRY_METRICS_HW_CHIP_ACCESSOR',
  'bmc.hw.chip.scanner': 'TELEMETRY_METRICS_HW_CHIP_SCANNER',
  'bmc.mc.flash.io': 'TELEMETRY_METRICS_MC_FLASH_IO',
  'bmc.rpc.client.request': 'TELEMETRY_METRICS_RPC_CLIENT_REQUEST',
  'bmc.persistence.server.request': 'TELEMETRY_METRICS_PERSISTENCE_SERVER_REQUEST',
  'bmc.persistence.flash.io': 'TELEMETRY_METRICS_PERSISTENCE_FLASH_IO',
  'bmc.broadcast.producer.send': 'TELEMETRY_METRICS_BROADCAST_PRODUCER_SEND',
  'bmc.system.uptime': 'TELEMETRY_METRICS_SYSTEM_UPTIME',
  'bmc.system.cpu.usage': 'TELEMETRY_METRICS_SYSTEM_CPU_USAGE',
  'bmc.system.memory.usage': 'TELEMETRY_METRICS_SYSTEM_MEMORY_USAGE',
  'bmc.process.cpu.usage': 'TELEMETRY_METRICS_PROCESS_CPU_USAGE',
  'bmc.process.memory.usage': 'TELEMETRY_METRICS_PROCESS_MEMORY_USAGE',
  'bmc.system.flash.io': 'TELEMETRY_METRICS_SYSTEM_FLASH_IO',
  'bmc.system.flash.lifeleft': 'TELEMETRY_METRICS_SYSTEM_FLASH_LIFELEFT',
};

interface ReceiverItem {
  Id: string;
  Address: string;
  Enabled: boolean;
  Port: number;
}

interface TracesConfig {
  SamplingRate: number;
  SamplingPolicy: SamplingPolicy;
  SamplingLevel: SamplingLevel;
  ExportIntervalSeconds: number;
}

interface MetricsConfig {
  ExportIntervalSeconds: number;
  SupportedMetrics: string[];
  ActivatedMetrics: string[];
}

interface LogsConfig {
  Enabled: boolean;
  ExportIntervalSeconds: number;
}

interface TelemetryResponse {
  TLSMode: string;
  ServiceEnabled: boolean;
  Receivers: ReceiverItem[];
  ServerIdentity: string;
  Traces?: TracesConfig;
  Metrics?: MetricsConfig;
  Logs?: LogsConfig;
}

interface SaveType {
  num: number;
  statusValue: any;
  serviceAddr: any;
  enabled: boolean;
  port: string | number | null;
}

interface TableItem {
  port: any;
  num: number;
  serviceAddr: any;
  enabled: boolean;
}

const redirectComp = ref();
const redirectSslComp = ref();
const commonDialogRef = ref();
const $router = useRouter();
const store = useStore();
const globalStoreService = new GlobalStoreService();

const isSystemLock = computed(() => store.state.glob.systemLocked);
const hasUserConfigPrivil = checkPrivil(UserPrivil.diagnosis);

const tempTableData: any[] = [];
const srcData = reactive({
  data: <any[]>[],
});

let defaultData: any = ref();
let response: TelemetryResponse;

const commonDialogConfig = reactive({
  id: 'observabilityTestModel',
  content: traduction('TELEMETRY_TEST_TIPS'),
  title: traduction('COMMON_CONFIRM'),
  cancelButton: {
    hide: true,
  },
});

const formTelemetry = reactive({
  state: false,
  authMode: {
    value: 'TLS',
    list: [
      {
        id: 'TLS',
        key: 'ALARM_REPORT_SYSLOG_AUTHOR_SINGLE',
      },
      {
        id: 'mTLS',
        key: 'ALARM_REPORT_SYSLOG_AUTHOR_DOUBLE',
      },
    ],
  },
  serverIdentity: {
    value: 'BoardSN',
    options: [
      {
        id: 'BoardSN',
        key: traduction('ALARM_REPORT_EMAIL_SUBJECT_1'),
      },
      {
        id: 'ProductAssetTag',
        key: traduction('ALARM_REPORT_EMAIL_SUBJECT_2'),
      },
      {
        id: 'HostName',
        key: traduction('ALARM_REPORT_EMAIL_SUBJECT_3'),
      },
    ],
  },
  tracePolicy: {
    value: DEFAULT_VALUES.SAMPLING_POLICY,
    list: SAMPLING_POLICY_OPTIONS,
  },
  levelPolicy: {
    value: DEFAULT_VALUES.SAMPLING_LEVEL,
    options: SAMPLING_LEVEL_OPTIONS,
  },
  samplingRate: {
    left: DEFAULT_VALUES.SAMPLING_RATE as number | string,
    right: DEFAULT_VALUES.TRACE_EXPORT_INTERVAL,
    options: [] as string[],
  },
  metrics: {
    supportedOptions: [] as Array<{ value: string; label: string }>,
    activatedOptions: [] as string[],
  },
  metricsReportPeriod: DEFAULT_VALUES.METRICS_EXPORT_INTERVAL,
  logEnabled: false,
  logReportPeriod: DEFAULT_VALUES.LOG_EXPORT_INTERVAL,
});

const formRef = ref();
const tracePeriodError = ref('');
const metricsPeriodError = ref('');
const logPeriodError = ref('');
const requiredError = traduction('VALID_REQUIRED_ERR');

const tracePeriodTip = traduction('VALIDTOR_TELE_INTGER_RANGE', [10, 30]);
const metricsPeriodTip = traduction('VALIDTOR_TELE_INTGER_RANGE', [30, 3600]);
const logPeriodTip = traduction('VALIDTOR_TELE_INTGER_RANGE', [10, 30]);

const tracePeriodVisible = ref(false);
const metricsPeriodVisible = ref(false);
const logPeriodVisible = ref(false);

function isEmpty(val: any): boolean {
  return val === null || val === undefined || (typeof val === 'string' && val.trim() === '');
}

function validateTraceExportInterval() {
  tracePeriodVisible.value = false;
  const val = formTelemetry.samplingRate.right;
  if (isEmpty(val)) {
    tracePeriodError.value = requiredError;
    return false;
  }
  const num = Number(val);
  if (isNaN(num) || !Number.isInteger(num) || num < 10 || num > 30) {
    tracePeriodError.value = tracePeriodTip;
    return false;
  }
  tracePeriodError.value = '';
  return true;
}

function validateMetricsPeriod() {
  metricsPeriodVisible.value = false;
  const val = formTelemetry.metricsReportPeriod;
  if (isEmpty(val)) {
    metricsPeriodError.value = requiredError;
    return false;
  }
  const num = Number(val);
  if (isNaN(num) || !Number.isInteger(num) || num < 30 || num > 3600) {
    metricsPeriodError.value = metricsPeriodTip;
    return false;
  }
  metricsPeriodError.value = '';
  return true;
}

function validateLogPeriod() {
  logPeriodVisible.value = false;
  const val = formTelemetry.logReportPeriod;
  if (isEmpty(val)) {
    logPeriodError.value = requiredError;
    return false;
  }
  const num = Number(val);
  if (isNaN(num) || !Number.isInteger(num) || num < 10 || num > 30) {
    logPeriodError.value = logPeriodTip;
    return false;
  }
  logPeriodError.value = '';
  return true;
}

function validateAll() {
  const validTraceExportInterval = validateTraceExportInterval();
  const validMetricsPeriod = validateMetricsPeriod();
  const validLogPeriod = validateLogPeriod();
  return validTraceExportInterval && validMetricsPeriod && validLogPeriod;
}

const isFormValid = computed(() => {
  return validateAll();
});

let isSaveBtnDisabled = ref(true);
watch(
  [defaultData.value, formTelemetry],
  (newValues, oldValues) => {
    const basicEqual = checkBasicFieldsEqual();
    const traceEqual = checkTraceFieldsEqual();
    const metricsEqual = checkMetricsFieldsEqual();
    const logEqual = checkLogFieldsEqual();
    const hasDiff = !(basicEqual && traceEqual && metricsEqual && logEqual);
    isSaveBtnDisabled.value = isSystemLock.value || !isFormValid.value || !hasDiff;
  },
  {
    deep: true,
  },
);

function isDataEqual(current: any, original: any, defaultValue: any): boolean {
  const convertedCurrent = typeof defaultValue === 'number' ? Number(current) : current;
  const compareTo = (original === undefined || original === null) ? defaultValue : original;
  return convertedCurrent === compareTo;
}

const hasChanges = (currentObj: Record<string, any>): boolean => {
  return Object.keys(currentObj).length > 0;
}

function handleMetricChange(metric: string, checked: boolean): void {
  const activatedOptions = formTelemetry.metrics.activatedOptions;
  if (checked && !activatedOptions.includes(metric)) {
    activatedOptions.push(metric);
  }
  if (!checked) {
    const index = activatedOptions.indexOf(metric);
    if (index > -1) {
      activatedOptions.splice(index, 1);
    }
  }
  changeBtnStatus();
}

function stateChange(): void {
  changeBtnStatus();
}

function authModeChange(): void {
  changeBtnStatus();
}

function checkBasicFieldsEqual(): boolean {
  const serviceEnabled = defaultData.value?.ServiceEnabled;
  const tlsMode = defaultData.value?.TLSMode;
  const serverIdentity = defaultData.value?.ServerIdentity;
  return isDataEqual(formTelemetry.state, serviceEnabled, false) &&
    isDataEqual(formTelemetry.authMode.value, tlsMode, 'TLS') &&
    isDataEqual(formTelemetry.serverIdentity.value, serverIdentity, 'BoardSN');
}

function checkTraceFieldsEqual(): boolean {
  const tracesData = defaultData.value?.Traces || {};
  const samplingPolicyEqual = isDataEqual(
    formTelemetry.tracePolicy.value,
    tracesData.SamplingPolicy,
    DEFAULT_VALUES.SAMPLING_POLICY,
  );
  const samplingLevelEqual = isDataEqual(
    formTelemetry.levelPolicy.value,
    tracesData.SamplingLevel,
    DEFAULT_VALUES.SAMPLING_LEVEL,
  );
  const samplingRateEqual = isDataEqual(
    formTelemetry.samplingRate.left,
    tracesData.SamplingRate,
    DEFAULT_VALUES.SAMPLING_RATE,
  );
  const exportIntervalEqual = isDataEqual(
    formTelemetry.samplingRate.right,
    tracesData.ExportIntervalSeconds,
    DEFAULT_VALUES.TRACE_EXPORT_INTERVAL,
  );
  return samplingPolicyEqual && samplingLevelEqual &&
    samplingRateEqual && exportIntervalEqual;
}

function checkOptionsFieldEqual(): boolean {
  const metricsData = defaultData.value?.Metrics || {};
  const currentOptions = JSON.stringify(formTelemetry.metrics.activatedOptions.sort());
  const originalOptions = JSON.stringify((metricsData.ActivatedMetrics || []).sort());
  return currentOptions === originalOptions;
}

function checkMetricsFieldsEqual(): boolean {
  const metricsData = defaultData.value?.Metrics || {};
  const periodEqual = isDataEqual(
    formTelemetry.metricsReportPeriod,
    metricsData.ExportIntervalSeconds,
    DEFAULT_VALUES.METRICS_EXPORT_INTERVAL,
  );
  return periodEqual && checkOptionsFieldEqual();
}

function checkLogFieldsEqual(): boolean {
  const logsData = defaultData.value?.Logs || {};
  const enabledEqual = isDataEqual(formTelemetry.logEnabled, logsData.Enabled, false);
  const periodEqual = isDataEqual(
    formTelemetry.logReportPeriod,
    logsData.ExportIntervalSeconds,
    DEFAULT_VALUES.LOG_EXPORT_INTERVAL,
  );
  return enabledEqual && periodEqual;
}

function changeBtnStatus(): void {
  if (formTelemetry.tracePolicy.value === 'Adaptive') {
    formTelemetry.samplingRate.left = defaultData.value?.Traces.SamplingRate;
  }
  isFormValid.value;
}

function buildBasicSaveParams(): Record<string, any> {
  const params: Record<string, any> = {};
  if (formTelemetry.state !== defaultData.value?.ServiceEnabled) {
    params.ServiceEnabled = formTelemetry.state;
  }
  if (formTelemetry.authMode.value !== defaultData.value?.TLSMode) {
    params.TLSMode = formTelemetry.authMode.value;
  }
  if (formTelemetry.serverIdentity.value !== defaultData.value?.ServerIdentity) {
    params.ServerIdentity = formTelemetry.serverIdentity.value;
  }
  return params;
}

function checkTracesChanges(tracesData: any): Record<string, boolean> {
  const defaultSamplingPolicy = tracesData.SamplingPolicy || DEFAULT_VALUES.SAMPLING_POLICY;
  const defaultSamplingLevel = tracesData.SamplingLevel || DEFAULT_VALUES.SAMPLING_LEVEL;
  const defaultSamplingRate = tracesData.SamplingRate || DEFAULT_VALUES.SAMPLING_RATE;
  const defaultExportInterval = tracesData.ExportIntervalSeconds ||
    DEFAULT_VALUES.TRACE_EXPORT_INTERVAL;
  return {
    policyChanged: formTelemetry.tracePolicy.value !== defaultSamplingPolicy,
    levelChanged: formTelemetry.levelPolicy.value !== defaultSamplingLevel,
    rateChanged: Number(formTelemetry.samplingRate.left) !== defaultSamplingRate,
    intervalChanged: Number(formTelemetry.samplingRate.right) !== defaultExportInterval,
  };
}

function buildTracesParams(): Partial<TracesConfig> {
  const tracesData = defaultData.value?.Traces || {};
  const tracesParam: Partial<TracesConfig> = {};
  const changes = checkTracesChanges(tracesData);
  if (changes.policyChanged) {
    tracesParam.SamplingPolicy = formTelemetry.tracePolicy.value;
  }
  if (changes.levelChanged) {
    tracesParam.SamplingLevel = formTelemetry.levelPolicy.value;
  }
  if (changes.rateChanged) {
    tracesParam.SamplingRate = Number(formTelemetry.samplingRate.left);
  }
  if (changes.intervalChanged) {
    tracesParam.ExportIntervalSeconds = Number(formTelemetry.samplingRate.right);
  }
  return tracesParam;
}

function buildMetricsParams(): Partial<MetricsConfig> {
  const metricsData = defaultData.value?.Metrics || {};
  const metricsParam: Partial<MetricsConfig> = {};
  const defaultExportInterval = metricsData.ExportIntervalSeconds ||
    DEFAULT_VALUES.METRICS_EXPORT_INTERVAL;
  if (Number(formTelemetry.metricsReportPeriod) !== defaultExportInterval) {
    metricsParam.ExportIntervalSeconds = Number(formTelemetry.metricsReportPeriod);
  }
  if (!checkOptionsFieldEqual()) {
    metricsParam.ActivatedMetrics = [...formTelemetry.metrics.activatedOptions];
  }
  return metricsParam;
}

function buildLogsParams(): Partial<LogsConfig> {
  const logsData = defaultData.value?.Logs || {};
  const logsParam: Partial<LogsConfig> = {};
  const defaultEnabled = logsData.Enabled || false;
  const defaultExportInterval = logsData.ExportIntervalSeconds ||
    DEFAULT_VALUES.LOG_EXPORT_INTERVAL;
  if (formTelemetry.logEnabled !== defaultEnabled) {
    logsParam.Enabled = formTelemetry.logEnabled;
  }
  if (Number(formTelemetry.logReportPeriod) !== defaultExportInterval) {
    logsParam.ExportIntervalSeconds = Number(formTelemetry.logReportPeriod);
  }
  return logsParam;
}

function buildSaveParams(): Record<string, any> {
  const saveParam = buildBasicSaveParams();
  const tracesParam = buildTracesParams();
  if (hasChanges(tracesParam)) {
    saveParam.Traces = tracesParam;
  }
  const metricsParam = buildMetricsParams();
  if (hasChanges(metricsParam)) {
    saveParam.Metrics = metricsParam;
  }
  const logsParam = buildLogsParams();
  if (hasChanges(logsParam)) {
    saveParam.Logs = logsParam;
  }
  return saveParam;
}

function saveBtn(redirectType: number): void {
  const saveParam = buildSaveParams();
  if (Object.keys(saveParam).length === 0) {
    getInfo();
    return;
  }
  telemetrySave(saveParam).then(
    () => {
      showSuccessMessage();
      getInfo();
      callbackSuccess(redirectType);
    },
    () => {
      showFailedMessage();
      callbackFail(redirectType);
    },
  );
}

function createValidationConfig(): Record<string, any> {
  return {
    validationAddr: {
      tip: traduction('COMMON_IPV4_IPV6_DOMIN'),
      tipPosition: 'right',
      errorMessage: {
        pattern: traduction('COMMON_FORMAT_ERROR'),
      },
    },
    validationPort: {
      tip: traduction('VALIDTOR_RANGE'),
      tipPosition: 'right',
      errorMessage: {
        number: traduction('ALARM_REPORT_RANGESIZE'),
        digits: traduction('ALARM_REPORT_RANGESIZE'),
        rangeValue: traduction('ALARM_REPORT_RANGESIZE'),
      },
    },
  };
}

function createTableItem(item: ReceiverItem): Record<string, any> {
  const portValue = item.Port === 0 ? null : item.Port;
  const validationConfig = createValidationConfig();
  const obj: Record<string, any> = {
    num: Number(item.Id) + 1,
    serviceAddr: item.Address,
    enabled: item.Enabled,
    port: portValue,
    isEdit: false,
    ...validationConfig,
  };
  obj.canSave = Boolean(obj.port && obj.serviceAddr);
  return obj;
}

function setTableData(response: TelemetryResponse): void {
  const data: any[] = [];
  response.Receivers.forEach((item: ReceiverItem) => {
    data.push(createTableItem(item));
  });
  srcData.data = data;
}

function getInfo(): void {
  globalStoreService.setValue('isLoading', true);
  getTelemetryInfo()
    .then((res: any) => {
      defaultData.value = res.data;
      response = res.data as TelemetryResponse;
      init(response);
      if (response.Receivers && response.Receivers.length > 0) {
        setTableData(response);
      }
      globalStoreService.setValue('isLoading', false);
    })
    .catch(() => {
      globalStoreService.setValue('isLoading', false);
    });
}

function initBasicFields(response: TelemetryResponse): void {
  formTelemetry.state = response.ServiceEnabled;
  formTelemetry.authMode.value = response.TLSMode;
  formTelemetry.serverIdentity.value = response.ServerIdentity;
}

function initTraceFields(response: TelemetryResponse): void {
  const tracesData: any = response.Traces || {};
  const defaultSamplingPolicy = tracesData.SamplingPolicy || DEFAULT_VALUES.SAMPLING_POLICY;
  const defaultSamplingLevel = tracesData.SamplingLevel || DEFAULT_VALUES.SAMPLING_LEVEL;
  const defaultSamplingRate = tracesData.SamplingRate || DEFAULT_VALUES.SAMPLING_RATE;
  const defaultExportInterval = tracesData.ExportIntervalSeconds ||
    DEFAULT_VALUES.TRACE_EXPORT_INTERVAL;
  formTelemetry.tracePolicy.value = defaultSamplingPolicy;
  formTelemetry.levelPolicy.value = defaultSamplingLevel;
  formTelemetry.samplingRate.left = defaultSamplingRate;
  formTelemetry.samplingRate.options = tracesData.SupportedSamplingRate.map((item: any) => ({
    id: item,
    label: item,
  }));
  formTelemetry.samplingRate.right = defaultExportInterval;
}

function initMetricsFields(response: TelemetryResponse): void {
  const metricsData: any = response.Metrics || {};
  const defaultExportInterval = metricsData.ExportIntervalSeconds ||
    DEFAULT_VALUES.METRICS_EXPORT_INTERVAL;
  formTelemetry.metricsReportPeriod = defaultExportInterval;
  const supportedMetrics = metricsData.SupportedMetrics || [];
  formTelemetry.metrics.supportedOptions = supportedMetrics.map((metric: string) => ({
    value: metric,
    label: METRICS_LABEL_MAP[metric] || metric,
  }));
  formTelemetry.metrics.activatedOptions = [...(metricsData.ActivatedMetrics || [])];
}

function initLogFields(response: TelemetryResponse): void {
  const logsData: any = response.Logs || {};
  const defaultEnabled = logsData.Enabled || false;
  const defaultExportInterval = logsData.ExportIntervalSeconds ||
    DEFAULT_VALUES.LOG_EXPORT_INTERVAL;
  formTelemetry.logEnabled = defaultEnabled;
  formTelemetry.logReportPeriod = defaultExportInterval;
}

function init(response: TelemetryResponse): void {
  initBasicFields(response);
  initTraceFields(response);
  initMetricsFields(response);
  initLogFields(response);
}

function syslogCancelFun(): void {
  init(response);
  validateTraceExportInterval();
  validateMetricsPeriod();
  validateLogPeriod();
  changeBtnStatus();
}

function handleTableSave(value: any): void {
  value.isEdit = false;
  save(value);
}

function handleTableCancel(value: any): void {
  cancel(value);
  value.isEdit = false;
}

function handleTableEdit(value: any): void {
  tempTableData[value.num - 1] = {
    num: value.num,
    serviceAddr: value.serviceAddr,
    enabled: value.enabled,
    port: value.port,
  };
  value.isEdit = true;
  loading(false);
}

function handleTableTest(value: any): void {
  if (!isSaveBtnDisabled.value) {
    loading(false);
    commonDialogRef.value.show();
  } else {
    test(value);
  }
}

function tableChange(event: any): void {
  loading(true);
  const { key, value } = event;
  switch (key) {
    case 'save':
      handleTableSave(value);
      break;
    case 'cancel':
      handleTableCancel(value);
      break;
    case 'edit':
      handleTableEdit(value);
      break;
    case 'test':
      handleTableTest(value);
      break;
    default:
      loading(false);
      break;
  }
}

function updateServerListData(syslogServerList: any[], data: SaveType): void {
  const memberId = data.num - 1;
  syslogServerList.forEach(
    (item: { Id: any; Enabled: any; Address: any; Port: number }) => {
      if (Number(item.Id) === Number(memberId)) {
        data.serviceAddr = item.Address;
        data.enabled = item.Enabled;
        data.port = item.Port === 0 ? null : item.Port;
      }
    },
  );
}

function handleSaveResponse(responseData: any, data: SaveType): void {
  let syslogServerList = responseData?.Receivers;
  if (responseData.error) {
    showFailedMessage();
    syslogServerList = responseData.data?.Receivers;
  } else {
    showSuccessMessage();
  }
  if (syslogServerList && syslogServerList.length > 0) {
    updateServerListData(syslogServerList, data);
  }
}

function save(data: SaveType): void {
  const params = {
    Receivers: [
      {
        Id: data.num - 1,
        Address: data.serviceAddr,
        Enabled: data.enabled,
        Port: parseInt(data.port as string, 10),
      },
    ],
  };
  telemetrySave(params)
    .then((res: any) => {
      handleSaveResponse(res.data, data);
      loading(false);
    })
    .catch(() => {
      loading(false);
      showFailedMessage();
    });
}

function cancel(data: TableItem): void {
  const tempData = tempTableData[data.num - 1];
  if (tempData) {
    data.serviceAddr = tempData.serviceAddr;
    data.port = tempData.port;
    data.enabled = tempData.enabled;
    tempTableData[data.num - 1] = null;
  }
  loading(false);
}

function test(data: { num: number }): void {
  const params = {
    ReceiverId: Number(data.num - 1),
  };
  telemetrySendTest(params)
    .then(() => {
      loading(false);
      showSuccessMessage(traduction('ALARM_REPORT_TEST_MESSAGE'));
    })
    .catch((error: any) => {
      loading(false);
      const code = error?.data?.error[0]?.code;
      if (code) {
        showFailedMessage(getErrorTranslate(code));
        return;
      }
      showFailedMessage();
    });
}

function commonDialogClose(): void {
  commonDialogRef.value.hide();
}

function redirect(): void {
  $router.push('/navigate/user/certificate/ca-certificate-list');
}

function callbackSuccess(redirectType: number): void {
  if (redirectType === 1) {
    redirectComp.value.hide();
    $router.push('/navigate/user/certificate/ca-certificate-list');
    return;
  }
  if (redirectType === 2) {
    redirectSslComp.value.hide();
    $router.push('/navigate/user/certificate/ssl-certificate');
    return;
  }
}

function redirectSsl(): void {
  $router.push('/navigate/user/certificate/ssl-certificate');
}

function callbackFail(redirectType: number): void {
  if (redirectType === 1) {
    redirectComp.value.hide();
    return;
  }
  if (redirectType === 2) {
    redirectSslComp.value.hide();
    return;
  }
}

onMounted(() => {
  getInfo();
});
</script>

<style lang="scss" scoped>
#syslog {
  margin-right: 24px;
  height: calc(100% - 104px);
}

#syslogCerItem {
  height: 16px;

  :deep(.el-form-item__label-wrap) {
    .el-form-item__label {
      padding-top: 0px;
    }
  }
}

#localCer {
  height: 16px;

  :deep(.el-form-item__label-wrap) {
    .el-form-item__label {
      padding-top: 0px;
    }
  }
}

.top-title {
  font-size: 16px;
  color: var(--o-text-color-primary);
  line-height: 24px;
  margin-bottom: 16px;
}

.syslog-info {
  background-color: var(--o-bg-color-base);
  border-radius: 4px;
  padding: 24px;
  margin-bottom: 16px;

  .el-select {
    width: 320px;
  }
}

.syslog-syntax {
  background-color: var(--o-bg-color-base);
  border-radius: 4px;
  padding: 24px;
}

#syslogAlert {
  font-size: 12px;
  color: var(--o-color-major);
  letter-spacing: 0;
  line-height: 16px;
  margin-left: 8px;
}

.cer-item {
  :deep(.el-form-item__content) {
    display: flex;
    justify-content: space-between;
  }

  .cer-box {
    width: calc((100% - 16px) / 2);
    display: flex;
    flex-direction: column;

    &.full-width {
      width: 100%;
    }
  }

  .local-cer {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    min-height: 100%;
  }

  .upload-dialog-label {
    font-size: 12px;
    color: var(--o-text-color-secondary);
    letter-spacing: 0;
    line-height: 32px;
    margin-right: 24px;
  }
}

.cer-file-upload {
  .el-form-item__content {
    position: relative;

    #uploadx {
      position: absolute;
      right: 24px;
      top: -4px;
    }
  }
}

.table-title {
  font-size: 16px;
  color: var(--o-text-color-primary);
  line-height: 24px;
  margin-bottom: 16px;
}

.syslog-btns {
  margin-bottom: 0;
}

:deep(.small-item) {
  height: 16px;

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

  .el-form-item__content {
    line-height: 16px;
  }

  .el-radio {
    height: 16px;
  }

  .el-radio__label {
    color: var(--o-text-color-secondary);
  }
}

.data-config-section {
  margin-top: 24px;

  .top-title {
    font-size: 16px;
    color: var(--o-text-color-primary);
    line-height: 24px;
    margin-bottom: 16px;
  }
}

.sampling-item {
  :deep(.el-form-item__content) {
    width: 100%;
  }

  .sampling-inputs {
    display: flex;
    align-items: center;
    gap: 16px;
    width: 100%;

    .el-input {
      width: 320px;
      flex: none;
    }

    .upload-label {
      font-size: 12px;
      color: var(--o-text-color-secondary);
      white-space: nowrap;
      margin: 0 8px;
    }
  }
}

.metrics-checkboxes {
  :deep(.el-form-item__content) {
    width: 100%;
  }

  .checkbox-grid {
    display: flex;
    flex-wrap: wrap;
    column-gap: 64px;
    width: 100%;

    .el-checkbox {
      margin-right: 0;

      :deep(.el-checkbox__label) {
        font-size: 12px;
        color: var(--o-text-color-secondary);
      }
    }
  }
}

:deep(.input-item .el-input) {
  width: 320px;
}

:deep(.input-item .el-select) {
  width: 320px;
}
</style>
