import { useEffect, useRef, useState } from 'react'
import { Settings2, Plus, X, Columns2, Grid2x2, SquareSlash } from 'lucide-react'
import { api, type Integration } from '../lib/api'
import { useTerminalSessions } from '../lib/TerminalSessionContext'
import { TERM_THEMES } from '../lib/terminalPrefs'

const GOLD = '#C8A434'
const TEXT_SECONDARY = '#7A7D85'

const FONT_SIZES = [11, 12, 13, 14, 15, 16]
// "Symbols Nerd Font Mono" is appended as a glyph-only fallback to every option, so
// distro icons / git branch / etc. from prompts like Starship render instead of
// showing as boxes — it has no letterforms of its own, so it never overrides the
// chosen base font for normal text.
const NERD_FALLBACK = '"Symbols Nerd Font Mono"'
const FONT_FAMILIES = [
  { name: 'Monospace', value: `ui-monospace, SFMono-Regular, Menlo, monospace, ${NERD_FALLBACK}` },
  { name: 'Fira Code', value: `"Fira Code", ui-monospace, monospace, ${NERD_FALLBACK}` },
  { name: 'JetBrains Mono', value: `"JetBrains Mono", ui-monospace, monospace, ${NERD_FALLBACK}` },
]

export default function Terminal() {
  const [hosts, setHosts] = useState<Integration[]>([])
  const [showPrefs, setShowPrefs] = useState(false)

  const {
    tabs,
    activeTabId,
    activePaneId,
    prefs,
    setActiveTabId,
    setActivePaneId,
    setPrefs,
    addTab,
    closeTab,
    setPaneCount,
    setPaneHost,
  } = useTerminalSessions()

  useEffect(() => {
    api.listIntegrations().then(({ integrations }) => {
      setHosts(integrations.filter((i) => i.type === 'ssh'))
    })
  }, [])

  const activeTab = tabs.find((t) => t.id === activeTabId) ?? tabs[0]

  const paneGridClass =
    activeTab.panes.length === 1
      ? 'grid-cols-1 grid-rows-1'
      : activeTab.panes.length === 2
        ? 'grid-cols-2 grid-rows-1'
        : 'grid-cols-2 grid-rows-2'

  const activePaneHostId = activeTab.panes.find((p) => p.id === activePaneId)?.hostId ?? null

  return (
    <div className="flex h-full gap-4">
      <div className="w-56 shrink-0 overflow-y-auto rounded-lg border border-white/10 bg-white/5 p-3">
        <p className="mb-2 text-xs font-medium uppercase tracking-wide" style={{ color: TEXT_SECONDARY }}>
          SSH Hosts
        </p>
        {hosts.length === 0 && (
          <p className="text-xs" style={{ color: TEXT_SECONDARY }}>
            No SSH integrations configured. Add one in Settings → Integrations.
          </p>
        )}
        <div className="flex flex-col gap-1">
          {hosts.map((h) => (
            <button
              key={h.id}
              onClick={() => activePaneId !== null && setPaneHost(activePaneId, h.id)}
              className="rounded-md px-2 py-1.5 text-left text-sm transition-colors"
              style={{
                background: activePaneHostId === h.id ? 'rgba(200,164,52,0.15)' : 'transparent',
                color: activePaneHostId === h.id ? GOLD : '#E8E6E0',
              }}
            >
              {h.name}
            </button>
          ))}
        </div>
        <p className="mt-3 text-[11px]" style={{ color: TEXT_SECONDARY }}>
          Click a pane, then a host to connect it. Sessions stay connected when
          you switch pages — close a tab or pane to disconnect.
        </p>
      </div>

      <div className="flex min-w-0 flex-1 flex-col gap-2">
        <div className="flex items-center gap-2">
          <div className="flex flex-1 items-center gap-1 overflow-x-auto">
            {tabs.map((tab) => (
              <div
                key={tab.id}
                onClick={() => setActiveTabId(tab.id)}
                className="flex shrink-0 cursor-pointer items-center gap-2 rounded-md px-3 py-1.5 text-xs"
                style={{
                  background: tab.id === activeTabId ? 'rgba(200,164,52,0.15)' : 'rgba(255,255,255,0.04)',
                  color: tab.id === activeTabId ? GOLD : '#E8E6E0',
                }}
              >
                {tab.name}
                <X
                  size={12}
                  onClick={(e) => {
                    e.stopPropagation()
                    closeTab(tab.id)
                  }}
                />
              </div>
            ))}
            <button onClick={addTab} className="shrink-0 rounded-md p-1.5" style={{ color: TEXT_SECONDARY }} title="New tab">
              <Plus size={14} />
            </button>
          </div>

          <div className="flex items-center gap-1">
            <button onClick={() => setPaneCount(1)} className="rounded-md p-1.5" style={{ color: activeTab.panes.length === 1 ? GOLD : TEXT_SECONDARY }} title="Single pane">
              <SquareSlash size={14} />
            </button>
            <button onClick={() => setPaneCount(2)} className="rounded-md p-1.5" style={{ color: activeTab.panes.length === 2 ? GOLD : TEXT_SECONDARY }} title="Split 2">
              <Columns2 size={14} />
            </button>
            <button onClick={() => setPaneCount(4)} className="rounded-md p-1.5" style={{ color: activeTab.panes.length === 4 ? GOLD : TEXT_SECONDARY }} title="Split 4">
              <Grid2x2 size={14} />
            </button>
            <button onClick={() => setShowPrefs((v) => !v)} className="rounded-md p-1.5" style={{ color: showPrefs ? GOLD : TEXT_SECONDARY }} title="Terminal preferences">
              <Settings2 size={14} />
            </button>
          </div>
        </div>

        {showPrefs && (
          <div className="flex items-center gap-4 rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-xs" style={{ color: '#E8E6E0' }}>
            <label className="flex items-center gap-2">
              Theme
              <select
                value={prefs.themeName}
                onChange={(e) => setPrefs((p) => ({ ...p, themeName: e.target.value }))}
                className="rounded-md border border-white/10 bg-transparent px-2 py-1"
              >
                {TERM_THEMES.map((t) => (
                  <option key={t.name} value={t.name}>
                    {t.name}
                  </option>
                ))}
              </select>
            </label>
            <label className="flex items-center gap-2">
              Font Size
              <select
                value={prefs.fontSize}
                onChange={(e) => setPrefs((p) => ({ ...p, fontSize: Number(e.target.value) }))}
                className="rounded-md border border-white/10 bg-transparent px-2 py-1"
              >
                {FONT_SIZES.map((s) => (
                  <option key={s} value={s}>
                    {s}px
                  </option>
                ))}
              </select>
            </label>
            <label className="flex items-center gap-2">
              Font
              <select
                value={prefs.fontFamily}
                onChange={(e) => setPrefs((p) => ({ ...p, fontFamily: e.target.value }))}
                className="rounded-md border border-white/10 bg-transparent px-2 py-1"
              >
                {FONT_FAMILIES.map((f) => (
                  <option key={f.name} value={f.value}>
                    {f.name}
                  </option>
                ))}
              </select>
            </label>
          </div>
        )}

        <div className={`grid min-h-0 flex-1 gap-2 ${paneGridClass}`}>
          {activeTab.panes.map((pane) => (
            <TerminalPane
              key={pane.id}
              paneId={pane.id}
              hostId={pane.hostId}
              hosts={hosts}
              active={pane.id === activePaneId}
              onFocus={() => setActivePaneId(pane.id)}
            />
          ))}
        </div>
      </div>
    </div>
  )
}

