<template>
  <el-dialog
    v-model="dialogVisible"
    width="720px"
    :show-close="true"
    :close-on-click-modal="false"
    :before-close="handleDialogClose"
    destroy-on-close
    class="realtime-alarm-dialog"
  >
    <template #header>
      <div class="dialog-header">
        <div>
          <div class="dialog-kicker">REALTIME ALARM</div>
          <div class="dialog-title">{{ currentAlarm?.alarmTitle || '实时告警待处置' }}</div>
        </div>
        <div class="dialog-badges">
          <el-tag type="danger" effect="dark">实时告警</el-tag>
          <el-tag type="warning" effect="plain">待处理 {{ pendingCount }}</el-tag>
        </div>
      </div>
    </template>

    <template v-if="currentAlarm">
      <el-descriptions :column="2" border size="small" class="alarm-descriptions">
        <el-descriptions-item label="点位">{{ currentAlarm.monitorName || currentAlarm.monitorId || '-' }}</el-descriptions-item>
        <el-descriptions-item label="记录时间">{{ formatDateTime(currentAlarm.collectTime) }}</el-descriptions-item>
        <el-descriptions-item label="异常原因">{{ currentAlarm.cause || '-' }}</el-descriptions-item>
        <el-descriptions-item label="告警级别">{{ currentAlarm.alarmLevel || '-' }}</el-descriptions-item>
        <el-descriptions-item label="实际值">{{ formatValue(currentAlarm.actualValue ?? currentAlarm.alarmData) }}</el-descriptions-item>
        <el-descriptions-item label="阈值">{{ formatValue(currentAlarm.thresholdValue) }}</el-descriptions-item>
        <el-descriptions-item :span="2" label="告警内容">{{ currentAlarm.alarmContent || '-' }}</el-descriptions-item>
      </el-descriptions>

      <div class="sop-header">
        <div>
          <div class="sop-title">命中 SOP</div>
          <div class="sop-tip">按 `monitorId + cause` 实时命中处置步骤，避免值班人员还要二次检索。</div>
        </div>
        <el-button text type="primary" :loading="sopLoading" @click="loadRealtimeActionSteps(currentAlarm)">刷新 SOP</el-button>
      </div>

      <el-skeleton :loading="sopLoading" animated>
        <template #template>
          <div class="skeleton-row" v-for="index in 2" :key="index">
            <el-skeleton-item variant="p" style="width: 100%; height: 72px" />
          </div>
        </template>
        <template #default>
          <el-empty v-if="!actionSteps.length" description="当前告警未命中处置步骤，请补充规则措施配置" />
          <div v-else class="sop-list">
            <article v-for="step in actionSteps" :key="step.objId || step.stepSequence" class="sop-card">
              <div class="sop-sequence">步骤 {{ step.stepSequence || '-' }}</div>
              <div class="sop-desc">{{ step.description || '-' }}</div>
              <div v-if="step.remark" class="sop-remark">{{ step.remark }}</div>
              <div v-if="step.stepImages?.length" class="sop-image-list">
                <button
                  v-for="image in step.stepImages"
                  :key="image.objId || image.imageSequence"
                  type="button"
                  class="sop-image-card"
                  @click="previewImage(image.imageUrl)"
                >
                  <img :src="resolveImageUrl(image.imageUrl)" :alt="image.description || 'SOP 参考图'" />
                  <span>{{ image.description || `图片 ${image.imageSequence || ''}` }}</span>
                </button>
              </div>
            </article>
          </div>
        </template>
      </el-skeleton>
    </template>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="deferCurrentAlarm">稍后处理</el-button>
        <el-button @click="returnToHome">返回首页</el-button>
        <el-button type="primary" :loading="handling" @click="confirmCurrentAlarm">我已处理</el-button>
      </div>
    </template>
  </el-dialog>

  <transition name="fade-slide">
    <div v-if="deferredQueue.length" class="deferred-float">
      <div class="deferred-title">稍后处理队列</div>
      <div class="deferred-count">{{ deferredQueue.length }} 条待继续处理</div>
      <el-button size="small" type="primary" @click="resumeDeferredAlarm">继续处理</el-button>
    </div>
  </transition>

  <el-dialog v-model="imagePreviewVisible" title="SOP 参考图" width="760px" append-to-body>
    <div class="image-preview-container">
      <img :src="previewImageUrl" alt="SOP 参考图预览" />
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus';
import { parseTime } from '@/utils/ruoyi';
import { getEmsAlarmActionStepsByAlarmInfo } from '@/api/ems/base/emsAlarmActionStep';
import { handleExceptions } from '@/api/ems/record/recordAlarmData';
import { useAlarmRealtimeBus } from '@/utils/alarmRealtime';
import type { AlarmHandleResultVO, EmsAlarmActionStepVO, EmsRecordAlarmDataVO } from '@/api/ems/types';

