import { theme } from './themes'

// Iframe cache - these never get recreated once loaded
// Use a global to survive hot reloads
const iframes: Map<string, { iframe: HTMLIFrameElement; port: number; contentHeight?: number }> =
  (window as any).__toolIframes ??= new Map()

// Track current state to avoid unnecessary DOM updates
// Also stored on window to survive hot reloads
let currentTool: string | null = (window as any).__currentTool ?? null

// Get the stable container (outside Hono-managed DOM)
const getContainer = () => document.getElementById('tool-iframes')

// Listen for messages from iframes
function setupMessageListener() {
  if ((window as any).__toolIframeMessageListener) return
    ; (window as any).__toolIframeMessageListener = true

  window.addEventListener('message', (event) => {
    const { type } = event.data || {}

    if (type === 'resize-iframe') {
      const height = event.data.height
      if (!height || typeof height !== 'number') return

      // Find which iframe sent this message
      for (const [, cached] of iframes) {
        if (cached.iframe.contentWindow === event.source) {
          cached.contentHeight = height
          cached.iframe.style.height = `${height}px`
          return
        }
      }
    }
  })
}

// Initialize the container styles
export function initToolIframes() {
  const container = getContainer()
  if (!container) return

  setupMessageListener()

  // Restore iframe cache from DOM if module was hot-reloaded
  if (iframes.size === 0) {
    const existingIframes = container.querySelectorAll('iframe')
    existingIframes.forEach(iframe => {
      try {
        const url = new URL(iframe.src)
        const port = parseInt(url.port, 10)
        const toolName = iframe.dataset.toolName
        const appName = iframe.dataset.appName
        if (port && toolName) {
          const cacheKey = appName ? `${toolName}:${appName}` : toolName
          iframes.set(cacheKey, { iframe, port })
        }
      } catch {
        // Invalid URL, skip
      }
    })
  }

  container.style.cssText = `
    display: none;
    position: fixed;
    background: ${theme('colors-bg')};
    overflow: auto;
  `
}

// Build URL with params using port-based routing
function buildToolUrl(port: number, params: Record<string, string>): string {
  const base = new URL(window.location.origin)
  base.port = String(port)
  const searchParams = new URLSearchParams(params)
  const query = searchParams.toString()
  return query ? `${base.origin}?${query}` : base.origin
}

// Build cache key from tool name and params
function buildCacheKey(toolName: string, params: Record<string, string>): string {
  const parts = [toolName]
  const sortedKeys = Object.keys(params).sort()
  for (const key of sortedKeys) {
    parts.push(`${key}=${params[key]}`)
  }
  return parts.join(':')
}

// Reset a tool iframe to its home page
export function resetToolIframe(toolName: string, selectedApp: string | null) {
  const params: Record<string, string> = {}
  if (selectedApp) params.app = selectedApp
  const cacheKey = buildCacheKey(toolName, params)
  const cached = iframes.get(cacheKey)
  if (cached) {
    // For code app, include empty file param to clear its localStorage
    const urlParams = toolName === 'code' ? { ...params, file: '' } : params
    cached.iframe.src = buildToolUrl(cached.port, urlParams)
  }
}

// Update which iframe is visible based on selected tab and tool state
export function updateToolIframes(
  selectedTab: string,
  tools: Array<{ name: string; port?: number; state: string }>,
  selectedApp: string | null
) {
  const container = getContainer()
  if (!container) return

  // Find the selected tool
  const selectedTool = tools.find(t => t.name === selectedTab)
  const showIframe = selectedTool?.state === 'running' && selectedTool?.port

  if (!showIframe) {
    if (currentTool !== null) {
      container.style.display = 'none'
      currentTool = null
      ;(window as any).__currentTool = null
    }
    return
  }

  const tool = selectedTool!

  // Build params and cache key
  const params: Record<string, string> = {}
  if (selectedApp) params.app = selectedApp
  const cacheKey = buildCacheKey(tool.name, params)

  // Skip if nothing changed
  if (currentTool === cacheKey) {
    const tabContent = document.querySelector('[data-tool-target]')
    if (tabContent) {
      const rect = tabContent.getBoundingClientRect()
      container.style.top = `${rect.top}px`
      container.style.left = `${rect.left}px`
      container.style.width = `${rect.width}px`
      container.style.height = `calc(100vh - ${rect.top}px)`
    }
    return
  }

  // Position container over the tab content area
  const tabContent = document.querySelector('[data-tool-target]')
  if (!tabContent) {
    container.style.display = 'none'
    currentTool = null
    return
  }

  const rect = tabContent.getBoundingClientRect()
  container.style.cssText = `
    display: block;
    position: fixed;
    top: ${rect.top}px;
    left: ${rect.left}px;
    width: ${rect.width}px;
    height: calc(100vh - ${rect.top}px);
    background: ${theme('colors-bg')};
    z-index: 100;
    overflow: auto;
  `

  // Get or create the iframe
  let cached = iframes.get(cacheKey)

  if (!cached || cached.port !== tool.port) {
    const iframe = document.createElement('iframe')
    iframe.src = buildToolUrl(tool.port!, params)
    iframe.dataset.toolName = tool.name
    iframe.dataset.appName = selectedApp ?? ''
    iframe.style.cssText = `width: 100%; border: none;`
    cached = { iframe, port: tool.port! }
    iframes.set(cacheKey, cached)
    container.appendChild(iframe)
  }

  // Show only the selected iframe
  for (const [key, { iframe }] of iframes) {
    const shouldShow = key === cacheKey
    if (shouldShow && iframe.parentElement !== container) {
      container.appendChild(iframe)
    }
    iframe.style.display = shouldShow ? 'block' : 'none'
  }

  currentTool = cacheKey
  ;(window as any).__currentTool = cacheKey
}
