/**
 * public/cell-monitor.ts — read-only "monitor" view of a session in a grid cell.
 *
 * A monitored quadrant renders the session's current screen via periodic
 * GET /live-sessions/:id/preview snapshots (RingBuffer.tail on the server) into a
 * read-only xterm. It NEVER attaches a WebSocket and NEVER sends a resize, so —
 * unlike a live interactive quadrant (latest-writer-wins) — it does not drive the
 * shared PTY size. That lets you WATCH a session in a small quadrant without
 * shrinking it for another device that is using it full-screen (the cross-device
 * shrink the split-grid design flagged).
 *
 * The snapshot is scaled with a CSS transform to fit the cell, like the launcher
 * thumbnails, so the real screen stays readable regardless of the cell size.
 */

import { Terminal } from '@xterm/xterm'
import { fetchPreview, PREVIEW_CLEAR, PREVIEW_THEME } from './preview-grid.js'

/** How often a monitored quadrant re-fetches the session's screen snapshot. */
const MONITOR_POLL_MS = 2000

export interface CellMonitor {
  dispose(): void
}

/** Scale the rendered term to fit `host`, top-left anchored (no upscaling). */
function fitMonitor(host: HTMLElement, screen: HTMLElement): void {
  const w = screen.offsetWidth
  const h = screen.offsetHeight
  if (w === 0 || h === 0 || host.clientWidth === 0 || host.clientHeight === 0) return
  const scale = Math.min(1, host.clientWidth / w, host.clientHeight / h)
  screen.style.transformOrigin = 'top left'
  screen.style.transform = `scale(${scale})`
}

/**
 * Mount a polling read-only preview of `sessionId` into `host`. Returns a handle
 * whose dispose() stops the poll and tears down the terminal. Best-effort: a
 * failed fetch just skips that tick (no throw).
 */
export function mountCellMonitor(host: HTMLElement, sessionId: string): CellMonitor {
  const term = new Terminal({
    disableStdin: true,
    cursorBlink: false,
    fontFamily: 'Menlo, Consolas, monospace',
    fontSize: 12,
    scrollback: 0,
    theme: PREVIEW_THEME,
  })
  term.open(host)

  let disposed = false
  let timer: ReturnType<typeof setTimeout> | null = null

  const poll = async (): Promise<void> => {
    const p = await fetchPreview(sessionId)
    if (disposed) return
    if (p) {
      const cols = Math.max(2, p.cols)
      const rows = Math.max(2, p.rows)
      if (term.cols !== cols || term.rows !== rows) term.resize(cols, rows)
      term.reset()
      term.write(PREVIEW_CLEAR + p.data, () => {
        const screen = host.firstElementChild
        if (screen instanceof HTMLElement) fitMonitor(host, screen)
      })
    }
    if (!disposed) timer = setTimeout(() => void poll(), MONITOR_POLL_MS)
  }
  void poll()

  return {
    dispose(): void {
      disposed = true
      if (timer !== null) {
        clearTimeout(timer)
        timer = null
      }
      term.dispose()
    },
  }
}
