/**
 * @file 模块间通信工具
 * @description 封装 Content Script、Background、Popup 之间的通信
 */

/**
 * 生成唯一请求ID
 * @returns {string} UUID
 */
function generateUUID() {
  return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}

/**
 * 消息客户端 - 用于 Content Script 和 Popup
 */
class MessageClient {
  /**
   * 向 Background 发送消息并等待响应
   * @param {string} type - 消息类型
   * @param {Object} payload - 消息数据
   * @param {number} timeout - 超时时间(ms)
   * @returns {Promise<any>} 响应数据
   */
  async sendToBackground(type, payload = {}, timeout = 5000) {
    const requestId = generateUUID();
    const message = {
      type,
      payload,
      meta: {
        timestamp: Date.now(),
        requestId
      }
    };

    return new Promise((resolve, reject) => {
      const timer = setTimeout(() => {
        reject(new Error(`Request timeout: ${type}`));
      }, timeout);

      chrome.runtime.sendMessage(message, (response) => {
        clearTimeout(timer);
        
        if (chrome.runtime.lastError) {
          reject(new Error(chrome.runtime.lastError.message));
          return;
        }
        
        if (response?.error) {
          reject(new Error(response.error.message));
        } else {
          resolve(response?.payload);
        }
      });
    });
  }

  /**
   * Ping 测试
   * @returns {Promise<boolean>}
   */
  async ping() {
    try {
      const result = await this.sendToBackground('PING');
      return result?.pong === true;
    } catch (error) {
      console.error('[Messaging] Ping failed:', error);
      return false;
    }
  }
}

/**
 * Background 消息处理器 - 用于 Service Worker
 */
class BackgroundHandler {
  constructor() {
    this.handlers = new Map();
    this.init();
  }

  /**
   * 注册消息处理器
   * @param {string} type - 消息类型
   * @param {Function} handler - 处理函数 (payload, sender) => Promise<any>
   */
  register(type, handler) {
    this.handlers.set(type, handler);
  }

  /**
   * 初始化监听
   */
  init() {
    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      this.handleMessage(message, sender, sendResponse);
      return true; // 保持消息通道开放
    });
  }

  /**
   * 处理消息
   */
  handleMessage(message, sender, sendResponse) {
    const { type, payload, meta } = message;
    const requestId = meta?.requestId;

    console.log('[Background] Received:', type, payload);

    // 内置 PING 处理
    if (type === 'PING') {
      sendResponse({
        type: 'PONG',
        payload: { pong: true },
        meta: { requestId }
      });
      return;
    }

    const handler = this.handlers.get(type);
    if (!handler) {
      sendResponse({
        type: `${type}_RESPONSE`,
        error: { message: `No handler for type: ${type}` },
        meta: { requestId }
      });
      return;
    }

    // 异步处理
    handler(payload, sender)
      .then(result => {
        sendResponse({
          type: `${type}_RESPONSE`,
          payload: result,
          meta: { requestId }
        });
      })
      .catch(error => {
        console.error('[Background] Handler error:', error);
        sendResponse({
          type: `${type}_RESPONSE`,
          error: { message: error.message },
          meta: { requestId }
        });
      });
  }

  /**
   * 向指定 Tab 的 Content Script 发送消息
   * @param {number} tabId - Tab ID
   * @param {string} type - 消息类型
   * @param {Object} payload - 消息数据
   */
  async sendToContent(tabId, type, payload = {}) {
    const requestId = generateUUID();
    const message = {
      type,
      payload,
      meta: {
        timestamp: Date.now(),
        requestId
      }
    };

    return new Promise((resolve, reject) => {
      const timer = setTimeout(() => {
        reject(new Error(`Send to content timeout: ${type}`));
      }, 5000);

      chrome.tabs.sendMessage(tabId, message, (response) => {
        clearTimeout(timer);
        if (chrome.runtime.lastError) {
          reject(new Error(chrome.runtime.lastError.message));
        } else if (response?.error) {
          reject(new Error(response.error.message));
        } else {
          resolve(response?.payload);
        }
      });
    });
  }

  /**
   * 向所有 Tab 广播消息
   * @param {string} type - 消息类型
   * @param {Object} payload - 消息数据
   */
  async broadcastToAllContent(type, payload = {}) {
    const tabs = await chrome.tabs.query({});
    const results = [];

    for (const tab of tabs) {
      if (tab.id) {
        try {
          const result = await this.sendToContent(tab.id, type, payload);
          results.push({ tabId: tab.id, success: true, result });
        } catch (error) {
          results.push({ tabId: tab.id, success: false, error: error.message });
        }
      }
    }

    return results;
  }
}

// 导出单例
export const messaging = new MessageClient();
export const backgroundHandler = new BackgroundHandler();

// 兼容性导出
export const sendToBackground = (type, payload, timeout) =>
  messaging.sendToBackground(type, payload, timeout);

export const sendToContent = (tabId, type, payload) =>
  backgroundHandler.sendToContent(tabId, type, payload);

export const ping = () => messaging.ping();
