/**
 * 实物金价 hooks（UniApp 单例模式实现）
 * @description 封装实物金价、黄金9999、铂金、白银、K金的价格获取与实时更新逻辑，通过单例WebSocket避免多页面连接超限，结合缓存减少接口请求
 *
 * 核心特性：
 * 1. 单例WebSocket：全局唯一连接，通过引用计数管理生命周期（页面全部隐藏时断开，任一页面显示时重连）
 * 2. 多金属支持：基础黄金(RTJ_Au)、黄金9999(AU9999)、铂金(RTJ_Pt)、白银(RTJ_Ag)、K金（自动计算，基础黄金75%）
 * 3. 数据自动处理：实时更新销售价/回收价/调整价，自动维护当日最高/最低价
 * 4. 缓存优化：接口请求结果缓存30秒，避免重复请求减轻服务器压力
 * 5. 错误容错：WebSocket断连自动重连（3秒延迟），数据解析异常捕获日志
 *
 * 依赖项：
 * - vue：ref/watch 响应式能力
 * - @dcloudio/uni-app：页面生命周期（onShow/onHide/onUnload）
 * - @/api/abacus：getCurrentPrice 接口（获取初始金价）
 * - pako：WebSocket消息解压（gzip格式）
 * - @/hooks/useSocket：WebSocket基础封装（需支持on/send/connect/disconnect方法）
 * - @/utils/weAtob：base64解码工具（处理WebSocket消息）
 *
 * 注意事项：
 * - WebSocket地址（wss://litews.jjh9999.com/wsv2/）、token（junit:test）
 * - 缓存时长（CACHE_DURATION）默认30秒，可根据需求调整
 * - K金价格依赖基础黄金自动计算（75%比例），无需额外接口请求
 */
import { ref, watch } from "vue";
import { onShow, onHide, onUnload } from "@dcloudio/uni-app";
import { getCurrentPrice } from "@/api/abacus";
import pako from "pako/dist/pako.min.js";
import useWebSocket from "@/hooks/useSocket";
import { weAtob } from "@/utils";

// WebSocket单例核心变量
let wsInstance = null;
let connectCount = 0;
let isConnected = false;
const dataCallbacks = new Set();

// 初始化WebSocket单例
const initWSSingleton = () => {
  if (wsInstance) return wsInstance;

  // 创建WebSocket实例
  const ws = useWebSocket("wss://litews.jjh9999.com/wsv2/", {
    heartbeat: false,
    heartbeatInterval: 20000,
  });

  // 初始化参数
  ws.on("open", () => {
    console.log("WS单例连接成功");
    isConnected = true;
    ws.send({
      company_id: "2289041670615554",
      id: "2189041670615552",
      code: 1,
      token: "junit:test",
      type: 1,
    });
  });

  // 接收消息：统一解析并分发给所有注册的回调
  ws.on("message", (msg) => {
    try {
      const strData = weAtob(msg.data);
      const charData = strData.split("").map((x) => x.charCodeAt(0));
      const binData = new Uint8Array(charData);
      const tempData = pako.inflate(binData, { to: "string" });
      const { data } = JSON.parse(tempData);

      if (data && data?.code !== 0) {
        const itemData = JSON.parse(data);
        if (itemData?.priceDataNew) {
          const priceData = {
            itemAu: itemData.priceDataNew.find((v) => v.gmCode === "RTJ_Au"),
            itemAu9999: itemData.priceDataNew.find(
              (v) => v.gmCode === "AU9999"
            ),
            itemPt: itemData.priceDataNew.find((v) => v.gmCode === "RTJ_Pt"),
            itemAg: itemData.priceDataNew.find((v) => v.gmCode === "RTJ_Ag"),
          };
          dataCallbacks.forEach((callback) => callback(priceData));
        }
      }
    } catch (error) {
      console.error("WS单例消息处理错误：", error);
    }
  });

  // 连接关闭：若仍有页面使用，3秒后自动重连
  ws.on("close", () => {
    isConnected = false;
    if (connectCount > 0) {
      setTimeout(() => ws.connect(), 3000);
    }
  });

  ws.on("error", (error) => {
    console.error("WS单例连接错误：", error);
    isConnected = false;
  });

  wsInstance = ws;
  return ws;
};

