import { ref, onBeforeUnmount } from 'vue';
import { pageShopOrder } from '@/api/shop/shopOrder';
import type { ShopOrder } from '@/api/shop/shopOrder/model';
import { useUserStore } from '@/store/modules/user';

/**
 * 新订单提醒 - 全局单例轮询 + 红点徽章 + 声音/语音播报
 *
 * 设计要点：
 * 1. **全局单例**：轮询状态（timer、lastOrderId、enabled、hasNewOrder）全部为模块级变量，
 *    无论多少个组件调用 useOrderNotify()，始终只有一个轮询在运行，避免重复请求。
 * 2. **红点徽章**：检测到新订单时，调用 userStore.setMenuBadge 给「订单管理」菜单挂红点；
 *    进入订单列表页时调用 clearBadge() 清除，并同步 lastOrderId 为最新（标记“已查看”）。
 * 3. **声音/语音**：保留原 Web Audio 叮声 + Speech Synthesis 语音播报。
 * 4. **回调集合**：多组件可各自注册 onNewOrder 回调（如 dashboard 刷新统计、订单页刷新表格），
 *    检测到新订单时统一遍历触发。
 *
 * 生命周期：
 * - layout 组件挂载时调用 useOrderNotify() 并触发 start()，全局启动一次，常驻不停。
 * - dashboard / 订单列表页 / cms dashboard 调用 useOrderNotify() 仅消费状态与 UI，不重复启动。
 */

// ============ 配置 ============

/** 轮询间隔（毫秒） */
const POLL_INTERVAL = 60_000;

/** 叮声频率（Hz），880 = 高音叮 */
const DING_FREQUENCY = 880;

/** 叮声持续时间（秒） */
const DING_DURATION = 0.3;

/** 语音播报文案 */
const SPEECH_TEXT = '您有一条新的订单';

/** 订单管理菜单路径（红点挂在这里） */
const ORDER_MENU_PATH = '/shop/shopOrder';

// ============ 模块级共享状态（音频相关） ============

/** 音频上下文（模块级共享，延迟创建，需用户交互后） */
let audioCtx: AudioContext | null = null;

/** 用户交互解锁音频的监听器（模块级，全局只注册一次） */
let unlockHandler: (() => void) | null = null;

// ============ 模块级单例状态（轮询 + 红点） ============

/** 是否开启提醒（所有组件共享同一开关） */
const enabled = ref(true);

/** 是否有未查看的新订单（驱动红点 / 快速入口标记） */
const hasNewOrder = ref(false);

/** 轮询是否进行中 */
let polling = false;

/** 轮询定时器 */
let timerId: ReturnType<typeof setInterval> | null = null;

/** 上次记录的最新订单 ID（用于判断是否有新订单） */
let lastOrderId: number | undefined = undefined;

/** 是否已完成首次初始化（首次只记录基准，不触发提醒） */
let initialized = false;

/** 是否已全局启动（避免重复 start） */
let started = false;

/** 新订单回调集合（多组件注册，统一触发） */
const newOrderCallbacks = new Set<() => void>();

// ============ 声音播放 ============

/**
 * 初始化 AudioContext（必须在用户交互后调用才能生效）
 */
function initAudioContext() {
  if (!audioCtx) {
    try {
      audioCtx = new (window.AudioContext ||
        (window as any).webkitAudioContext)();
    } catch (e) {
      console.warn('[订单提醒] AudioContext 创建失败:', e);
      return;
    }
  }
  // 如果上下文被暂停（浏览器策略），尝试恢复
  if (audioCtx.state === 'suspended') {
    audioCtx.resume();
  }
}

/**
 * 注册用户交互监听器，首次交互时解锁音频
 * 浏览器策略：音频播放需要用户交互后才允许，注册一次性监听器自动解锁
 * 全局只注册一次，多实例共享
 */
function registerAudioUnlock() {
  if (unlockHandler) return;

  unlockHandler = () => {
    initAudioContext();
    // 解锁后移除监听器
    if (unlockHandler) {
      document.removeEventListener('click', unlockHandler);
      document.removeEventListener('keydown', unlockHandler);
      unlockHandler = null;
    }
  };

  document.addEventListener('click', unlockHandler, { once: true });
  document.addEventListener('keydown', unlockHandler, { once: true });
}

/**
 * 播放"叮"声 - 使用 Web Audio API 生成，无需音频文件
 */
function playDingSound() {
  if (!audioCtx) return;

  const now = audioCtx.currentTime;

  // 创建振荡器
  const oscillator = audioCtx.createOscillator();
  oscillator.type = 'sine';
  oscillator.frequency.setValueAtTime(DING_FREQUENCY, now);

  // 创建增益节点（控制音量包络）
  const gainNode = audioCtx.createGain();
  gainNode.gain.setValueAtTime(0, now);
  gainNode.gain.linearRampToValueAtTime(0.5, now + 0.01);
  gainNode.gain.exponentialRampToValueAtTime(0.001, now + DING_DURATION);

  // 连接：振荡器 → 增益 → 输出
  oscillator.connect(gainNode);
  gainNode.connect(audioCtx.destination);

  // 播放
  oscillator.start(now);
  oscillator.stop(now + DING_DURATION);
}

/**
 * 语音播报 - 使用浏览器原生 Speech Synthesis API
 */
function speak(text: string) {
  if (!('speechSynthesis' in window)) return;

  // 取消可能正在进行的播报
  window.speechSynthesis.cancel();

  const utterance = new SpeechSynthesisUtterance(text);
  utterance.lang = 'zh-CN';
  utterance.rate = 1;
  utterance.pitch = 1;
  utterance.volume = 1;

  window.speechSynthesis.speak(utterance);
}