const router = useRouter();

const dialogVisible = ref(false);
const handling = ref(false);
const sopLoading = ref(false);
const currentAlarm = ref<EmsRecordAlarmDataVO | null>(null);
const currentQueueSource = ref<'live' | 'deferred' | null>(null);
const liveQueue = ref<EmsRecordAlarmDataVO[]>([]);
const deferredQueue = ref<EmsRecordAlarmDataVO[]>([]);
const actionSteps = ref<EmsAlarmActionStepVO[]>([]);
const imagePreviewVisible = ref(false);
const previewImageUrl = ref('');
const handledKeys = reactive(new Set<string>());

const pendingCount = computed(() => liveQueue.value.length + deferredQueue.value.length + (currentAlarm.value ? 1 : 0));

const buildAlarmKey = (alarm?: EmsRecordAlarmDataVO | null) => {
  if (!alarm) {
    return '';
  }
  return String(alarm.objId ?? `${alarm.monitorId || ''}_${alarm.cause || ''}_${alarm.collectTime || ''}`);
};

const formatDateTime = (value?: string | Date | number | null) => (value ? parseTime(value, '{y}-{m}-{d} {h}:{i}:{s}') : '-');

const formatValue = (value?: string | number | null) => (value === null || value === undefined || value === '' ? '-' : value);

const resolveImageUrl = (imageUrl?: string | null) => {
  if (!imageUrl) {
    return '';
  }
  if (/^https?:\/\//.test(imageUrl)) {
    return imageUrl;
  }
  return `${import.meta.env.VITE_APP_BASE_API || ''}${imageUrl}`;
};

const previewImage = (imageUrl?: string | null) => {
  if (!imageUrl) {
    return;
  }
  previewImageUrl.value = resolveImageUrl(imageUrl);
  imagePreviewVisible.value = true;
};

const loadRealtimeActionSteps = async (alarm: EmsRecordAlarmDataVO) => {
  if (!alarm.monitorId || !alarm.cause) {
    actionSteps.value = [];
    return;
  }
  sopLoading.value = true;
  try {
    const response = await getEmsAlarmActionStepsByAlarmInfo(alarm.monitorId, alarm.cause);
    actionSteps.value = ((response as any).data ?? []) as EmsAlarmActionStepVO[];
  } catch (error) {
    actionSteps.value = [];
    ElMessage.warning('SOP 加载失败，请稍后重试');
  } finally {
    sopLoading.value = false;
  }
};

const openAlarmFromQueue = async (queueSource: 'live' | 'deferred') => {
  if (currentAlarm.value) {
    return;
  }
  const targetQueue = queueSource === 'live' ? liveQueue.value : deferredQueue.value;
  const nextAlarm = targetQueue.shift();
  if (!nextAlarm) {
    return;
  }
  currentAlarm.value = nextAlarm;
  currentQueueSource.value = queueSource;
  dialogVisible.value = true;
  await loadRealtimeActionSteps(nextAlarm);
};

const openNextLiveAlarm = async () => {
  if (!currentAlarm.value && liveQueue.value.length) {
    await openAlarmFromQueue('live');
  }
};

const enqueueRealtimeAlarms = async (alarms: EmsRecordAlarmDataVO[]) => {
  const newAlarms = alarms.filter((alarm) => {
    const alarmKey = buildAlarmKey(alarm);
    if (!alarmKey || handledKeys.has(alarmKey) || String(alarm.alarmStatus) === '0') {
      return false;
    }
    const isDuplicate =
      buildAlarmKey(currentAlarm.value) === alarmKey ||
      liveQueue.value.some((item) => buildAlarmKey(item) === alarmKey) ||
      deferredQueue.value.some((item) => buildAlarmKey(item) === alarmKey);
    return !isDuplicate;
  });
  if (!newAlarms.length) {
    return;
  }
  liveQueue.value.push(...newAlarms);
  await openNextLiveAlarm();
};

const consumeHandleResult = (result?: AlarmHandleResultVO | null) => {
  const updatedCount = Number(result?.updatedCount ?? 0);
  const alreadyHandledCount = Number(result?.alreadyHandledCount ?? 0);
  if (updatedCount > 0 || alreadyHandledCount > 0) {
    return true;
  }
  return false;
};

const clearCurrentAlarm = async () => {
  if (currentAlarm.value) {
    handledKeys.add(buildAlarmKey(currentAlarm.value));
  }
  currentAlarm.value = null;
  currentQueueSource.value = null;
  actionSteps.value = [];
  dialogVisible.value = false;
  await openNextLiveAlarm();
};

