import { useCallback, useEffect, useRef, useState } from 'react'
import { Link } from 'react-router-dom'

type InstallerConfig = { enabled: boolean; default_install_url: string }

export function RemoteInstallPage() {
  const [cfg, setCfg] = useState<InstallerConfig | null>(null)
  const [cfgError, setCfgError] = useState('')
  const [host, setHost] = useState('')
  const [port, setPort] = useState('22')
  const [username, setUsername] = useState('root')
  const [authType, setAuthType] = useState<'key' | 'password'>('key')
  const [privateKey, setPrivateKey] = useState('')
  const [passphrase, setPassphrase] = useState('')
  const [password, setPassword] = useState('')
  const [installUrl, setInstallUrl] = useState('')
  const [log, setLog] = useState<string[]>([])
  const [running, setRunning] = useState(false)
  const [exitCode, setExitCode] = useState<number | null>(null)
  const [formError, setFormError] = useState('')
  const logRef = useRef<HTMLPreElement>(null)

  useEffect(() => {
    fetch('/api/v1/public-install/config')
      .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`))))
      .then((d: InstallerConfig) => {
        setCfg(d)
        setInstallUrl(d.default_install_url || '')
      })
      .catch(() => setCfgError('Could not load installer configuration'))
  }, [])

  useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight
  }, [log])

  const appendLog = useCallback((line: string) => {
    setLog((prev) => [...prev.slice(-2000), line])
  }, [])

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    setFormError('')
    setLog([])
    setExitCode(null)
    if (!cfg?.enabled) return

    const urlField = installUrl.trim() || cfg.default_install_url
    const auth =
      authType === 'key'
        ? { type: 'key' as const, private_key: privateKey, passphrase: passphrase || null }
        : { type: 'password' as const, password }

    const body = {
      host: host.trim(),
      port: parseInt(port, 10) || 22,
      username: username.trim(),
      auth,
      install_url: urlField === cfg.default_install_url ? null : urlField,
    }

    setRunning(true)
    try {
      const res = await fetch('/api/v1/public-install/jobs', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      })
      if (!res.ok) {
        const err = await res.json().catch(() => ({}))
        throw new Error(err.detail || `HTTP ${res.status}`)
      }
      const { job_id } = (await res.json()) as { job_id: string }

      const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
      const ws = new WebSocket(`${proto}//${window.location.host}/api/v1/public-install/ws/${job_id}`)

      ws.onmessage = (ev) => {
        try {
          const data = JSON.parse(ev.data as string)
          if (data.type === 'line' && typeof data.text === 'string') appendLog(data.text)
          if (data.type === 'done') setExitCode(typeof data.exit_code === 'number' ? data.exit_code : -1)
        } catch {
          appendLog(String(ev.data))
        }
      }
      ws.onerror = () => appendLog('[websocket error]')
      ws.onclose = () => setRunning(false)
    } catch (err) {
      setFormError(err instanceof Error ? err.message : 'Request failed')
      setRunning(false)
    } finally {
      if (authType === 'password') setPassword('')
    }
  }

  if (!cfg && !cfgError) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-100 dark:bg-gray-900">
        <p className="text-gray-500">Loading…</p>
      </div>
    )
  }

  if (cfgError) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-100 dark:bg-gray-900 p-4">
        <p className="text-red-600">{cfgError}</p>
      </div>
    )
  }

  if (cfg && !cfg.enabled) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-100 dark:bg-gray-900 p-4">
        <div className="w-full max-w-lg p-8 bg-white dark:bg-gray-800 rounded-xl shadow-lg space-y-4">
          <h1 className="text-xl font-bold text-gray-900 dark:text-white">Remote SSH installer disabled</h1>
          <p className="text-gray-600 dark:text-gray-300 text-sm">
            Enable it on the API server with environment variable{' '}
            <code className="bg-gray-200 dark:bg-gray-700 px-1 rounded">ENABLE_REMOTE_INSTALLER=true</code> and restart
            the backend. Prefer SSH keys; exposing this endpoint increases risk.
          </p>
          <p className="text-sm text-gray-600 dark:text-gray-400">
            One-liner on the target server (as root):{' '}
            <code className="break-all block mt-2 bg-gray-900 text-green-400 p-2 rounded text-xs">
              curl -fsSL {cfg.default_install_url} | bash
            </code>
          </p>
          <Link to="/login" className="inline-block text-blue-600 hover:underline text-sm">
            Panel login
          </Link>
        </div>
      </div>
    )
  }

  return (
    <div className="min-h-screen bg-gray-100 dark:bg-gray-900 py-8 px-4">
      <div className="max-w-3xl mx-auto space-y-6">
        <div className="bg-amber-100 dark:bg-amber-900/40 border border-amber-300 dark:border-amber-700 rounded-lg p-4 text-sm text-amber-950 dark:text-amber-100">
          <strong>Security warning:</strong> SSH credentials are sent to this panel API and used only for this session
          (not stored). Prefer <strong>SSH private keys</strong>. Root password SSH is often disabled on Ubuntu. Non-root
          users need <strong>passwordless sudo</strong> (<code>sudo -n</code>) to run the installer. Allow SSH from this
          server to the target on port {port}.
        </div>

        <div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6">
          <h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">Remote install (SSH)</h1>
          <p className="text-sm text-gray-600 dark:text-gray-400 mb-6">
            Runs the published <code>install.sh</code> on the target via SSH (same as shell one-liner).
          </p>

          <form onSubmit={handleSubmit} className="space-y-4">
            {formError && (
              <div className="p-3 rounded-lg bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300 text-sm">
                {formError}
              </div>
            )}
            <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
              <div className="sm:col-span-2">
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Host</label>
                <input
                  type="text"
                  value={host}
                  onChange={(e) => setHost(e.target.value)}
                  className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                  placeholder="203.0.113.50"
                  required
                />
              </div>
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">SSH port</label>
                <input
                  type="number"
                  value={port}
                  onChange={(e) => setPort(e.target.value)}
                  className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                  min={1}
                  max={65535}
                />
              </div>
            </div>
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">SSH username</label>
              <input
                type="text"
                value={username}
                onChange={(e) => setUsername(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                required
              />
            </div>
            <div>
              <span className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Authentication</span>
              <div className="flex gap-4">
                <label className="inline-flex items-center gap-2 text-sm text-gray-800 dark:text-gray-200">
                  <input
                    type="radio"
                    name="auth"
                    checked={authType === 'key'}
                    onChange={() => setAuthType('key')}
                  />
                  Private key
                </label>
                <label className="inline-flex items-center gap-2 text-sm text-gray-800 dark:text-gray-200">
                  <input
                    type="radio"
                    name="auth"
                    checked={authType === 'password'}
                    onChange={() => setAuthType('password')}
                  />
                  Password
                </label>
              </div>
            </div>
            {authType === 'key' ? (
              <>
                <div>
                  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Private key (PEM)</label>
                  <textarea
                    value={privateKey}
                    onChange={(e) => setPrivateKey(e.target.value)}
                    rows={6}
                    className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white font-mono text-xs"
                    placeholder="-----BEGIN OPENSSH PRIVATE KEY-----"
                    required
                  />
                </div>
                <div>
                  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
                    Key passphrase (optional)
                  </label>
                  <input
                    type="password"
                    value={passphrase}
                    onChange={(e) => setPassphrase(e.target.value)}
                    className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                  />
                </div>
              </>
            ) : (
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">SSH password</label>
                <input
                  type="password"
                  value={password}
                  onChange={(e) => setPassword(e.target.value)}
                  className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
                  required
                />
              </div>
            )}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
                Install script URL (https only)
              </label>
              <input
                type="url"
                value={installUrl}
                onChange={(e) => setInstallUrl(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm"
              />
            </div>
            <button
              type="submit"
              disabled={running || !cfg?.enabled || !cfg}
              className="w-full py-2 px-4 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white rounded-lg font-medium"
            >
              {running ? 'Running…' : 'Start remote install'}
            </button>
          </form>
        </div>

        {log.length > 0 && (
          <div className="bg-gray-900 text-gray-100 rounded-xl p-4 font-mono text-xs overflow-hidden">
            <pre ref={logRef} className="max-h-96 overflow-auto whitespace-pre-wrap break-words">
              {log.join('\n')}
            </pre>
            {exitCode !== null && (
              <p className="mt-2 text-sm border-t border-gray-700 pt-2">
                Exit code: <strong>{exitCode}</strong>
              </p>
            )}
          </div>
        )}

        <p className="text-center text-sm text-gray-500">
          <Link to="/login" className="text-blue-600 hover:underline">
            Panel login
          </Link>
        </p>
      </div>
    </div>
  )
}