/**
 * 触发提醒：叮声 + 语音播报 + 通知所有已注册回调
 */
function triggerNotify() {
  initAudioContext();
  playDingSound();
  speak(SPEECH_TEXT);
  // 触发所有已注册回调（刷新各页面数据）
  newOrderCallbacks.forEach((cb) => {
    try {
      cb();
    } catch (e) {
      console.warn('[订单提醒] 回调执行失败:', e);
    }
  });
}

// ============ 红点徽章控制 ============

/**
 * 设置/清除订单管理菜单的红点徽章
 * @param on true=显示红点，false=清除红点
 */
function setOrderBadge(on: boolean) {
  hasNewOrder.value = on;
  try {
    const userStore = useUserStore();
    if (on) {
      // 'dot' 表示纯红点（不显示数字），由 menu-title.vue 渲染为 a-badge dot
      userStore.setMenuBadge(ORDER_MENU_PATH, 'dot', '#ff4d4f');
    } else {
      // 传 undefined 清除徽章
      userStore.setMenuBadge(ORDER_MENU_PATH, undefined);
    }
  } catch (e) {
    console.warn('[订单提醒] 设置菜单红点失败:', e);
  }
}

// ============ 轮询逻辑 ============

/**
 * 检测是否有新订单
 * 只查最新 1 条，与 lastOrderId 比较：不同且更大则说明有新订单
 */
async function checkNewOrder() {
  if (!enabled.value) return;
  try {
    const result = await pageShopOrder({
      page: 1,
      limit: 1,
      type: 0
    });

    const latestOrder: ShopOrder | undefined = result?.list?.[0];

    if (!latestOrder) {
      lastOrderId = undefined;
      return;
    }

    const currentOrderId = latestOrder.orderId;

    if (!initialized) {
      // 首次只记录基准，不触发提醒
      lastOrderId = currentOrderId;
      initialized = true;
      return;
    }

    if (
      currentOrderId !== lastOrderId &&
      (lastOrderId === undefined || (currentOrderId ?? 0) > lastOrderId)
    ) {
      // 有新订单：声音 + 语音 + 回调 + 红点
      triggerNotify();
      setOrderBadge(true);
    }

    lastOrderId = currentOrderId;
  } catch (error) {
    console.warn('[订单提醒] 轮询查询失败:', error);
  }
}

function startPolling() {
  if (polling) return;
  polling = true;
  initialized = false;

  checkNewOrder();
  timerId = setInterval(checkNewOrder, POLL_INTERVAL);
}

function stopPolling() {
  polling = false;
  if (timerId) {
    clearInterval(timerId);
    timerId = null;
  }
}

// ============ 全局启动 / 停止 ============

/**
 * 全局启动订单提醒（由 layout 组件调用一次即可）
 * 内部用 started 标志保证幂等，重复调用安全
 */
function start() {
  if (started) return;
  started = true;
  registerAudioUnlock();
  if (enabled.value) {
    startPolling();
  }
}

/**
 * 清除红点并同步 lastOrderId 为当前最新订单（标记“已查看”）
 * 进入订单列表页时调用
 */
async function clearBadge() {
  // 立即清除红点（同步，体验即时）
  setOrderBadge(false);
  // 重新查询最新订单，把 lastOrderId 同步为最新，标记“已查看到此订单”
  // 这样后续只有比这个更新的订单才会再次触发红点
  try {
    const result = await pageShopOrder({ page: 1, limit: 1, type: 0 });
    const latest: ShopOrder | undefined = result?.list?.[0];
    lastOrderId = latest?.orderId;
    initialized = true;
  } catch (e) {
    console.warn('[订单提醒] 同步最新订单失败:', e);
  }
}

// ============ 对外接口 ============

/**
 * 新订单提醒组合式函数（全局单例）
 *
 * 用法：
 * ```ts
 * // layout 全局启动（仅一次）
 * const { start } = useOrderNotify();
 * start();
 *
 * // dashboard / 订单页消费状态与 UI
 * const { enabled, hasNewOrder, toggle, testNotify, clearBadge } = useOrderNotify({
 *   onNewOrder: () => reload()
 * });
 * ```
 *
 * @param options.onNewOrder 检测到新订单时的回调（组件卸载时自动移除）
 */
export function useOrderNotify(options?: { onNewOrder?: () => void }) {
  // 注册回调（组件卸载时自动移除，避免内存泄漏）
  const cb = options?.onNewOrder;
  if (cb) {
    newOrderCallbacks.add(cb);
    onBeforeUnmount(() => {
      newOrderCallbacks.delete(cb);
    });
  }

  // 开关切换
  const toggle = (value: boolean) => {
    enabled.value = value;
    if (value) {
      initAudioContext();
      startPolling();
    } else {
      stopPolling();
      setOrderBadge(false);
    }
  };

  // 测试提醒
  const testNotify = () => {
    initAudioContext();
    triggerNotify();
  };

  return {
    /** 是否开启提醒（响应式，所有组件共享） */
    enabled,
    /** 是否有未查看的新订单（响应式，驱动红点） */
    hasNewOrder,
    /** 开关切换 */
    toggle,
    /** 测试提醒（声音 + 语音） */
    testNotify,
    /** 清除红点并标记已查看（进入订单页时调用） */
    clearBadge,
    /** 全局启动（layout 调用一次） */
    start
  };
}