const confirmCurrentAlarm = async () => {
  if (!currentAlarm.value?.objId) {
    return;
  }
  handling.value = true;
  try {
    const response = await handleExceptions(currentAlarm.value.objId);
    const success = consumeHandleResult((response as any).data ?? null);
    if (!success) {
      ElMessage.warning((response as any).msg || '告警状态未更新，请刷新后重试');
      return;
    }
    ElMessage.success('告警状态已回写为已处理');
    await clearCurrentAlarm();
  } finally {
    handling.value = false;
  }
};

const deferCurrentAlarm = async () => {
  if (!currentAlarm.value) {
    dialogVisible.value = false;
    return;
  }
  // 稍后处理只保留在前端待办队列，不主动改写后端状态，避免把“未完成处置”误标为成功闭环。
  deferredQueue.value.push(currentAlarm.value);
  currentAlarm.value = null;
  currentQueueSource.value = null;
  actionSteps.value = [];
  dialogVisible.value = false;
  await openNextLiveAlarm();
};

const returnToHome = async () => {
  await router.push('/index');
  await deferCurrentAlarm();
};

const resumeDeferredAlarm = async () => {
  if (currentAlarm.value) {
    return;
  }
  await openAlarmFromQueue('deferred');
};

const handleDialogClose = async (done: () => void) => {
  await deferCurrentAlarm();
  done();
};

let stopBus: (() => void) | undefined;

onMounted(() => {
  stopBus = useAlarmRealtimeBus().on((event) => {
    void enqueueRealtimeAlarms(event.alarms || []);
  });
});

onUnmounted(() => {
  stopBus?.();
});
</script>

<style scoped>
.dialog-header {
  align-items: center;
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.dialog-kicker {
  color: var(--el-text-color-secondary);
  font-size: 12px;
  letter-spacing: 0.16em;
}

.dialog-title {
  color: var(--el-text-color-primary);
  font-size: 22px;
  font-weight: 700;
  margin-top: 6px;
}

.dialog-badges {
  display: flex;
  gap: 8px;
}

.alarm-descriptions {
  margin-bottom: 20px;
}

.sop-header {
  align-items: center;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.sop-title {
  font-size: 16px;
  font-weight: 600;
}

.sop-tip {
  color: var(--el-text-color-secondary);
  font-size: 13px;
  margin-top: 4px;
}

.skeleton-row + .skeleton-row {
  margin-top: 12px;
}

.sop-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sop-card {
  background: linear-gradient(135deg, rgba(250, 244, 235, 0.9), rgba(255, 249, 245, 0.95));
  border: 1px solid rgba(194, 154, 132, 0.22);
  border-radius: 16px;
  padding: 16px;
}

.sop-sequence {
  color: #9a5f44;
  font-size: 12px;
  letter-spacing: 0.12em;
}

.sop-desc {
  color: #43261c;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.7;
  margin-top: 8px;
}

.sop-remark {
  color: #7b665c;
  font-size: 13px;
  line-height: 1.7;
  margin-top: 8px;
}

.sop-image-list {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  margin-top: 12px;
}

.sop-image-card {
  align-items: stretch;
  background: #fff;
  border: 1px solid rgba(194, 154, 132, 0.24);
  border-radius: 14px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  text-align: left;
}

.sop-image-card img {
  border-radius: 10px;
  height: 110px;
  object-fit: cover;
  width: 100%;
}

.sop-image-card span {
  color: #5d463f;
  font-size: 12px;
  line-height: 1.5;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.deferred-float {
  background: rgba(68, 30, 22, 0.96);
  border-radius: 18px;
  bottom: 24px;
  box-shadow: 0 18px 40px rgba(33, 16, 12, 0.22);
  color: #fff6ef;
  padding: 16px 18px;
  position: fixed;
  right: 24px;
  width: 240px;
  z-index: 2100;
}

.deferred-title {
  font-size: 14px;
  font-weight: 600;
}

.deferred-count {
  color: rgba(255, 244, 235, 0.8);
  font-size: 12px;
  line-height: 1.7;
  margin: 8px 0 12px;
}

.image-preview-container {
  align-items: center;
  display: flex;
  justify-content: center;
  min-height: 320px;
}

.image-preview-container img {
  max-height: 70vh;
  max-width: 100%;
}

.fade-slide-enter-active,
.fade-slide-leave-active {
  transition: all 0.2s ease;
}

.fade-slide-enter-from,
.fade-slide-leave-to {
  opacity: 0;
  transform: translateY(8px);
}

@media (max-width: 768px) {
  .dialog-header {
    align-items: flex-start;
    flex-direction: column;
  }

  .dialog-badges {
    flex-wrap: wrap;
  }

  .deferred-float {
    bottom: 16px;
    left: 16px;
    right: 16px;
    width: auto;
  }
}
</style>
