/**
 * TerminalPanel — xterm.js front-end over the /api/projects/{id}/terminal
 * WebSocket PTY bridge.
 *
 * Lifecycle:
 *   - On mount + project change: opens a WS, attaches it to a fresh xterm.
 *   - Resize: ResizeObserver -> fit addon -> send {"resize":[c,r]} control frame.
 *   - On unmount: closes the WS (server reaps the PTY child).
 */

import { useEffect, useRef } from 'react'
import useAppStore from '../store/appStore'
import { Terminal } from '@xterm/xterm'
import { FitAddon } from '@xterm/addon-fit'
import '@xterm/xterm/css/xterm.css'

export default function TerminalPanel() {
  const projectId = useAppStore((s) => s.project.id)
  const theme     = useAppStore((s) => s.theme)
  const hostRef   = useRef(null)
  const termRef   = useRef(null)
  const wsRef     = useRef(null)
  const fitRef    = useRef(null)

  useEffect(() => {
    if (!projectId || !hostRef.current) return

    // Colour scheme picked to match the studio surfaces (CSS vars aren't
    // accessible from xterm directly so we hardcode a small palette).
    const dark = theme !== 'light'
    const term = new Terminal({
      fontFamily:    'ui-monospace, "JetBrains Mono", Menlo, monospace',
      fontSize:      12.5,
      lineHeight:    1.15,
      cursorBlink:   true,
      convertEol:    false,
      scrollback:    5000,
      allowProposedApi: true,
      theme: dark
        ? { background: '#0b1220', foreground: '#e2e8f0', cursor: '#22d3ee', selectionBackground: '#1e3a8a' }
        : { background: '#f8fafc', foreground: '#0f172a', cursor: '#0284c7', selectionBackground: '#bfdbfe' },
    })
    const fit = new FitAddon()
    term.loadAddon(fit)
    term.open(hostRef.current)
    fit.fit()
    term.focus()
    termRef.current = term
    fitRef.current  = fit

    const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
    const wsUrl = `${proto}//${window.location.host}`
                + `/api/projects/${projectId}/terminal`
                + `?cols=${term.cols}&rows=${term.rows}`
    const ws = new WebSocket(wsUrl)
    ws.binaryType = 'arraybuffer'
    wsRef.current = ws

    ws.onopen = () => {
      term.write('\x1b[2m[tesseract] terminal connected — bash/zsh at project root.\x1b[0m\r\n')
    }
    ws.onmessage = (ev) => {
      if (ev.data instanceof ArrayBuffer) {
        term.write(new Uint8Array(ev.data))
      } else if (typeof ev.data === 'string') {
        term.write(ev.data)
      }
    }
    ws.onclose = () => {
      term.write('\r\n\x1b[2m[tesseract] terminal disconnected.\x1b[0m\r\n')
    }
    ws.onerror = () => {
      term.write('\r\n\x1b[31m[tesseract] terminal error.\x1b[0m\r\n')
    }

    const onData = term.onData((data) => {
      if (ws.readyState === WebSocket.OPEN) ws.send(data)
    })

    const ro = new ResizeObserver(() => {
      try {
        fit.fit()
        if (ws.readyState === WebSocket.OPEN) {
          ws.send(JSON.stringify({ resize: [term.cols, term.rows] }))
        }
      } catch { /* ignore */ }
    })
    ro.observe(hostRef.current)

    return () => {
      ro.disconnect()
      onData.dispose()
      try { ws.close() } catch { /* ignore */ }
      term.dispose()
      termRef.current = null
      fitRef.current  = null
      wsRef.current   = null
    }
  }, [projectId, theme])

  if (!projectId) {
    return (
      <div style={{ height: '100%', display: 'grid', placeItems: 'center', color: 'var(--text-faint)', fontSize: 12 }}>
        Open a project to launch a terminal.
      </div>
    )
  }
  return (
    <div
      ref={hostRef}
      style={{
        width:      '100%',
        height:     '100%',
        background: theme === 'light' ? '#f8fafc' : '#0b1220',
        padding:    6,
        boxSizing:  'border-box',
      }}
    />
  )
}
