/* eslint-disable */
/**
 * Composable for handling window message communication
 * Provides a consistent interface for cross-window/iframe communication
 */

// Define common message types as constants
export const WindowMessageTypes = {
  LOGIN_COMPLETE: 'login-complete',
  AFTER_LOGIN: 'after-login',
  OAUTH_PROVIDER_CONNECTED: 'oauth-provider-connected'
}

export const useWindowMessage = (messageType = null) => {
  const listeners = ref(new Map())
  
  /**
   * Derives an acknowledgment message name from the original message name
   * @param {string} originalMessage - The original message name
   * @returns {string} - The derived acknowledgment message name
   */
  const deriveAcknowledgmentName = (originalMessage) => {
    return `${originalMessage}-acknowledged`
  }
  
  /**
   * Add a listener for a specific message type
   * 
   * @param {string} eventType - The type of message to listen for (defaults to constructor value)
   * @param {Function} callback - The callback function to call when the message is received
   * @param {Object} options - Options for the listener
   * @param {boolean} options.useMessageChannel - Whether to expect and use MessageChannel ports in the event
   * @param {boolean} options.acknowledge - Whether to automatically acknowledge the message
   */
  const listen = (callback, options = {}, eventType = null) => {
    const targetEventType = eventType || messageType
    if (!targetEventType) {
      console.error('No message type provided to listen for')
      return
    }
    
    const { 
      useMessageChannel = true, 
      acknowledge = true 
    } = options
    
    const acknowledgmentName = deriveAcknowledgmentName(targetEventType)
    
    const handler = (event) => {
      // For simple messages
      if (!useMessageChannel && event.data === targetEventType) {
        callback(event)
        return
      }
      
      // For MessageChannel messages
      if (useMessageChannel && event.data === targetEventType && event.ports && event.ports.length > 0) {
        // Send acknowledgement if requested
        if (acknowledge && event.ports[0]) {
          event.ports[0].postMessage(acknowledgmentName)
        }
        
        // Call the callback with the event
        callback(event)
        return
      }
    }
    
    // Add the listener to the window
    window.addEventListener('message', handler)
    
    // Store the handler for cleanup
    listeners.value.set(targetEventType, handler)
    
    // Return a function to remove the listener
    return () => stopListening(targetEventType)
  }
  
  /**
   * Remove a listener for a specific message type
   * 
   * @param {string} eventType - The type of message to stop listening for
   */
  const stopListening = (eventType = null) => {
    const targetEventType = eventType || messageType
    if (!targetEventType) {
      console.error('No message type provided to stop listening for')
      return
    }
    
    const handler = listeners.value.get(targetEventType)
    if (handler) {
      window.removeEventListener('message', handler)
      listeners.value.delete(targetEventType)
    }
  }
  
  /**
   * Send a message to another window
   * 
   * @param {Window} targetWindow - The window to send the message to
   * @param {Object} options - Options for sending the message
   * @param {string} options.eventType - The type of message to send (defaults to constructor value)
   * @param {string} options.targetOrigin - The origin to send the message to, defaults to '*'
   * @param {boolean} options.useMessageChannel - Whether to use MessageChannel for communication
   * @param {number} options.timeout - Timeout in ms for the acknowledgment, defaults to 500ms
   * @param {boolean} options.waitForAcknowledgment - Whether to wait for acknowledgment
   * @returns {Promise} - Resolves when acknowledged or after timeout
   */
  const send = (targetWindow, options = {}) => {
    const { 
      eventType = null,
      targetOrigin = '*', 
      useMessageChannel = true,
      timeout = 500,
      waitForAcknowledgment = true
    } = options
    
    const targetEventType = eventType || messageType
    if (!targetEventType) {
      console.error('No message type provided to send')
      return Promise.reject(new Error('No message type provided'))
    }
    
    const acknowledgmentName = deriveAcknowledgmentName(targetEventType)
    
    if (!useMessageChannel) {
      // Simple message without MessageChannel
      targetWindow.postMessage(targetEventType, targetOrigin)
      return Promise.resolve()
    } else {
      // Using MessageChannel for two-way communication
      return new Promise((resolve) => {
        // Create a message channel for two-way communication
        const channel = new MessageChannel()
        
        // If we expect an acknowledgment, listen for it
        if (waitForAcknowledgment) {
          channel.port1.onmessage = (event) => {
            if (event.data === acknowledgmentName) {
              resolve(true) // Acknowledged
            }
          }
        }
        
        // Send the message with the port
        targetWindow.postMessage(targetEventType, targetOrigin, [channel.port2])
        
        // Set a timeout as fallback
        if (waitForAcknowledgment) {
          setTimeout(() => resolve(false), timeout)
        } else {
          resolve(true)
        }
      })
    }
  }
  
  /**
   * Cleanup all listeners
   * Call this explicitly if needed, though it's automatically called on unmount
   */
  const cleanup = () => {
    listeners.value.forEach((handler, type) => {
      window.removeEventListener('message', handler)
    })
    listeners.value.clear()
  }
  
  // Auto-cleanup when the component is unmounted
  onUnmounted(() => {
    cleanup()
  })
  
  // If messageType was provided on creation, set up a default listener
  const setupDefaultListener = (callback, options = {}) => {
    if (messageType && callback) {
      return listen(callback, options)
    }
  }
  
  return {
    listen,
    stopListening,
    send,
    cleanup,
    setupDefaultListener
  }
} 