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

interface Me {
  first_name: string
  last_name: string
  role: string
}

interface LdapConfig {
  id: string
  enabled: boolean
  host: string
  port: number
  use_ssl: boolean
  use_tls: boolean
  bind_dn: string
  base_dn: string
  user_search_filter: string
  attr_email: string
  attr_firstname: string
  attr_lastname: string
  attr_username: string
  attr_department: string | null
  last_sync_at: string | null
}

interface LdapUserPreview {
  dn: string
  email: string
  first_name: string
  last_name: string
  department: string | null
}

interface SyncResult {
  created: number
  updated: number
  deactivated: number
  errors: string[]
}

type FormState = {
  host: string
  port: string
  use_ssl: boolean
  use_tls: boolean
  bind_dn: string
  bind_password: string
  base_dn: string
  user_search_filter: string
  attr_email: string
  attr_firstname: string
  attr_lastname: string
  attr_username: string
  attr_department: string
  enabled: boolean
}

const DEFAULTS: FormState = {
  host: '', port: '389', use_ssl: false, use_tls: false,
  bind_dn: '', bind_password: '', base_dn: '',
  user_search_filter: '(objectClass=person)',
  attr_email: 'mail', attr_firstname: 'givenName',
  attr_lastname: 'sn', attr_username: 'sAMAccountName',
  attr_department: '', enabled: false,
}

function configToForm(c: LdapConfig): FormState {
  return {
    host: c.host, port: String(c.port),
    use_ssl: c.use_ssl, use_tls: c.use_tls,
    bind_dn: c.bind_dn, bind_password: '',
    base_dn: c.base_dn, user_search_filter: c.user_search_filter,
    attr_email: c.attr_email, attr_firstname: c.attr_firstname,
    attr_lastname: c.attr_lastname, attr_username: c.attr_username,
    attr_department: c.attr_department ?? '', enabled: c.enabled,
  }
}

