// composables/useAlertMarquee.ts
// 通知状态管理 — 模块级单例
// 消息队列 / 通知中心抽屉 / 详情弹窗 / 悬浮滚动条位置
// 获取：SSE 主通道 + 10s 轮询降级 + 每60s全量对账

import { ref, computed, onBeforeUnmount } from "vue";
import baseService from "@/service/baseService";
import app from "@/constants/app";
import { getToken } from "@/utils/cache";

export type AlertLevel = "info" | "warning" | "danger";

export interface AlertMessage {
  id: string;
  level: AlertLevel;
  title: string;
  content: string;
  publishTime: string;
}

// ---------- sessionStorage 辅助 ----------

const SEEN_KEY = "alert_last_seen_id";

function getLastSeenId(): string {
  try {
    return sessionStorage.getItem(SEEN_KEY) || "";
  } catch {
    return "";
  }
}

function setLastSeenId(id: string): void {
  try {
    sessionStorage.setItem(SEEN_KEY, id);
  } catch {
    console.error("useAlertMarquee: sessionStorage.setItem 失败");
  }
}

// ---------- 模块级单例状态 ----------

/** 通知队列（最新在末尾） */
const messages = ref<AlertMessage[]>([]);

/** 通知中心抽屉是否打开 */
const drawerVisible = ref(false);

/** 当前查看详情的消息（null = 详情弹窗关闭） */
const detailTarget = ref<AlertMessage | null>(null);

/** 悬浮滚动条拖拽位置 */
const position = ref<{ x: number; y: number }>({ x: 0, y: 0 });

/** 队列上限 */
const MAX_QUEUE = 50;

// ---------- 计算属性 ----------

/** 最新一条通知 */
const latestMessage = computed(() => {
  return messages.value.length > 0
    ? messages.value[messages.value.length - 1]
    : null;
});

/** 通知数量 */
const messageCount = computed(() => messages.value.length);

/** 是否有通知 */
const hasMessages = computed(() => messages.value.length > 0);

/** 仅紧急 (danger) 级别的通知 */
const dangerMessages = computed(() =>
  messages.value.filter((m) => m.level === "danger")
);

/** 最新一条紧急通知（悬浮滚动条展示用） */
const latestDangerMessage = computed(() => {
  return dangerMessages.value.length > 0
    ? dangerMessages.value[dangerMessages.value.length - 1]
    : null;
});

/** 紧急通知数量 */
const dangerCount = computed(() => dangerMessages.value.length);

/** 是否有紧急通知 */
const hasDangerMessages = computed(() => dangerMessages.value.length > 0);

/** 详情弹窗是否可见 */
const detailVisible = computed({
  get: () => detailTarget.value !== null,
  set: (v: boolean) => {
    if (!v) detailTarget.value = null;
  }
});

/** 按时间倒序排列的消息（最新在前，给通知中心和详情列表用） */
const messagesReversed = computed(() => [...messages.value].reverse());

// ---------- 后端 API ----------

async function fetchNotifications(): Promise<AlertMessage[]> {
  const lastId = messages.value.length > 0
    ? messages.value[messages.value.length - 1].id
    : getLastSeenId() || "0";
  const res = await baseService.get(`/sys/alert/active/since?since=${lastId}`);
  if (res.code === 0 && Array.isArray(res.data)) {
    return res.data.map((item: AlertMessage) => ({
      ...item,
      content: item.title ? `【${item.title}】${item.content}` : item.content
    }));
  }
  return [];
}

/** 全量对账：从服务端拉取所有活跃通知ID，清除本地已撤回/已删除的通知 */
async function reconcileAlerts(): Promise<void> {
  try {
    const res = await baseService.get("/sys/alert/active");
    if (res.code === 0 && Array.isArray(res.data)) {
      const serverIds = new Set((res.data as AlertMessage[]).map((a) => a.id));
      const before = messages.value.length;
      messages.value = messages.value.filter((m) => serverIds.has(m.id));
      if (messages.value.length < before && messages.value.length > 0) {
        const maxId = messages.value.reduce((max, m) => (m.id > max ? m.id : max), messages.value[0].id);
        setLastSeenId(maxId);
      }
    }
  } catch {
    console.error("useAlertMarquee: 全量对账失败");
  }
}

// ---------- SSE 实时推送 + 轮询降级 ----------

let eventSource: EventSource | null = null;
let pollingTimer: ReturnType<typeof setInterval> | null = null;
let started = false;

/** 合并新通知到队列 */
function mergeNewAlerts(newMsgs: AlertMessage[]): void {
  if (newMsgs.length === 0) return;

  const existingIds = new Set(messages.value.map((m) => m.id));
  for (const msg of newMsgs) {
    if (!existingIds.has(msg.id)) {
      messages.value.push(msg);
    }
  }

  if (messages.value.length > MAX_QUEUE) {
    messages.value = messages.value.slice(messages.value.length - MAX_QUEUE);
  }
}

