import { useEffect, useState } from 'react'
import QRCode from 'qrcode'
import { api } from '../api/client'
import { Layout } from '../components/Layout'

interface UserOut {
  id: string; first_name: string; last_name: string; email: string; role: string; personnel_number: string | null
  totp_enabled?: boolean
}

const ROLE_LABELS: Record<string, string> = {
  SUPER_ADMIN: 'Super Admin', COMPANY_ADMIN: 'Administrator',
  HR: 'HR', MANAGER: 'Manager', EMPLOYEE: 'Mitarbeiter',
}

// ── TOTP-Setup-Schritte ───────────────────────────────────────────────────────
type TotpStep = 'idle' | 'setup' | 'confirm' | 'done'

function TotpSection({ enabled, onToggle }: { enabled: boolean; onToggle: () => void }) {
  const [step, setStep] = useState<TotpStep>('idle')
  const [qrDataUrl, setQrDataUrl] = useState('')
  const [secret, setSecret] = useState('')
  const [code, setCode] = useState('')
  const [disablePw, setDisablePw] = useState('')
  const [disableCode, setDisableCode] = useState('')
  const [showDisable, setShowDisable] = useState(false)
  const [error, setError] = useState('')
  const [loading, setLoading] = useState(false)

  const inp = 'w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500'

  const startSetup = async () => {
    setLoading(true); setError('')
    try {
      const res = await api.post<{ secret: string; otpauth_uri: string }>('/auth/totp/setup', {})
      setSecret(res.secret)
      // Secret in DB speichern (ohne Aktivierung)
      await api.post('/auth/totp/setup/save', {})
      const dataUrl = await QRCode.toDataURL(res.otpauth_uri, { width: 200, margin: 2 })
      setQrDataUrl(dataUrl)
      setStep('setup')
    } catch (e: unknown) { setError(e instanceof Error ? e.message : 'Fehler') }
    finally { setLoading(false) }
  }

  const confirmCode = async () => {
    if (code.length !== 6) { setError('Code muss 6 Ziffern haben'); return }
    setLoading(true); setError('')
    try {
      await api.post('/auth/totp/confirm', { code })
      setStep('done')
      setCode('')
      onToggle()
    } catch (e: unknown) { setError(e instanceof Error ? e.message : 'Ungültiger Code') }
    finally { setLoading(false) }
  }

  const disableTotp = async () => {
    setLoading(true); setError('')
    try {
      await api.post('/auth/totp/disable', { password: disablePw, code: disableCode })
      setShowDisable(false); setDisablePw(''); setDisableCode('')
      onToggle()
    } catch (e: unknown) { setError(e instanceof Error ? e.message : 'Fehler') }
    finally { setLoading(false) }
  }

  // Aktiv-Zustand
  if (enabled && step !== 'done') {
    return (
      <div>
        <div className='flex items-center justify-between'>
          <div className='flex items-center gap-2'>
            <span className='w-2.5 h-2.5 rounded-full bg-green-500 inline-block' />
            <span className='text-sm font-medium text-green-700'>Aktiv</span>
          </div>
          <button onClick={() => setShowDisable(!showDisable)}
            className='text-sm text-red-500 hover:text-red-700 hover:underline'>
            Deaktivieren
          </button>
        </div>
        {showDisable && (
          <div className='mt-4 space-y-3 border-t border-gray-100 pt-4'>
            <p className='text-sm text-gray-600'>Zur Bestätigung Passwort und aktuellen TOTP-Code eingeben:</p>
            <input type='password' placeholder='Aktuelles Passwort' value={disablePw}
              onChange={e => setDisablePw(e.target.value)} className={inp} />
            <input type='text' inputMode='numeric' placeholder='6-stelliger Code' maxLength={6}
              value={disableCode} onChange={e => setDisableCode(e.target.value.replace(/\D/g, ''))} className={inp} />
            {error && <p className='text-sm text-red-600'>{error}</p>}
            <div className='flex gap-2'>
              <button onClick={disableTotp} disabled={loading || !disablePw || disableCode.length < 6}
                className='flex-1 py-2 bg-red-600 text-white rounded-lg text-sm font-medium hover:bg-red-700 disabled:opacity-50'>
                {loading ? 'Bitte warten…' : '2FA deaktivieren'}
              </button>
              <button onClick={() => { setShowDisable(false); setError('') }}
                className='px-4 py-2 border border-gray-300 rounded-lg text-sm text-gray-600 hover:bg-gray-50'>
                Abbrechen
              </button>
            </div>
          </div>
        )}
      </div>
    )
  }

  // Setup-Flow
  if (step === 'idle') {
    return (
      <div>
        <p className='text-sm text-gray-500 mb-4'>
          Mit einem Einmalpasswort (TOTP) aus einer Authenticator-App wird dein Konto zusätzlich abgesichert.
          Kompatibel mit Google Authenticator, Authy, und anderen TOTP-Apps.
        </p>
        <button onClick={startSetup} disabled={loading}
          className='px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 disabled:opacity-50'>
          {loading ? 'Bitte warten…' : '2FA einrichten'}
        </button>
        {error && <p className='text-sm text-red-600 mt-2'>{error}</p>}
      </div>
    )
  }

  if (step === 'setup') {
    return (
      <div className='space-y-4'>
        <p className='text-sm text-gray-600'>
          <strong>Schritt 1:</strong> Scanne den QR-Code mit deiner Authenticator-App.
        </p>
        <div className='flex justify-center'>
          {qrDataUrl && <img src={qrDataUrl} alt='TOTP QR-Code' className='rounded-lg border border-gray-200 p-2' />}
        </div>
        <details className='text-xs text-gray-400'>
          <summary className='cursor-pointer hover:text-gray-600'>Secret manuell eingeben</summary>
          <code className='block mt-2 bg-gray-50 rounded px-3 py-2 text-gray-700 font-mono break-all select-all'>
            {secret}
          </code>
        </details>
        <p className='text-sm text-gray-600'>
          <strong>Schritt 2:</strong> Gib den 6-stelligen Code aus der App ein:
        </p>
        <input type='text' inputMode='numeric' placeholder='123456' maxLength={6}
          value={code} onChange={e => setCode(e.target.value.replace(/\D/g, ''))}
          className={`${inp} text-center text-xl tracking-widest font-mono`} autoFocus />
        {error && <p className='text-sm text-red-600'>{error}</p>}
        <div className='flex gap-2'>
          <button onClick={confirmCode} disabled={loading || code.length < 6}
            className='flex-1 py-2 bg-green-600 text-white rounded-lg text-sm font-medium hover:bg-green-700 disabled:opacity-50'>
            {loading ? 'Prüfen…' : 'Bestätigen & aktivieren'}
          </button>
          <button onClick={() => { setStep('idle'); setCode(''); setError('') }}
            className='px-4 py-2 border border-gray-300 rounded-lg text-sm text-gray-600 hover:bg-gray-50'>
            Abbrechen
          </button>
        </div>
      </div>
    )
  }

  // done
  return (
    <div className='flex items-center gap-2 text-green-700'>
      <svg className='w-5 h-5' fill='none' viewBox='0 0 24 24' stroke='currentColor'>
        <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M5 13l4 4L19 7' />
      </svg>
      <span className='text-sm font-medium'>Zwei-Faktor-Authentifizierung erfolgreich aktiviert!</span>
    </div>
  )
}

