import { useEffect, useRef, useState } from 'react'
import Guacamole from 'guacamole-common-js'
import { api, getToken, type Integration } from '../lib/api'

const TEXT_SECONDARY = '#7A7D85'

type SessionStatus = 'connecting' | 'connected' | 'error'

interface Session {
  sessionId: string
  hostId: number
  name: string
  status: SessionStatus
  errorMessage: string
}

interface SessionHandle {
  client: any
  container: HTMLDivElement
}

export default function RemoteDesktop() {
  const [hosts, setHosts] = useState<Integration[]>([])
  const [sessions, setSessions] = useState<Session[]>([])
  const [activeSessionId, setActiveSessionId] = useState<string | null>(null)
  const displayHostRef = useRef<HTMLDivElement>(null)
  const handlesRef = useRef<Map<string, SessionHandle>>(new Map())

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

  useEffect(() => {
    return () => {
      handlesRef.current.forEach(({ client }) => client.disconnect())
    }
  }, [])

  function patchSession(sessionId: string, patch: Partial<Session>) {
    setSessions((prev) => prev.map((s) => (s.sessionId === sessionId ? { ...s, ...patch } : s)))
  }

  function openSession(host: Integration) {
    const sessionId = crypto.randomUUID()
    const session: Session = { sessionId, hostId: host.id, name: host.name, status: 'connecting', errorMessage: '' }
    setSessions((prev) => [...prev, session])
    setActiveSessionId(sessionId)

    const container = document.createElement('div')
    container.className = 'h-full w-full overflow-auto'

    const token = getToken()
    const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'
    // Guacamole.WebSocketTunnel appends its own "?<data>" query string on connect(),
    // so the tunnel URL itself must not already contain one.
    const tunnel = new Guacamole.WebSocketTunnel(`${proto}://${window.location.host}/api/guacamole`)
    const client = new Guacamole.Client(tunnel)
    handlesRef.current.set(sessionId, { client, container })

    client.onerror = (err: { message?: string }) => {
      patchSession(sessionId, { status: 'error', errorMessage: err?.message ?? 'Connection failed' })
    }
    client.onstatechange = (state: number) => {
      if (state === 3) patchSession(sessionId, { status: 'connected' })
    }

    container.appendChild(client.getDisplay().getElement())
    client.connect(`token=${encodeURIComponent(token ?? '')}&integrationId=${host.id}`)
  }

  function closeSession(sessionId: string) {
    const handle = handlesRef.current.get(sessionId)
    handle?.client.disconnect()
    handle?.container.remove()
    handlesRef.current.delete(sessionId)
    setSessions((prev) => {
      const next = prev.filter((s) => s.sessionId !== sessionId)
      if (activeSessionId === sessionId) {
        setActiveSessionId(next.length > 0 ? next[next.length - 1].sessionId : null)
      }
      return next
    })
  }

  // Show only the active session's display element; keep the rest mounted off-DOM so
  // background sessions stay connected while their tab isn't focused.
  useEffect(() => {
    const host = displayHostRef.current
    if (!host) return
    host.innerHTML = ''
    const active = activeSessionId ? handlesRef.current.get(activeSessionId) : null
    if (active) host.appendChild(active.container)
  }, [activeSessionId])

  const activeSession = sessions.find((s) => s.sessionId === activeSessionId)

  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 }}>
          Remote Desktops
        </p>
        {hosts.length === 0 && (
          <p className="text-xs" style={{ color: TEXT_SECONDARY }}>
            No remote desktop integrations configured. Add one in Settings → Integrations.
          </p>
        )}
        {hosts.map((h) => (
          <button
            key={h.id}
            onClick={() => openSession(h)}
            className="mb-1 w-full rounded-md px-2 py-1.5 text-left text-sm transition hover:bg-white/10"
            style={{ color: '#E8E6E0' }}
          >
            {h.name}
          </button>
        ))}
      </div>

      <div className="flex flex-1 flex-col overflow-hidden rounded-lg border border-white/10 bg-black">
        <div className="flex items-center gap-1 overflow-x-auto border-b border-white/10 px-2 py-1.5">
          {sessions.length === 0 && (
            <p className="px-1 text-sm" style={{ color: TEXT_SECONDARY }}>
              Select a remote desktop to connect
            </p>
          )}
          {sessions.map((s) => (
            <div
              key={s.sessionId}
              onClick={() => setActiveSessionId(s.sessionId)}
              className="flex shrink-0 cursor-pointer items-center gap-2 rounded-md px-2 py-1 text-sm"
              style={{
                background: activeSessionId === s.sessionId ? 'rgba(200,164,52,0.15)' : 'transparent',
                color: activeSessionId === s.sessionId ? '#C8A434' : '#E8E6E0',
              }}
            >
              <span
                className="h-1.5 w-1.5 rounded-full"
                style={{
                  background: s.status === 'connected' ? '#4ADE80' : s.status === 'error' ? '#F87171' : '#FBBF24',
                }}
              />
              {s.name}
              <button
                onClick={(e) => {
                  e.stopPropagation()
                  closeSession(s.sessionId)
                }}
                className="ml-1 rounded px-1 text-xs hover:bg-white/10"
                style={{ color: TEXT_SECONDARY }}
                title="Disconnect"
              >
                ✕
              </button>
            </div>
          ))}
        </div>

        {activeSession && (
          <div className="flex items-center justify-between border-b border-white/10 px-3 py-2">
            <p className="text-sm" style={{ color: TEXT_SECONDARY }}>
              {activeSession.name}
            </p>
            <div className="flex items-center gap-3">
              <p className="text-xs" style={{ color: TEXT_SECONDARY }}>
                {activeSession.status === 'connecting' && 'Connecting…'}
                {activeSession.status === 'connected' && 'Connected'}
                {activeSession.status === 'error' && `Error: ${activeSession.errorMessage}`}
              </p>
              <button
                onClick={() => closeSession(activeSession.sessionId)}
                className="rounded-md border border-white/10 px-2 py-1 text-xs transition hover:bg-white/10"
                style={{ color: '#E8E6E0' }}
              >
                Disconnect
              </button>
            </div>
          </div>
        )}

        <div ref={displayHostRef} className="flex-1 overflow-auto" />
      </div>
    </div>
  )
}
