import { useTranslation } from '../i18n'
import { useEffect, useState, useCallback, useRef } from 'react'

// ── Constants ──
const BUILTIN_DOCKER_NAME = '__docker__'

// ── Types ──

interface RunnerInfo {
  name: string
  token: string
  mode: string
  docker_image: string
  workspace: string
  created_at: string
  shell?: string
  online: boolean
}

interface RunnerPanelProps {
  serverUrl?: string
  wsUrl?: string
  senderId?: string
}

// ── Component ──

export default function RunnerPanel({ serverUrl, wsUrl, senderId }: RunnerPanelProps) {
  const [runners, setRunners] = useState<RunnerInfo[]>([])
  const [activeRunner, setActiveRunner] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)
  const [actionLoading, setActionLoading] = useState(false)
  const [showAddForm, setShowAddForm] = useState(false)
  const [menuOpen, setMenuOpen] = useState<string | null>(null)
  const [copied, setCopied] = useState<string | null>(null)
  const [deleteConfirm, setDeleteConfirm] = useState<string | null>(null)
  // Server-provided connection info (fetched from backend)
  const [serverWsUrl, setServerWsUrl] = useState<string>(wsUrl || '')
  const [serverSenderId, setServerSenderId] = useState<string>(senderId || '')

  // Add form state
  const [formName, setFormName] = useState('')
  const [formMode, setFormMode] = useState<'native' | 'docker'>('native')
  const [formDockerImage, setFormDockerImage] = useState('ubuntu:22.04')
  const [formWorkspace, setFormWorkspace] = useState('')
  const { t } = useTranslation()

  const menuRef = useRef<HTMLDivElement>(null)

  // Close menu on outside click
  useEffect(() => {
    if (!menuOpen) return
    const handleClick = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
        setMenuOpen(null)
      }
    }
    document.addEventListener('mousedown', handleClick)
    return () => document.removeEventListener('mousedown', handleClick)
  }, [menuOpen])

  // Fetch runners
  const fetchRunners = useCallback(async () => {
    try {
      const resp = await fetch('/api/runners')
      const data = await resp.json()
      if (data.ok) {
        setRunners(data.runners || [])
        // Store server-provided connection info
        if (data.ws_url) setServerWsUrl(data.ws_url)
        if (data.sender_id) setServerSenderId(data.sender_id)
        // Also get active runner
        const activeResp = await fetch('/api/runners/active')
        const activeData = await activeResp.json()
        if (activeData.ok && activeData.name) {
          setActiveRunner(activeData.name)
        } else {
          setActiveRunner(null)
        }
      }
    } catch {
      // silently fail
    }
    setLoading(false)
  }, [])

  // Auto-refresh runner list every 30s while panel is visible
  useEffect(() => {
    fetchRunners()
    const timer = setInterval(() => { fetchRunners().catch((err) => { console.warn('[RunnerPanel] poll failed:', err) }) }, 30_000)
    return () => clearInterval(timer)
  }, [fetchRunners])

  // Listen for real-time runner status changes from WebSocket
  useEffect(() => {
    const handler = (e: Event) => {
      const detail = (e as CustomEvent).detail
      if (detail) {
        fetchRunners()
      }
    }
    window.addEventListener('runner-status-change', handler)
    return () => window.removeEventListener('runner-status-change', handler)
  }, [fetchRunners])

  // Shell-quote a string for safe terminal paste
  const shellQuote = (s: string) => "'" + s.replace(/'/g, "'\\''") + "'"

  // Build connect command for a runner
  const buildCommand = useCallback((runner: RunnerInfo) => {
    // Prefer server-provided ws_url, fall back to deriving from serverUrl or window.location
    let wsBase = serverWsUrl
    if (!wsBase && serverUrl) {
      wsBase = serverUrl.replace(/^http/, 'ws')
    }
    if (!wsBase) {
      wsBase = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}`
    }
    // Use server-provided sender_id (e.g. "web-1"), not hardcoded "web-0"
    const sid = serverSenderId || 'web-0'
    let cmd = `./xbot-runner --server ${shellQuote(wsBase + '/ws/' + sid)} --token ${shellQuote(runner.token)}`
    if (runner.mode === 'docker' && runner.docker_image) {
      cmd += ` --mode docker --docker-image ${shellQuote(runner.docker_image)}`
    }
    if (runner.workspace) {
      cmd += ` --workspace ${shellQuote(runner.workspace)}`
    }
    return cmd
  }, [serverWsUrl, serverUrl, serverSenderId])

  // Set active
  const handleSetActive = useCallback(async (name: string) => {
    setActionLoading(true)
    try {
      const resp = await fetch('/api/runners/active', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name }),
      })
      const data = await resp.json()
      if (data.ok) {
        setActiveRunner(name)
      }
    } catch { /* ignored */ }
    setActionLoading(false)
  }, [])

  // Copy command
  const handleCopyCommand = useCallback(async (runner: RunnerInfo) => {
    const cmd = buildCommand(runner)
    try {
      await navigator.clipboard.writeText(cmd)
      setCopied(runner.name)
      setTimeout(() => setCopied(null), 2000)
    } catch { /* ignored */ }
  }, [buildCommand])

  // Delete runner
  const handleDelete = useCallback(async (name: string) => {
    setActionLoading(true)
    try {
      const resp = await fetch(`/api/runners/${encodeURIComponent(name)}`, { method: 'DELETE' })
      const data = await resp.json()
      if (data.ok) {
        setRunners(prev => prev.filter(r => r.name !== name))
        if (activeRunner === name) setActiveRunner(null)
      }
    } catch { /* ignored */ }
    setActionLoading(false)
    setDeleteConfirm(null)
    setMenuOpen(null)
  }, [activeRunner])

  // Create runner
  const handleCreate = useCallback(async () => {
    if (!formName.trim()) return
    setActionLoading(true)
    try {
      const body: Record<string, string> = {
        name: formName.trim(),
        mode: formMode,
      }
      if (formMode === 'docker' && formDockerImage.trim()) {
        body.docker_image = formDockerImage.trim()
      }
      if (formWorkspace.trim()) {
        body.workspace = formWorkspace.trim()
      }
      const resp = await fetch('/api/runners', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      })
      const data = await resp.json()
      if (data.ok) {
        // Re-fetch the full runner list to get accurate info (online status, workspace, etc.)
        await fetchRunners()
        setShowAddForm(false)
        setFormName('')
        setFormMode('native')
        setFormDockerImage('ubuntu:22.04')
        setFormWorkspace('')
      }
    } catch { /* ignored */ }
    setActionLoading(false)
  }, [formName, formMode, formDockerImage, formWorkspace, fetchRunners])

  // Format mode label
  const modeLabel = (mode: string) => {
    switch (mode) {
      case 'docker': return t('dockerMode')
      default: return t('nativeMode')
    }
  }

  // Shorten workspace path
  const shortPath = (ws: string) => {
    if (!ws) return ''
    const home = ws.replace(/^\/home\/\w+|^\/Users\/\w+/, '~')
    return home
  }

  if (loading) {
    return (
      <div className="settings-section">
        <div className="settings-section-title">{t('workspaceEnv')}</div>
        <div className="text-center py-6 text-slate-500 text-sm">{t("sidebarLoading")}</div>
      </div>
    )
  }

  return (
    <div className="settings-section">
      <div className="settings-section-title">{t('workspaceEnv')}</div>
      <p className="text-xs text-slate-500 mb-3">
        {t("manageRunners")}
      </p>

      {/* Runner cards */}
      {runners.length === 0 && !showAddForm ? (
        <div className="text-center py-6 text-slate-500">
          <p className="text-2xl mb-2">🖥️</p>
          <p className="text-sm">{t('noRunners')}</p>
          <p className="text-xs text-slate-600 mt-1">{t('addRunnerHint')}</p>
        </div>
      ) : (
        <div className="runner-list">
          {runners.map(runner => (
            <div
              key={runner.name}
              className={`runner-card ${activeRunner === runner.name ? 'runner-card-active' : ''} ${runner.online ? 'runner-card-online' : ''}`}
              onClick={() => {
                if (runner.online && activeRunner !== runner.name) {
                  handleSetActive(runner.name)
                }
              }}
            >
              {/* Status indicator + Name + Active badge */}
              <div className="runner-card-header">
                <div className="runner-card-title">
                  <span className={`runner-status-dot ${runner.online ? 'runner-dot-online' : 'runner-dot-offline'}`} />
                  <span className="runner-name">{runner.name}</span>
                  {activeRunner === runner.name && (
                    <span className="runner-active-badge">{t('activeBadge')}</span>
                  )}
                </div>
                <div className="runner-card-menu-wrap" ref={menuRef}>
                  <button
                    className="runner-menu-btn"
                    onClick={(e) => {
                      e.stopPropagation()
                      setMenuOpen(menuOpen === runner.name ? null : runner.name)
                    }}
                  >
                    ⋯
                  </button>
                  {menuOpen === runner.name && runner.name !== BUILTIN_DOCKER_NAME && (
                    <div className="runner-menu" onClick={e => e.stopPropagation()}>
                      <button
                        className="runner-menu-item"
                        onClick={() => {
                          handleCopyCommand(runner)
                          setMenuOpen(null)
                        }}
                      >
                        📋 {copied === runner.name ? t('copiedCommand') : t('copyConnectCommand')}
                      </button>
                      <button
                        className="runner-menu-item runner-menu-item-danger"
                        onClick={() => {
                          setDeleteConfirm(runner.name)
                          setMenuOpen(null)
                        }}
                      >
                        🗑️ {t("deleteRunner")}
                      </button>
                    </div>
                  )}
                </div>
              </div>

              {/* Info line */}
              <div className="runner-card-info">
                <span>{runner.name === BUILTIN_DOCKER_NAME ? t('dockerSandbox') : modeLabel(runner.mode)}</span>
                {runner.name !== BUILTIN_DOCKER_NAME && runner.docker_image && (
                  <span className="runner-card-meta">· {runner.docker_image}</span>
                )}
                {runner.name === BUILTIN_DOCKER_NAME && (
                  <span className="runner-card-meta">· {runner.docker_image || t('builtinEnv')}</span>
                )}
                {runner.workspace && (
                  <span className="runner-card-meta">· {shortPath(runner.workspace)}</span>
                )}

              </div>

              {/* Connect command (shown for active or expanded, but not for builtin docker) */}
              {(activeRunner === runner.name || copied === runner.name) && runner.name !== BUILTIN_DOCKER_NAME && (
                <div className="runner-card-command">
                  <code className="runner-command-text">{buildCommand(runner)}</code>
                  <button
                    className="settings-copy-btn"
                    onClick={(e) => {
                      e.stopPropagation()
                      handleCopyCommand(runner)
                    }}
                    title={t('copyConnectCommand')}
                  >📋</button>
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Add form */}
      {showAddForm ? (
        <div className="runner-add-form">
          <div className="settings-item">
            <label className="settings-label">{t("runnerName")} *</label>
            <input
              type="text"
              className="settings-input"
              placeholder={t('runnerNamePlaceholder')}
              maxLength={64}
              value={formName}
              onChange={e => setFormName(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') handleCreate() }}
              autoFocus
            />
          </div>
          <div className="settings-item">
            <label className="settings-label">{t("runMode")}</label>
            <div className="flex gap-2 mt-1">
              {[
                { value: 'native' as const, label: t('nativeMode') },
                { value: 'docker' as const, label: t('dockerMode') },
              ].map(opt => (
                <button
                  key={opt.value}
                  className={`flex-1 px-3 py-2 rounded-lg text-sm border transition-colors ${
                    formMode === opt.value
                      ? 'bg-blue-500/20 border-blue-500/50 text-blue-400'
                      : 'bg-slate-800 border-slate-700 text-slate-400 hover:border-slate-500'
                  }`}
                  onClick={() => setFormMode(opt.value)}
                >
                  {opt.label}
                </button>
              ))}
            </div>
          </div>
          {formMode === 'docker' && (
            <div className="settings-item">
              <label className="settings-label">{t("dockerImage")}</label>
              <input
                type="text"
                className="settings-input"
                placeholder="ubuntu:22.04"
                value={formDockerImage}
                onChange={e => setFormDockerImage(e.target.value)}
              />
            </div>
          )}
          <div className="settings-item">
            <label className="settings-label">{t("workspace")}</label>
            <input
              type="text"
              className="settings-input"
              placeholder={t('workspacePlaceholder')}
              value={formWorkspace}
              onChange={e => setFormWorkspace(e.target.value)}
            />
            <span className="text-xs text-slate-500 mt-1 block">{t('workspaceHint')}</span>
          </div>

          <div className="flex gap-2 mt-3">
            <button
              className="settings-action-btn"
              onClick={handleCreate}
              disabled={!formName.trim() || actionLoading}
            >
              {actionLoading ? t('creating') : t('create')}
            </button>
            <button
              className="settings-action-btn"
              onClick={() => { setShowAddForm(false); setFormName('') }}
            >
              {t("cancel")}
            </button>
          </div>
        </div>
      ) : (
        <button
          className="settings-action-btn w-full mt-3"
          onClick={() => setShowAddForm(true)}
        >
          ➕ {t("addWorkspace")}
        </button>
      )}

      {/* Delete confirmation dialog */}
      {deleteConfirm && (
        <>
          <div className="runner-delete-backdrop" onClick={() => setDeleteConfirm(null)} />
          <div className="runner-delete-dialog">
            <div className="runner-delete-title">{t("confirmDeleteRunner")}</div>
            <p className="runner-delete-text">
              {t("confirmDeleteRunnerText", { name: deleteConfirm })}
            </p>
            {runners.find(r => r.name === deleteConfirm)?.online && (
              <p className="runner-delete-warning">
                {t("runnerOnlineWarning")}
              </p>
            )}
            <div className="flex gap-2 mt-4 justify-end">
              <button
                className="settings-action-btn"
                onClick={() => setDeleteConfirm(null)}
                disabled={actionLoading}
              >
                {t("cancel")}
              </button>
              <button
                className="settings-action-btn settings-action-danger"
                onClick={() => handleDelete(deleteConfirm)}
                disabled={actionLoading}
              >
                {actionLoading ? '⏳' : '🗑️ {t("deleteRunner")}'}
              </button>
            </div>
          </div>
        </>
      )}
    </div>
  )
}