// ── iCal-Abo ──────────────────────────────────────────────────────────────────

function IcalSection() {
  const [enabled, setEnabled] = useState(false)
  const [url, setUrl] = useState('')          // nur direkt nach Erzeugen bekannt
  const [busy, setBusy] = useState(false)
  const [copied, setCopied] = useState(false)

  useEffect(() => {
    api.get<{ enabled: boolean }>('/users/me/ical-token')
      .then(r => setEnabled(r.enabled)).catch(() => {})
  }, [])

  async function createOrRotate() {
    setBusy(true)
    try {
      const r = await api.post<{ enabled: boolean; url: string }>('/users/me/ical-token', {})
      setEnabled(true); setUrl(r.url); setCopied(false)
    } finally { setBusy(false) }
  }

  async function disable() {
    setBusy(true)
    try {
      await api.del('/users/me/ical-token')
      setEnabled(false); setUrl('')
    } finally { setBusy(false) }
  }

  function copy() {
    navigator.clipboard.writeText(url).then(() => {
      setCopied(true); setTimeout(() => setCopied(false), 2000)
    })
  }

  return (
    <div className='bg-white rounded-xl shadow-sm border border-gray-200 p-6'>
      <div className='mb-4'>
        <h2 className='font-semibold text-gray-800'>Kalender-Abo (iCal)</h2>
        <p className='text-sm text-gray-400 mt-0.5'>
          Abonniere deine genehmigten Abwesenheiten schreibgeschützt in Outlook, Apple oder
          Google Kalender. Die URL enthält ein geheimes Token – nicht weitergeben.
        </p>
      </div>

      {url && (
        <div className='mb-4 rounded-lg border border-blue-200 bg-blue-50 p-3'>
          <p className='text-xs font-medium text-blue-800 mb-1'>
            Deine Feed-URL (wird nur jetzt einmal angezeigt):
          </p>
          <div className='flex items-center gap-2'>
            <input readOnly value={url} onFocus={e => e.target.select()}
              className='flex-1 border border-blue-300 rounded px-2 py-1.5 text-xs font-mono bg-white' />
            <button onClick={copy}
              className='px-3 py-1.5 bg-blue-600 text-white rounded text-xs font-medium hover:bg-blue-700 whitespace-nowrap'>
              {copied ? 'Kopiert ✓' : 'Kopieren'}
            </button>
          </div>
        </div>
      )}

      {!url && enabled && (
        <p className='mb-4 text-sm text-green-700 font-medium'>
          ✓ Feed ist aktiv. Aus Sicherheitsgründen wird die URL nicht erneut angezeigt –
          bei Verlust neu erzeugen (das alte Token wird dabei ungültig).
        </p>
      )}

      <div className='flex flex-wrap gap-2'>
        <button onClick={createOrRotate} disabled={busy}
          className='py-2 px-4 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 disabled:opacity-50'>
          {busy ? '…' : enabled ? 'URL neu erzeugen (rotieren)' : 'Feed aktivieren'}
        </button>
        {enabled && (
          <button onClick={disable} disabled={busy}
            className='py-2 px-4 border border-red-300 text-red-600 rounded-lg text-sm font-medium hover:bg-red-50 disabled:opacity-50'>
            Feed deaktivieren
          </button>
        )}
      </div>
    </div>
  )
}