const CACHE_DURATION = 30 * 1000; // 缓存有效期：30秒
const fetchCache = new Map();

export default function useRealGoldPrice(options) {
  const { realCode = "All" } = options || {};

  // 基础黄金（RTJ_Au）
  const realGoldprice = ref(0); // 实时销售价
  const realGoldRecyclePrice = ref(0); // 实时回收价
  const goldAdjustPrice = ref(0); // 调整价
  const goldTodayHigh = ref(0); // 今日最高价
  const goldTodayLow = ref(0); // 今日最低价

  // 黄金9999（AU9999）
  const realAu9999price = ref(0);
  const realAu9999RecyclePrice = ref(0);
  const Au9999AdjustPrice = ref(0);
  const au9999TodayHigh = ref(0);
  const au9999TodayLow = ref(0);

  // 铂金（RTJ_Pt）
  const realPtprice = ref(0);
  const realPtRecyclePrice = ref(0);
  const PtAdjustPrice = ref(0);
  const ptTodayHigh = ref(0);
  const ptTodayLow = ref(0);

  // 白银（RTJ_Ag）
  const realAgprice = ref(0);
  const realAgRecyclePrice = ref(0);
  const AgAdjustPrice = ref(0);
  const agTodayHigh = ref(0);
  const agTodayLow = ref(0);

  // K金（基础黄金75%自动计算）
  const realKGoldprice = ref(0);
  const realKGoldRecyclePrice = ref(0);
  const KGoldAdjustPrice = ref(0);
  const kGoldTodayHigh = ref(0);
  const kGoldTodayLow = ref(0);

  // 当前价（简化快捷访问）
  const currentGoldPrice = ref(0);
  const currentAu9999Price = ref(0);
  const currentPtPrice = ref(0);
  const currentAgPrice = ref(0);
  const currentKGoldPrice = ref(0);

  // 更新当日最高/最低价
  const updateHighLowPrices = (currentPrice, highRef, lowRef) => {
    const price = Number(currentPrice);
    if (isNaN(price)) return;

    // 首次设置价格时，同步初始化最高/最低价
    if (highRef.value === 0 && lowRef.value === 0) {
      highRef.value = price;
      lowRef.value = price;
      return;
    }

    highRef.value = Math.max(highRef.value, price);
    lowRef.value = Math.min(lowRef.value, price);
  };

  // 统一更新金属价格（销售价/回收价）
  const updatePrice = (
    item,
    sellPriceRef,
    recyclePriceRef,
    adjustPriceRef,
    highRef,
    lowRef
  ) => {
    if (item?.sellPrice?.price) {
      const sellPrice = (
        Number(item.sellPrice.price) + Number(adjustPriceRef.value)
      ).toFixed(2);
      sellPriceRef.value = sellPrice;
      updateHighLowPrices(sellPrice, highRef, lowRef);
    }
    if (item?.buyPrice?.price) {
      recyclePriceRef.value = (
        Number(item.buyPrice.price) + Number(adjustPriceRef.value)
      ).toFixed(2);
    }
  };

  watch(
    [realGoldprice, realGoldRecyclePrice, goldAdjustPrice],
    ([newSell, newRecycle, newAdjust]) => {
      const kSell = (Number(newSell) * 0.75).toFixed(2);
      realKGoldprice.value = kSell;
      realKGoldRecyclePrice.value = (Number(newRecycle) * 0.75).toFixed(2);
      KGoldAdjustPrice.value = (Number(newAdjust) * 0.75).toFixed(2);
      currentKGoldPrice.value = kSell;
      updateHighLowPrices(kSell, kGoldTodayHigh, kGoldTodayLow);
    },
    { immediate: true }
  );

  // WebSocket单例集成
  const ws = initWSSingleton();

  // 当前页面的价格更新回调（接收单例分发的数据）
  const handlePriceUpdate = (priceData) => {
    const { itemAu, itemAu9999, itemPt, itemAg } = priceData;

    // 根据realCode筛选需要更新的金属类型
    switch (realCode) {
      case "RTJ_Au":
        updatePrice(
          itemAu,
          realGoldprice,
          realGoldRecyclePrice,
          goldAdjustPrice,
          goldTodayHigh,
          goldTodayLow
        );
        currentGoldPrice.value = realGoldprice.value;
        break;
      case "AU9999":
        updatePrice(
          itemAu9999,
          realAu9999price,
          realAu9999RecyclePrice,
          Au9999AdjustPrice,
          au9999TodayHigh,
          au9999TodayLow
        );
        currentAu9999Price.value = realAu9999price.value;
        break;
      case "RTJ_Pt":
        updatePrice(
          itemPt,
          realPtprice,
          realPtRecyclePrice,
          PtAdjustPrice,
          ptTodayHigh,
          ptTodayLow
        );
        currentPtPrice.value = realPtprice.value;
        break;
      case "RTJ_Ag":
        updatePrice(
          itemAg,
          realAgprice,
          realAgRecyclePrice,
          AgAdjustPrice,
          agTodayHigh,
          agTodayLow
        );
        currentAgPrice.value = realAgprice.value;
        break;
      case "RTJ_KGold":
        break; // K金依赖基础黄金，无需额外处理
      case "All":
        updatePrice(
          itemAu,
          realGoldprice,
          realGoldRecyclePrice,
          goldAdjustPrice,
          goldTodayHigh,
          goldTodayLow
        );
        updatePrice(
          itemAu9999,
          realAu9999price,
          realAu9999RecyclePrice,
          Au9999AdjustPrice,
          au9999TodayHigh,
          au9999TodayLow
        );
        updatePrice(
          itemPt,
          realPtprice,
          realPtRecyclePrice,
          PtAdjustPrice,
          ptTodayHigh,
          ptTodayLow
        );
        updatePrice(
          itemAg,
          realAgprice,
          realAgRecyclePrice,
          AgAdjustPrice,
          agTodayHigh,
          agTodayLow
        );
        currentGoldPrice.value = realGoldprice.value;
        currentAu9999Price.value = realAu9999price.value;
        currentPtPrice.value = realPtprice.value;
        currentAgPrice.value = realAgprice.value;
        break;
    }
  };

  onShow(() => {
    connectCount++;
    if (connectCount === 1 && !isConnected) {
      ws.connect();
    }
    initPriceData();
  });

  onHide(() => {
    connectCount = Math.max(connectCount - 1, 0);
    if (connectCount === 0 && isConnected) {
      ws.disconnect();
    }
  });

  onUnload(() => {
    // 页面卸载时移除回调，避免内存泄漏
    dataCallbacks.delete(handlePriceUpdate);
    connectCount = Math.max(connectCount - 1, 0);
    if (connectCount === 0 && isConnected) {
      ws.disconnect();
    }
  });

  // 注册当前页面的价格更新回调
  dataCallbacks.add(handlePriceUpdate);

  // 主动获取金属价格（支持缓存）
  async function fetchGoldPrice(code = "RTJ_Au", tradeType = 3) {
    const cacheKey = `${code}_${tradeType}`;
    const now = Date.now();

    // 优先使用缓存（30秒内有效）
    const cached = fetchCache.get(cacheKey);
    if (cached && now - cached.lastFetchTime < CACHE_DURATION) {
      handleFetchData(cached.data, code, tradeType);
      return cached.data;
    }

    // 缓存失效，发起接口请求
    const params = { tradeType };
    if (code === "AU9999" || code === "RTJ_Pt" || code === "RTJ_Ag") {
      params.code = code;
    }

    try {
      const { data } = await getCurrentPrice(params);
      // 缓存请求结果
      fetchCache.set(cacheKey, { lastFetchTime: now, data });
      // 处理并更新价格
      handleFetchData(data, code, tradeType);
      return data;
    } catch (error) {
      console.error(`获取${code}价格失败：`, error);
      throw error;
    }
  }

  // 根据realCode初始化对应金属价格
  const initPriceData = () => {
    const tasks = [];
    if (realCode === "All" || realCode === "RTJ_Au")
      tasks.push(fetchGoldPrice("RTJ_Au"));
    if (realCode === "All" || realCode === "AU9999")
      tasks.push(fetchGoldPrice("AU9999"));
    if (realCode === "All" || realCode === "RTJ_Pt")
      tasks.push(fetchGoldPrice("RTJ_Pt"));
    if (realCode === "All" || realCode === "RTJ_Ag")
      tasks.push(fetchGoldPrice("RTJ_Ag"));
    Promise.all(tasks).catch((err) => console.error("初始化价格失败：", err));
  };

  // 处理接口返回的价格数据
  const handleFetchData = (data, code, tradeType) => {
    let sellRef, recycleRef, adjustRef, highRef, lowRef;

    // 匹配对应金属的响应式变量
    switch (code) {
      case "AU9999":
        [sellRef, recycleRef, adjustRef, highRef, lowRef] = [
          realAu9999price,
          realAu9999RecyclePrice,
          Au9999AdjustPrice,
          au9999TodayHigh,
          au9999TodayLow,
        ];
        break;
      case "RTJ_Pt":
        [sellRef, recycleRef, adjustRef, highRef, lowRef] = [
          realPtprice,
          realPtRecyclePrice,
          PtAdjustPrice,
          ptTodayHigh,
          ptTodayLow,
        ];
        break;
      case "RTJ_Ag":
        [sellRef, recycleRef, adjustRef, highRef, lowRef] = [
          realAgprice,
          realAgRecyclePrice,
          AgAdjustPrice,
          agTodayHigh,
          agTodayLow,
        ];
        break;
      default: // RTJ_Au（基础黄金）
        [sellRef, recycleRef, adjustRef, highRef, lowRef] = [
          realGoldprice,
          realGoldRecyclePrice,
          goldAdjustPrice,
          goldTodayHigh,
          goldTodayLow,
        ];
        break;
    }

    // 计算最终价格（调整价+基础价）
    const adjustPrice = tradeType === 3 ? 0 : data.adjustPrice;
    adjustRef.value = adjustPrice;
    const sellPrice = (Number(adjustPrice) + Number(data.sellPrice)).toFixed(2);
    sellRef.value = sellPrice;
    recycleRef.value = (
      Number(adjustPrice) + Number(data.buyPrice || 0)
    ).toFixed(2);
    updateHighLowPrices(sellPrice, highRef, lowRef);

    // 更新当前价快捷访问变量
    if (code === "RTJ_Au") currentGoldPrice.value = sellPrice;
    if (code === "AU9999") currentAu9999Price.value = sellPrice;
    if (code === "RTJ_Pt") currentPtPrice.value = sellPrice;
    if (code === "RTJ_Ag") currentAgPrice.value = sellPrice;
  };

  return {
    // 基础黄金相关
    realGoldprice,
    realGoldRecyclePrice,
    goldAdjustPrice,
    goldTodayHigh,
    goldTodayLow,

    // 黄金9999相关
    realAu9999price,
    realAu9999RecyclePrice,
    Au9999AdjustPrice,
    currentAu9999Price,
    au9999TodayHigh,
    au9999TodayLow,

    // 铂金相关
    realPtprice,
    realPtRecyclePrice,
    PtAdjustPrice,
    ptTodayHigh,
    ptTodayLow,

    // 白银相关
    realAgprice,
    realAgRecyclePrice,
    AgAdjustPrice,
    agTodayHigh,
    agTodayLow,

    // K金相关
    realKGoldprice,
    realKGoldRecyclePrice,
    KGoldAdjustPrice,
    kGoldTodayHigh,
    kGoldTodayLow,

    // 当前价快捷访问
    currentGoldPrice,
    currentPtPrice,
    currentAgPrice,
    currentKGoldPrice,

    // 主动获取价格方法
    fetchGoldPrice,
  };
}
