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

type SetupStep = 'idle' | 'registering-sw' | 'generating' | 'done' | 'error'

function isBrowserSupported(): boolean {
  try {
    // Ed25519 requires SubtleCrypto and the algorithm support
    // We can only really verify at runtime, but check for the basics here
    return (
      typeof crypto !== 'undefined' &&
      typeof crypto.subtle !== 'undefined' &&
      typeof crypto.randomUUID === 'function' &&
      'serviceWorker' in navigator
    )
  } catch {
    return false
  }
}

async function sendMessageToSW(
  reg: ServiceWorkerRegistration,
  message: object
): Promise<Record<string, unknown>> {
  return new Promise((resolve, reject) => {
    const channel = new MessageChannel()
    channel.port1.onmessage = (e) => resolve(e.data as Record<string, unknown>)
    channel.port1.onmessageerror = () => reject(new Error('MessageChannel-Fehler'))
    const sw = reg.active
    if (!sw) { reject(new Error('ServiceWorker nicht aktiv')); return }
    sw.postMessage({ ...message, port: channel.port2 }, [channel.port2])
  })
}

export function KioskSetupPage() {
  const [searchParams] = useSearchParams()
  const deviceIdParam = searchParams.get('device_id') ?? ''

  const [deviceId, setDeviceId]   = useState(deviceIdParam)
  const [step, setStep]           = useState<SetupStep>('idle')
  const [errorMsg, setErrorMsg]   = useState<string | null>(null)
  const [publicKeyPem, setPublicKeyPem] = useState<string | null>(null)
  const [copied, setCopied]       = useState(false)
  const [existingDeviceId, setExistingDeviceId] = useState<string | null>(null)
  const swRegRef = useRef<ServiceWorkerRegistration | null>(null)

  const supported = isBrowserSupported()

  // On mount: register SW and check for existing credentials
  useEffect(() => {
    if (!supported) return
    ;(async () => {
      try {
        const reg = await navigator.serviceWorker.register('/kiosk-sw.js', { scope: '/' })
        // Wait until the SW is active
        if (!reg.active) {
          await new Promise<void>((resolve) => {
            const sw = reg.installing || reg.waiting
            if (!sw) { resolve(); return }
            sw.addEventListener('statechange', function handler() {
              if (sw.state === 'activated') {
                sw.removeEventListener('statechange', handler)
                resolve()
              }
            })
          })
          // Re-fetch after activation
          const updated = await navigator.serviceWorker.ready
          swRegRef.current = updated
        } else {
          swRegRef.current = reg
        }
        // Check if credentials already exist
        const ready = await navigator.serviceWorker.ready
        swRegRef.current = ready
        const result = await sendMessageToSW(ready, { type: 'CHECK_CREDENTIALS' })
        if (result.hasCredentials) {
          setExistingDeviceId(result.deviceId as string)
        }
      } catch {
        // SW registration failure is non-fatal for the setup UI
      }
    })()
  }, [supported])

  async function handleGenerate() {
    setErrorMsg(null)
    setCopied(false)
    setPublicKeyPem(null)

    if (!deviceId.trim()) {
      setErrorMsg('Bitte eine Geraete-ID eingeben (UUID des Kiosk-Geraets).')
      return
    }

    setStep('registering-sw')
    try {
      if (!swRegRef.current) {
        const reg = await navigator.serviceWorker.register('/kiosk-sw.js', { scope: '/' })
        const ready = await navigator.serviceWorker.ready
        swRegRef.current = reg.active ? reg : ready
      }
      const ready = await navigator.serviceWorker.ready
      swRegRef.current = ready

      setStep('generating')
      const result = await sendMessageToSW(ready, {
        type: 'GENERATE_KEYPAIR',
        deviceId: deviceId.trim(),
      })

      if (!result.success) {
        throw new Error((result.error as string) ?? 'Unbekannter Fehler im ServiceWorker')
      }

      setPublicKeyPem(result.publicKeyPem as string)
      setExistingDeviceId(deviceId.trim())
      setStep('done')
    } catch (e: unknown) {
      const msg = e instanceof Error ? e.message : String(e)
      // Ed25519 not supported
      if (msg.includes('Ed25519') || msg.includes('NotSupportedError') || msg.includes('algorithm')) {
        setErrorMsg(
          'Dieser Browser unterstuetzt kein Ed25519. Bitte Chrome 113+, Firefox 130+ oder Safari 16.4+ verwenden.'
        )
      } else {
        setErrorMsg(msg)
      }
      setStep('error')
    }
  }

  async function handleReset() {
    if (!swRegRef.current) return
    try {
      await sendMessageToSW(swRegRef.current, { type: 'CLEAR_CREDENTIALS' })
      setExistingDeviceId(null)
      setPublicKeyPem(null)
      setStep('idle')
      setDeviceId(deviceIdParam)
      setErrorMsg(null)
      setCopied(false)
    } catch (e: unknown) {
      setErrorMsg(e instanceof Error ? e.message : 'Fehler beim Zuruecksetzen')
    }
  }

  async function handleCopy() {
    if (!publicKeyPem) return
    try {
      await navigator.clipboard.writeText(publicKeyPem)
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    } catch {
      // fallback: select textarea
    }
  }

  const isGenerating = step === 'registering-sw' || step === 'generating'

  if (!supported) {
    return (
      <div className='min-h-screen bg-gray-900 text-white flex items-center justify-center p-6'>
        <div className='max-w-md w-full bg-gray-800 rounded-2xl p-8 text-center'>
          <div className='text-4xl mb-4'>⚠️</div>
          <h1 className='text-xl font-bold mb-2'>Browser nicht unterstuetzt</h1>
          <p className='text-gray-400 text-sm'>
            Dieser Browser unterstuetzt kein Ed25519 oder ServiceWorker.
            Bitte Chrome 113+, Firefox 130+ oder Safari 16.4+ verwenden.
          </p>
        </div>
      </div>
    )
  }

  return (
    <div className='min-h-screen bg-gray-900 text-white flex items-center justify-center p-6'>
      <div className='max-w-lg w-full space-y-6'>

        {/* Header */}
        <div className='text-center'>
          <div className='text-5xl mb-3'>🔐</div>
          <h1 className='text-2xl font-bold'>Kiosk einrichten</h1>
          <p className='text-gray-400 text-sm mt-1'>
            Generiert ein Ed25519-Schluessel&shy;paar fuer dieses Geraet.
            Der private Schluessel verlässt den Browser nie.
          </p>
        </div>

        {/* Existing credentials warning */}
        {existingDeviceId && step !== 'done' && (
          <div className='bg-yellow-900/50 border border-yellow-700 rounded-xl px-4 py-3 text-sm text-yellow-300'>
            <span className='font-semibold'>Achtung:</span> Dieses Geraet hat bereits gespeicherte Credentials
            fuer Geraet <code className='bg-yellow-900 rounded px-1'>{existingDeviceId}</code>.
            Ein Neugenerieren ueberschreibt den vorhandenen Schluessel.{' '}
            <button onClick={handleReset} className='underline hover:text-yellow-100 ml-1'>
              Zuruecksetzen
            </button>
          </div>
        )}

        {/* Main card */}
        <div className='bg-gray-800 rounded-2xl p-6 space-y-4'>
          <label className='block'>
            <span className='text-sm font-medium text-gray-300 block mb-1'>Geraete-ID (UUID)</span>
            <input
              value={deviceId}
              onChange={e => setDeviceId(e.target.value)}
              placeholder='z.B. 550e8400-e29b-41d4-a716-446655440000'
              disabled={isGenerating || step === 'done'}
              className='w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-sm text-white
                         placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500
                         disabled:opacity-50'
            />
            <p className='text-xs text-gray-500 mt-1'>
              Die UUID des Geraets aus der Admin-Oberflaeche (Einstellungen → Kiosk-Geraete).
            </p>
          </label>

          {errorMsg && (
            <div className='bg-red-900/50 border border-red-700 rounded-lg px-3 py-2 text-sm text-red-300'>
              {errorMsg}
            </div>
          )}

          {step !== 'done' && (
            <button
              onClick={handleGenerate}
              disabled={isGenerating || !deviceId.trim()}
              className='w-full py-3 bg-blue-600 hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed
                         rounded-xl font-semibold text-sm transition-colors'
            >
              {step === 'registering-sw' && 'ServiceWorker wird registriert…'}
              {step === 'generating'     && 'Schluesselpaar wird generiert…'}
              {(step === 'idle' || step === 'error') && 'Schluesselpaar generieren'}
            </button>
          )}

          {/* Success state */}
          {step === 'done' && publicKeyPem && (
            <div className='space-y-4'>
              <div className='flex items-center gap-2 text-green-400 text-sm font-medium'>
                <span className='text-lg'>✓</span>
                Schluesselpaar generiert und gespeichert.
              </div>

              <div>
                <div className='flex items-center justify-between mb-1'>
                  <span className='text-xs font-medium text-gray-400 uppercase tracking-wide'>
                    Public Key (PEM-Format)
                  </span>
                  <button
                    onClick={handleCopy}
                    className='text-xs text-blue-400 hover:text-blue-300 transition-colors'
                  >
                    {copied ? '✓ Kopiert!' : 'Kopieren'}
                  </button>
                </div>
                <pre className='bg-gray-900 rounded-lg p-3 text-xs text-green-300 font-mono
                                overflow-x-auto whitespace-pre-wrap break-all border border-gray-700'>
                  {publicKeyPem}
                </pre>
              </div>

              <div className='bg-blue-900/40 border border-blue-700 rounded-lg px-3 py-3 text-xs text-blue-300 space-y-1'>
                <p className='font-semibold text-blue-200'>Naechste Schritte:</p>
                <ol className='list-decimal ml-4 space-y-1'>
                  <li>Public Key oben kopieren und an den Admin schicken (E-Mail reicht – kein Geheimnis).</li>
                  <li>
                    Admin registriert das Geraet auf dem Server:{' '}
                    <code className='bg-blue-950 rounded px-1'>timemaster kiosk add --pubkey ...</code>
                  </li>
                  <li>Admin gibt das Geraet in der Web-Oberflaeche frei.</li>
                  <li>Kiosk-Modus starten.</li>
                </ol>
              </div>

              <div className='flex gap-3'>
                <Link
                  to='/kiosk'
                  className='flex-1 text-center py-2.5 bg-green-600 hover:bg-green-700 rounded-xl
                             font-semibold text-sm transition-colors'
                >
                  Zum Kiosk →
                </Link>
                <button
                  onClick={handleReset}
                  className='px-4 py-2.5 border border-gray-600 text-gray-300 hover:bg-gray-700
                             rounded-xl text-sm transition-colors'
                >
                  Zuruecksetzen
                </button>
              </div>
            </div>
          )}
        </div>

        {/* Back link */}
        {step !== 'done' && (
          <p className='text-center text-xs text-gray-600'>
            <Link to='/login' className='hover:text-gray-400 underline'>Zurueck zum Login</Link>
          </p>
        )}
      </div>
    </div>
  )
}