// ── Hauptseite ────────────────────────────────────────────────────────────────

export function ProfilePage() {
  const [me, setMe] = useState<UserOut | null>(null)
  const [totpEnabled, setTotpEnabled] = useState(false)
  const [currentPw, setCurrentPw] = useState('')
  const [newPw, setNewPw] = useState('')
  const [confirmPw, setConfirmPw] = useState('')
  const [saving, setSaving] = useState(false)
  const [success, setSuccess] = useState(false)
  const [error, setError] = useState<string | null>(null)
  // Stempel-PIN (Kiosk / öffentliches QR-Stempeln)
  const [pin, setPin] = useState('')
  const [pinConfirm, setPinConfirm] = useState('')
  const [pinSaving, setPinSaving] = useState(false)
  const [pinSuccess, setPinSuccess] = useState(false)
  const [pinError, setPinError] = useState<string | null>(null)

  const [notifPrefs, setNotifPrefs] = useState<{ key: string; label: string; enabled: boolean }[]>([])

  const loadMe = () => {
    api.get<UserOut>('/auth/me').then(u => {
      setMe(u)
      setTotpEnabled(u.totp_enabled ?? false)
    }).catch(() => {})
  }

  const loadNotifPrefs = () => {
    api.get<{ key: string; label: string; enabled: boolean }[]>('/users/me/notification-prefs')
      .then(setNotifPrefs).catch(() => {})
  }

  async function toggleNotif(key: string, enabled: boolean) {
    setNotifPrefs(prev => prev.map(p => p.key === key ? { ...p, enabled } : p))
    try {
      const updated = await api.patch<{ key: string; label: string; enabled: boolean }[]>(
        '/users/me/notification-prefs', { prefs: { [key]: enabled } })
      setNotifPrefs(updated)
    } catch { loadNotifPrefs() }
  }

  useEffect(() => { loadMe(); loadNotifPrefs() }, [])

  async function changePassword(e: React.FormEvent) {
    e.preventDefault()
    if (newPw !== confirmPw) { setError('Passwörter stimmen nicht überein'); return }
    if (newPw.length < 8) { setError('Mindestens 8 Zeichen'); return }
    setSaving(true); setError(null); setSuccess(false)
    try {
      await api.post('/auth/change-password', { current_password: currentPw, new_password: newPw })
      setSuccess(true)
      setCurrentPw(''); setNewPw(''); setConfirmPw('')
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : 'Fehler beim Ändern des Passworts')
    } finally {
      setSaving(false)
    }
  }

  async function savePin(e: React.FormEvent) {
    e.preventDefault()
    if (!me) return
    if (pin !== pinConfirm) { setPinError('PINs stimmen nicht überein'); return }
    if (!/^\d{4,6}$/.test(pin)) { setPinError('PIN muss 4 bis 6 Ziffern haben'); return }
    setPinSaving(true); setPinError(null); setPinSuccess(false)
    try {
      await api.post(`/users/${me.id}/kiosk-pin`, { pin })
      setPinSuccess(true)
      setPin(''); setPinConfirm('')
    } catch (e: unknown) {
      setPinError(e instanceof Error ? e.message : 'Fehler beim Setzen der PIN')
    } finally {
      setPinSaving(false)
    }
  }

  return (
    <Layout userRole={me?.role ?? ''} userName={me ? `${me.first_name} ${me.last_name}` : ''}>
      <div className='max-w-lg mx-auto space-y-6'>
        <h1 className='text-2xl font-bold text-gray-900'>Mein Profil</h1>

        {/* Profil-Info */}
        {me && (
          <div className='bg-white rounded-xl shadow-sm border border-gray-200 p-6'>
            <div className='flex items-center gap-4'>
              <div className='w-14 h-14 rounded-full bg-blue-100 flex items-center justify-center text-blue-700 font-bold text-xl'>
                {me.first_name[0]}{me.last_name[0]}
              </div>
              <div>
                <p className='text-lg font-semibold text-gray-900'>{me.first_name} {me.last_name}</p>
                <p className='text-sm text-gray-500'>{me.email}</p>
                <span className='inline-block mt-1 text-xs px-2 py-0.5 rounded-full bg-blue-50 text-blue-700 font-medium'>
                  {ROLE_LABELS[me.role] ?? me.role}
                </span>
              </div>
            </div>
            {me.personnel_number && (
              <div className='mt-4 pt-4 border-t border-gray-100 flex items-center justify-between'>
                <span className='text-sm text-gray-500'>Personalnummer</span>
                <span className='text-sm font-mono font-semibold text-gray-800'>{me.personnel_number}</span>
              </div>
            )}
          </div>
        )}

        {/* Zwei-Faktor-Authentifizierung */}
        <div className='bg-white rounded-xl shadow-sm border border-gray-200 p-6'>
          <div className='mb-4'>
            <h2 className='font-semibold text-gray-800'>Zwei-Faktor-Authentifizierung</h2>
            <p className='text-sm text-gray-400 mt-0.5'>TOTP · Google Authenticator, Authy, etc.</p>
          </div>
          <TotpSection enabled={totpEnabled} onToggle={loadMe} />
        </div>

        {/* Stempel-PIN */}
        <div className='bg-white rounded-xl shadow-sm border border-gray-200 p-6'>
          <div className='mb-4'>
            <h2 className='font-semibold text-gray-800'>Stempel-PIN</h2>
            <p className='text-sm text-gray-400 mt-0.5'>
              4–6 Ziffern · für Kiosk-Terminals und das mobile QR-Stempeln (Personalnummer + PIN).
            </p>
          </div>
          <form onSubmit={savePin} className='space-y-4'>
            <div>
              <label className='block text-sm font-medium text-gray-700 mb-1'>Neue PIN</label>
              <input type='password' inputMode='numeric' value={pin}
                onChange={e => setPin(e.target.value.replace(/\D/g, '').slice(0, 6))}
                autoComplete='off'
                className='w-full border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono tracking-widest focus:outline-none focus:ring-2 focus:ring-blue-500' />
            </div>
            <div>
              <label className='block text-sm font-medium text-gray-700 mb-1'>PIN bestätigen</label>
              <input type='password' inputMode='numeric' value={pinConfirm}
                onChange={e => setPinConfirm(e.target.value.replace(/\D/g, '').slice(0, 6))}
                autoComplete='off'
                className='w-full border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono tracking-widest focus:outline-none focus:ring-2 focus:ring-blue-500' />
            </div>
            {pinError && <p className='text-sm text-red-600'>{pinError}</p>}
            {pinSuccess && <p className='text-sm text-green-600 font-medium'>PIN erfolgreich gesetzt</p>}
            <button type='submit' disabled={pinSaving || !pin || !pinConfirm}
              className='w-full py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 disabled:opacity-50'>
              {pinSaving ? 'Speichern…' : 'PIN speichern'}
            </button>
          </form>
        </div>

        {/* Kalender-Abo (iCal) */}
        <IcalSection />

        {/* Passwort ändern */}
        <div className='bg-white rounded-xl shadow-sm border border-gray-200 p-6'>
          <h2 className='font-semibold text-gray-700 mb-4'>Passwort ändern</h2>
          <form onSubmit={changePassword} className='space-y-4'>
            <div>
              <label className='block text-sm font-medium text-gray-700 mb-1'>Aktuelles Passwort</label>
              <input type='password' value={currentPw} onChange={e => setCurrentPw(e.target.value)}
                required autoComplete='current-password'
                className='w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500' />
            </div>
            <div>
              <label className='block text-sm font-medium text-gray-700 mb-1'>Neues Passwort</label>
              <input type='password' value={newPw} onChange={e => setNewPw(e.target.value)}
                required autoComplete='new-password'
                className='w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500' />
              <p className='mt-1 text-xs text-gray-400'>Mindestens 8 Zeichen, 1 Großbuchstabe, 1 Zahl</p>
            </div>
            <div>
              <label className='block text-sm font-medium text-gray-700 mb-1'>Neues Passwort bestätigen</label>
              <input type='password' value={confirmPw} onChange={e => setConfirmPw(e.target.value)}
                required autoComplete='new-password'
                className='w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500' />
            </div>
            {error && <p className='text-sm text-red-600'>{error}</p>}
            {success && <p className='text-sm text-green-600 font-medium'>Passwort erfolgreich geändert</p>}
            <button type='submit' disabled={saving || !currentPw || !newPw || !confirmPw}
              className='w-full py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-700 disabled:opacity-50'>
              {saving ? 'Speichern…' : 'Passwort ändern'}
            </button>
          </form>
        </div>

        {/* Benachrichtigungen */}
        {notifPrefs.length > 0 && (
          <div className='bg-white rounded-xl shadow-sm border border-gray-200 p-6'>
            <h2 className='font-semibold text-gray-700 mb-1'>E-Mail-Benachrichtigungen</h2>
            <p className='text-xs text-gray-400 mb-4'>Lege fest, worüber du per E-Mail informiert werden möchtest.</p>
            <div className='space-y-3'>
              {notifPrefs.map(p => (
                <label key={p.key} className='flex items-center justify-between gap-3 cursor-pointer'>
                  <span className='text-sm text-gray-700'>{p.label}</span>
                  <input type='checkbox' checked={p.enabled}
                    onChange={e => toggleNotif(p.key, e.target.checked)}
                    className='h-4 w-4 accent-blue-600' />
                </label>
              ))}
            </div>
          </div>
        )}
      </div>
    </Layout>
  )
}