/** 建立 SSE 实时推送连接 */
function initSse(): void {
  let token: string;
  try {
    token = getToken();
    if (!token) return;
  } catch {
    console.error("useAlertMarquee: 获取token失败，SSE初始化取消");
    return;
  }

  const baseUrl = app.api || "";
  const url = `${baseUrl}/sys/alert/stream?token=${encodeURIComponent(token)}`;

  eventSource = new EventSource(url);

  eventSource.addEventListener("alert", (e: MessageEvent) => {
    try {
      const alert = JSON.parse(e.data) as AlertMessage;
      mergeNewAlerts([alert]);
    } catch {
      console.error("useAlertMarquee: SSE alert 事件解析失败");
    }
  });

  eventSource.addEventListener("alert-withdrawn", (e: MessageEvent) => {
    try {
      const { id } = JSON.parse(e.data) as { id: string };
      removeAlert(id);
    } catch {
      console.error("useAlertMarquee: SSE alert-withdrawn 事件解析失败");
    }
  });

  eventSource.addEventListener("alert-deleted", (e: MessageEvent) => {
    try {
      const { ids } = JSON.parse(e.data) as { ids: string[] };
      for (const id of ids) {
        removeAlert(id);
      }
    } catch {
      console.error("useAlertMarquee: SSE alert-deleted 事件解析失败");
    }
  });

  eventSource.onerror = () => {
    // SSE 连接失败，关闭并降级为轮询
    closeSse();
    startPollingFallback();
  };
}

/** 关闭 SSE 连接 */
function closeSse(): void {
  if (eventSource) {
    eventSource.close();
    eventSource = null;
  }
}

/** 降级轮询（SSE 失败时自动启动，每 10 秒增量拉取 + 每 60 秒全量对账） */
function startPollingFallback(): void {
  if (pollingTimer !== null) return;
  let tick = 0;
  pollingTimer = setInterval(async () => {
    try {
      const data = await fetchNotifications();
      mergeNewAlerts(data);
      tick++;
      if (tick % 6 === 0) {
        await reconcileAlerts();
      }
    } catch {
      console.error("useAlertMarquee: 轮询拉取通知失败");
    }
  }, 10000);
}

/** 启动通知获取：先 REST API 拉存量，再建立 SSE 连接 */
async function startPolling(_intervalMs?: number): Promise<void> {
  if (started) return;
  started = true;

  // 先通过 REST API 拉取存量通知
  try {
    const data = await fetchNotifications();
    mergeNewAlerts(data);
  } catch {
    console.error("useAlertMarquee: 启动时拉取存量通知失败");
  }

  // 尝试建立 SSE 连接（失败则降级为轮询）
  initSse();
}

function stopPolling(): void {
  closeSse();
  if (pollingTimer !== null) {
    clearInterval(pollingTimer);
    pollingTimer = null;
  }
  started = false;
}

// ---------- 通知中心抽屉 ----------

function toggleDrawer(): void {
  drawerVisible.value = !drawerVisible.value;
}

function openDrawer(): void {
  drawerVisible.value = true;
}

function closeDrawer(): void {
  drawerVisible.value = false;
}

// ---------- 详情弹窗 ----------

function showDetail(msg: AlertMessage): void {
  detailTarget.value = msg;
}

function closeDetail(): void {
  detailTarget.value = null;
}

// ---------- 消息操作 ----------

/** 外部推送一条警告 */
function pushAlert(msg: AlertMessage): void {
  const existingIds = new Set(messages.value.map((m) => m.id));
  if (!existingIds.has(msg.id)) {
    messages.value.push(msg);
  }
  if (messages.value.length > MAX_QUEUE) {
    messages.value = messages.value.slice(messages.value.length - MAX_QUEUE);
  }
}

/** 删除单条通知 */
function removeAlert(id: string): void {
  // 如果正在查看的详情就是这条，先关闭弹窗
  if (detailTarget.value?.id === id) {
    detailTarget.value = null;
  }
  messages.value = messages.value.filter((m) => m.id !== id);
  if (messages.value.length === 0) {
    drawerVisible.value = false;
  }
}

/** 清空全部通知 */
function clearAll(): void {
  if (messages.value.length > 0) {
    const maxId = messages.value.reduce(
      (max, m) => (m.id > max ? m.id : max),
      messages.value[0].id
    );
    setLastSeenId(maxId);
  }
  messages.value = [];
  drawerVisible.value = false;
  detailTarget.value = null;
}

/** 设置拖拽位置 */
function setPosition(pos: { x: number; y: number }): void {
  position.value = pos;
}

// ---------- composable 导出 ----------

export function useAlertMarquee() {
  onBeforeUnmount(() => {
    stopPolling();
  });

  return {
    // 消息
    messages,
    messagesReversed,
    latestMessage,
    messageCount,
    hasMessages,
    // 紧急通知（悬浮滚动条用）
    dangerMessages,
    latestDangerMessage,
    dangerCount,
    hasDangerMessages,
    // 通知中心
    drawerVisible,
    toggleDrawer,
    openDrawer,
    closeDrawer,
    // 详情
    detailTarget,
    detailVisible,
    showDetail,
    closeDetail,
    // 滚动条位置
    position,
    setPosition,
    // 操作
    pushAlert,
    removeAlert,
    clearAll,
    // 轮询
    fetchNotifications,
    mergeNewAlerts,
    startPolling,
    stopPolling
  };
}