function TerminalPane({
  paneId,
  hostId,
  hosts,
  active,
  onFocus,
}: {
  paneId: number
  hostId: number | null
  hosts: Integration[]
  active: boolean
  onFocus: () => void
}) {
  const { attachPane, getPaneInfo, reconnectTmux, version } = useTerminalSessions()
  const cellRef = useRef<HTMLDivElement>(null)

  // Mount the persistent xterm DOM node owned by the provider into this cell;
  // on unmount (route change or layout change) the wrapper is moved back to the
  // hidden root rather than disposed, so the session keeps running.
  useEffect(() => {
    if (!cellRef.current) return
    const detach = attachPane(paneId, cellRef.current)
    return detach
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [paneId])

  // `version` is read so the header re-renders when live pane state changes.
  void version
  const info = getPaneInfo(paneId)
  const host = hosts.find((h) => h.id === hostId)

  return (
    <div
      onClick={onFocus}
      className="flex min-w-0 min-h-0 flex-col rounded-lg p-2"
      style={{
        backgroundColor: '#15161A',
        border: active ? `1px solid ${GOLD}` : '1px solid rgba(255,255,255,0.1)',
      }}
    >
      <div className="mb-2 flex items-center gap-2 px-1 text-xs" style={{ color: TEXT_SECONDARY }}>
        <span className="inline-block h-2 w-2 rounded-full" style={{ background: info.connected ? '#2ECC71' : '#7A7D85' }} />
        {host ? (info.connected ? `Connected — ${host.name}` : `Disconnected — ${host.name}`) : 'Select a host to connect'}
        {host && (
          <select
            value={info.selectedTmux}
            onClick={(e) => e.stopPropagation()}
            onChange={(e) => reconnectTmux(paneId, e.target.value)}
            className="ml-auto rounded-md border border-white/10 bg-transparent px-1.5 py-0.5"
            style={{ color: TEXT_SECONDARY, fontSize: '11px' }}
            title="Attach to a tmux session on this host"
          >
            <option value="">Plain shell</option>
            <option value="__new__">New tmux session</option>
            {info.tmuxSessions.map((s) => (
              <option key={s} value={s}>
                tmux: {s}
              </option>
            ))}
          </select>
        )}
      </div>
      <div ref={cellRef} className="min-h-0 flex-1" />
    </div>
  )
}