export function LdapSettingsPage() {
  const [me, setMe]             = useState<Me | null>(null)
  const [config, setConfig]     = useState<LdapConfig | null>(null)
  const [form, setForm]         = useState<FormState>(DEFAULTS)
  const [loading, setLoading]   = useState(true)
  const [saving, setSaving]     = useState(false)
  const [saveMsg, setSaveMsg]   = useState('')
  const [saveErr, setSaveErr]   = useState('')

  const [testing, setTesting]   = useState(false)
  const [testMsg, setTestMsg]   = useState('')
  const [testOk, setTestOk]     = useState<boolean | null>(null)

  const [previewing, setPreviewing] = useState(false)
  const [preview, setPreview]       = useState<LdapUserPreview[] | null>(null)

  const [syncing, setSyncing]       = useState(false)
  const [syncResult, setSyncResult] = useState<SyncResult | null>(null)

  async function load() {
    try {
      const [meData, cfgData] = await Promise.all([
        api.get<Me>('/auth/me'),
        api.get<LdapConfig | null>('/ldap/config'),
      ])
      setMe(meData)
      if (cfgData) {
        setConfig(cfgData)
        setForm(configToForm(cfgData))
      }
    } catch (e: unknown) {
      console.error(e)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => { load() }, [])

  function upd(field: keyof FormState) {
    return (e: React.ChangeEvent<HTMLInputElement>) =>
      setForm(f => ({ ...f, [field]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }))
  }

  async function handleSave() {
    setSaveMsg(''); setSaveErr(''); setSaving(true)
    try {
      const payload: Record<string, unknown> = {
        ...form,
        port: parseInt(form.port),
        attr_department: form.attr_department || null,
      }
      if (!form.bind_password) delete payload.bind_password
      if (config) {
        await api.patch('/ldap/config', payload)
      } else {
        await api.post('/ldap/config', payload)
      }
      setSaveMsg('Gespeichert.')
      load()
    } catch (e: unknown) {
      setSaveErr(e instanceof Error ? e.message : 'Fehler')
    } finally {
      setSaving(false)
    }
  }

  async function handleTest() {
    setTesting(true); setTestMsg(''); setTestOk(null)
    try {
      const res = await api.post<{ success: boolean; message: string }>('/ldap/test', {})
      setTestOk(res.success)
      setTestMsg(res.message)
    } catch (e: unknown) {
      setTestOk(false)
      setTestMsg(e instanceof Error ? e.message : 'Fehler')
    } finally {
      setTesting(false)
    }
  }

  async function handlePreview() {
    setPreviewing(true); setPreview(null)
    try {
      const data = await api.get<LdapUserPreview[]>('/ldap/preview')
      setPreview(data)
    } catch (e: unknown) {
      alert(e instanceof Error ? e.message : 'Fehler')
    } finally {
      setPreviewing(false)
    }
  }

  async function handleSync() {
    if (!confirm('LDAP-Benutzer synchronisieren? Neue Benutzer werden angelegt, nicht gefundene deaktiviert.')) return
    setSyncing(true); setSyncResult(null)
    try {
      const res = await api.post<SyncResult>('/ldap/sync', { default_role: 'EMPLOYEE' })
      setSyncResult(res)
    } catch (e: unknown) {
      alert(e instanceof Error ? e.message : 'Fehler')
    } finally {
      setSyncing(false)
    }
  }

  const inputClass = 'w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent'
  const labelClass = 'block text-xs font-medium text-gray-700 mb-1'

  if (loading) return (
    <div className='min-h-screen bg-gray-50 flex items-center justify-center'><Spinner /></div>
  )

  return (
    <Layout userRole={me?.role ?? ''} userName={`${me?.first_name} ${me?.last_name}`}>
      <div className='max-w-2xl space-y-6'>
        <div>
          <h1 className='text-xl font-bold text-gray-800'>LDAP-Anbindung</h1>
          <p className='text-sm text-gray-500 mt-0.5'>
            Verbindet TimeMaster mit einem ActiveDirectory oder OpenLDAP-Server.
          </p>
        </div>

        {/* Status Banner */}
        <div className={`flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium border ${
          config?.enabled
            ? 'bg-green-50 text-green-700 border-green-200'
            : 'bg-gray-100 text-gray-600 border-gray-200'
        }`}>
          <span className={`h-2 w-2 rounded-full flex-shrink-0 ${config?.enabled ? 'bg-green-500' : 'bg-gray-400'}`} />
          {config?.enabled ? 'LDAP aktiv' : 'LDAP deaktiviert'}
          {config?.last_sync_at && (
            <span className='ml-auto text-xs font-normal'>
              Letzter Sync: {new Date(config.last_sync_at).toLocaleString('de-DE')}
            </span>
          )}
        </div>

        {/* Form */}
        <div className='bg-white rounded-xl border border-gray-100 shadow-sm p-6 space-y-4'>
          <h2 className='text-sm font-semibold text-gray-700'>Server-Konfiguration</h2>

          <div className='flex gap-3'>
            <div className='flex-1'>
              <label className={labelClass}>Host *</label>
              <input value={form.host} onChange={upd('host')} className={inputClass} placeholder='ldap.firma.de' />
            </div>
            <div className='w-24'>
              <label className={labelClass}>Port</label>
              <input value={form.port} onChange={upd('port')} className={inputClass} placeholder='389' />
            </div>
          </div>

          <div className='flex gap-6'>
            <label className='flex items-center gap-2 text-sm text-gray-700 cursor-pointer'>
              <input type='checkbox' checked={form.use_ssl} onChange={upd('use_ssl')} className='rounded' />
              SSL (LDAPS)
            </label>
            <label className='flex items-center gap-2 text-sm text-gray-700 cursor-pointer'>
              <input type='checkbox' checked={form.use_tls} onChange={upd('use_tls')} className='rounded' />
              STARTTLS
            </label>
            <label className='flex items-center gap-2 text-sm text-gray-700 cursor-pointer'>
              <input type='checkbox' checked={form.enabled} onChange={upd('enabled')} className='rounded' />
              Aktiviert
            </label>
          </div>

          <div>
            <label className={labelClass}>Bind DN *</label>
            <input value={form.bind_dn} onChange={upd('bind_dn')} className={inputClass}
              placeholder='cn=service,dc=firma,dc=de' />
          </div>
          <div>
            <label className={labelClass}>Bind Passwort {config ? '(leer lassen = unverändert)' : '*'}</label>
            <input type='password' value={form.bind_password} onChange={upd('bind_password')} className={inputClass} />
          </div>
          <div>
            <label className={labelClass}>Base DN *</label>
            <input value={form.base_dn} onChange={upd('base_dn')} className={inputClass}
              placeholder='ou=users,dc=firma,dc=de' />
          </div>
          <div>
            <label className={labelClass}>Suchfilter</label>
            <input value={form.user_search_filter} onChange={upd('user_search_filter')} className={inputClass} />
          </div>

          <h2 className='text-sm font-semibold text-gray-700 pt-2'>Attribut-Mapping</h2>
          <div className='grid grid-cols-2 gap-3'>
            {([
              ['attr_email', 'E-Mail Attribut'],
              ['attr_firstname', 'Vorname Attribut'],
              ['attr_lastname', 'Nachname Attribut'],
              ['attr_username', 'Benutzername Attribut'],
              ['attr_department', 'Abteilung Attribut (optional)'],
            ] as [keyof FormState, string][]).map(([field, label]) => (
              <div key={field}>
                <label className={labelClass}>{label}</label>
                <input value={form[field] as string} onChange={upd(field)} className={inputClass} />
              </div>
            ))}
          </div>

          {saveErr && <p className='text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2'>{saveErr}</p>}
          {saveMsg && <p className='text-sm text-green-700 bg-green-50 border border-green-200 rounded px-3 py-2'>{saveMsg}</p>}

          <div className='flex gap-2 pt-2'>
            <button
              onClick={handleSave}
              disabled={saving}
              className='px-4 py-2 text-sm font-semibold text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50 transition-colors'
            >
              {saving ? 'Speichere…' : config ? 'Aktualisieren' : 'Konfiguration speichern'}
            </button>
          </div>
        </div>

        {/* Test + Sync (only if config exists) */}
        {config && (
          <div className='bg-white rounded-xl border border-gray-100 shadow-sm p-6 space-y-4'>
            <h2 className='text-sm font-semibold text-gray-700'>Verbindung & Synchronisation</h2>

            <div className='flex flex-wrap gap-2'>
              <button
                onClick={handleTest}
                disabled={testing}
                className='px-4 py-2 text-sm font-medium border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50 transition-colors'
              >
                {testing ? 'Teste…' : 'Verbindung testen'}
              </button>
              <button
                onClick={handlePreview}
                disabled={previewing}
                className='px-4 py-2 text-sm font-medium border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50 transition-colors'
              >
                {previewing ? 'Lädt…' : 'Vorschau (50 Benutzer)'}
              </button>
              <button
                onClick={handleSync}
                disabled={syncing}
                className='px-4 py-2 text-sm font-semibold text-white bg-green-600 rounded-lg hover:bg-green-700 disabled:opacity-50 transition-colors'
              >
                {syncing ? 'Synchronisiere…' : 'Jetzt synchronisieren'}
              </button>
            </div>

            {testMsg && (
              <div className={`text-sm px-3 py-2 rounded border ${
                testOk ? 'text-green-700 bg-green-50 border-green-200' : 'text-red-700 bg-red-50 border-red-200'
              }`}>
                {testOk ? '✓ ' : '✗ '}{testMsg}
              </div>
            )}

            {syncResult && (
              <div className='text-sm bg-blue-50 border border-blue-200 rounded px-3 py-2 space-y-1'>
                <p className='font-medium text-blue-800'>Sync abgeschlossen</p>
                <p className='text-blue-700'>Erstellt: {syncResult.created} · Aktualisiert: {syncResult.updated} · Deaktiviert: {syncResult.deactivated}</p>
                {syncResult.errors.length > 0 && (
                  <p className='text-red-600'>Fehler: {syncResult.errors.join(', ')}</p>
                )}
              </div>
            )}

            {preview && (
              <div className='overflow-hidden rounded-lg border border-gray-200'>
                <div className='px-3 py-2 bg-gray-50 border-b border-gray-200 text-xs font-medium text-gray-600'>
                  {preview.length} Benutzer gefunden
                </div>
                <div className='overflow-x-auto max-h-64'>
                  <table className='w-full text-xs'>
                    <thead className='bg-gray-50 text-gray-500'>
                      <tr>
                        {['E-Mail', 'Vorname', 'Nachname', 'DN'].map(h => (
                          <th key={h} className='px-3 py-2 text-left font-medium'>{h}</th>
                        ))}
                      </tr>
                    </thead>
                    <tbody className='divide-y divide-gray-100'>
                      {preview.map((u, i) => (
                        <tr key={i} className='hover:bg-gray-50'>
                          <td className='px-3 py-1.5 text-gray-700'>{u.email}</td>
                          <td className='px-3 py-1.5 text-gray-600'>{u.first_name}</td>
                          <td className='px-3 py-1.5 text-gray-600'>{u.last_name}</td>
                          <td className='px-3 py-1.5 text-gray-400 font-mono truncate max-w-xs'>{u.dn}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    </Layout>
  )
}
