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

// ── Types ────────────────────────────────────────────────────────────────────

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

interface AuditEntry {
  id: string
  user_id: string | null
  user_name: string | null
  action: string
  entity_type: string | null
  entity_id: string | null
  old_value: Record<string, unknown> | null
  new_value: Record<string, unknown> | null
  ip_address: string | null
  created_at: string
}

interface AuditListResponse { total: number; items: AuditEntry[] }

interface UserItem { id: string; full_name: string }

// ── Helpers ───────────────────────────────────────────────────────────────────

function formatTs(iso: string) {
  const d = new Date(iso)
  return d.toLocaleString('de-DE', {
    day: '2-digit', month: '2-digit', year: 'numeric',
    hour: '2-digit', minute: '2-digit', second: '2-digit',
  })
}

function actionBadgeColor(action: string) {
  if (action.includes('delete') || action.includes('cancel') || action.includes('reject') || action.includes('revoke'))
    return 'bg-red-100 text-red-700'
  if (action.includes('create') || action.includes('invite') || action.includes('register') || action.includes('approve'))
    return 'bg-green-100 text-green-700'
  if (action.includes('update') || action.includes('change') || action.includes('rotate') || action.includes('reset'))
    return 'bg-yellow-100 text-yellow-700'
  return 'bg-gray-100 text-gray-600'
}

function JsonBlock({ label, val }: { label: string; val: Record<string, unknown> | null }) {
  if (!val) return <span className='text-gray-400 italic text-xs'>–</span>
  return (
    <div>
      <p className='text-xs font-semibold text-gray-500 mb-1'>{label}</p>
      <pre className='text-xs bg-gray-50 border border-gray-200 rounded p-2 overflow-auto max-h-40 whitespace-pre-wrap break-all'>
        {JSON.stringify(val, null, 2)}
      </pre>
    </div>
  )
}

const PAGE_SIZE = 50

// ── Component ─────────────────────────────────────────────────────────────────

export function AuditLogPage() {
  const [me, setMe] = useState<Me | null>(null)
  const [entries, setEntries] = useState<AuditEntry[]>([])
  const [total, setTotal] = useState(0)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')

  // Filters
  const [filterUser, setFilterUser] = useState('')
  const [filterAction, setFilterAction] = useState('')
  const [filterEntity, setFilterEntity] = useState('')
  const [filterFrom, setFilterFrom] = useState('')
  const [filterTo, setFilterTo] = useState('')
  const [offset, setOffset] = useState(0)

  // Filter-Options
  const [users, setUsers] = useState<UserItem[]>([])
  const [actions, setActions] = useState<string[]>([])
  const [entityTypes, setEntityTypes] = useState<string[]>([])

  // Detail-Expand
  const [expanded, setExpanded] = useState<string | null>(null)

  const load = useCallback(async (off = 0) => {
    setLoading(true)
    setError('')
    try {
      const params = new URLSearchParams()
      params.set('limit', String(PAGE_SIZE))
      params.set('offset', String(off))
      if (filterUser)   params.set('user_id', filterUser)
      if (filterAction) params.set('action', filterAction)
      if (filterEntity) params.set('entity_type', filterEntity)
      if (filterFrom)   params.set('date_from', new Date(filterFrom).toISOString())
      if (filterTo)     params.set('date_to', new Date(filterTo + 'T23:59:59').toISOString())

      const data = await api.get<AuditListResponse>(`/audit-logs?${params}`)
      setEntries(data.items)
      setTotal(data.total)
      setOffset(off)
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : 'Fehler beim Laden')
    } finally {
      setLoading(false)
    }
  }, [filterUser, filterAction, filterEntity, filterFrom, filterTo])

  useEffect(() => {
    Promise.all([
      api.get<Me>('/auth/me'),
      api.get<{ items: UserItem[]; total: number }>('/users').catch(() => ({ items: [], total: 0 })),
      api.get<string[]>('/audit-logs/actions').catch(() => []),
      api.get<string[]>('/audit-logs/entity-types').catch(() => []),
    ]).then(([meData, usersData, actionsData, entitiesData]) => {
      setMe(meData)
      setUsers(usersData.items)
      setActions(actionsData)
      setEntityTypes(entitiesData)
    })
  }, [])

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

  // ── CSV-Export ──────────────────────────────────────────────────────────────

  async function exportCsv() {
    // Alle Seiten laden (max 5000)
    const params = new URLSearchParams()
    params.set('limit', '5000')
    params.set('offset', '0')
    if (filterUser)   params.set('user_id', filterUser)
    if (filterAction) params.set('action', filterAction)
    if (filterEntity) params.set('entity_type', filterEntity)
    if (filterFrom)   params.set('date_from', new Date(filterFrom).toISOString())
    if (filterTo)     params.set('date_to', new Date(filterTo + 'T23:59:59').toISOString())

    try {
      const data = await api.get<AuditListResponse>(`/audit-logs?${params}`)
      const header = ['Zeitstempel', 'Benutzer', 'Aktion', 'Entity-Typ', 'Entity-ID', 'IP', 'Alt', 'Neu']
      const rows = data.items.map(e => [
        formatTs(e.created_at),
        e.user_name ?? '',
        e.action,
        e.entity_type ?? '',
        e.entity_id ?? '',
        e.ip_address ?? '',
        e.old_value ? JSON.stringify(e.old_value) : '',
        e.new_value ? JSON.stringify(e.new_value) : '',
      ])
      const csv = [header, ...rows]
        .map(r => r.map(v => `"${String(v).replace(/"/g, '""')}"`).join(';'))
        .join('\n')
      const blob = new Blob(['﻿' + csv], { type: 'text/csv;charset=utf-8;' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `audit-log-${new Date().toISOString().slice(0, 10)}.csv`
      a.click()
      URL.revokeObjectURL(url)
    } catch (e: unknown) {
      alert(e instanceof Error ? e.message : 'Export fehlgeschlagen')
    }
  }

  // ── Render ──────────────────────────────────────────────────────────────────

  const inputClass = 'border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500'

  const totalPages = Math.ceil(total / PAGE_SIZE)
  const currentPage = Math.floor(offset / PAGE_SIZE) + 1

  return (
    <Layout userRole={me?.role ?? ''} userName={me ? `${me.first_name} ${me.last_name}` : ''}>
      <div className='p-6 max-w-screen-xl mx-auto'>

        {/* Header */}
        <div className='flex items-center justify-between mb-6'>
          <div>
            <h1 className='text-2xl font-bold text-gray-900'>Audit-Log</h1>
            <p className='text-sm text-gray-500 mt-0.5'>
              Alle sicherheitsrelevanten Aktionen im System
            </p>
          </div>
          <button
            onClick={exportCsv}
            className='flex items-center gap-2 px-4 py-2 bg-white border border-gray-300 rounded-lg text-sm font-medium hover:bg-gray-50'
          >
            <svg className='w-4 h-4' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
              <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2}
                d='M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4' />
            </svg>
            CSV exportieren
          </button>
        </div>

        {/* Filter */}
        <div className='bg-white rounded-xl border border-gray-200 p-4 mb-6'>
          <div className='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3'>

            <div>
              <label className='block text-xs font-medium text-gray-600 mb-1'>Benutzer</label>
              <select value={filterUser} onChange={e => setFilterUser(e.target.value)} className={inputClass + ' w-full'}>
                <option value=''>Alle</option>
                {users.map(u => (
                  <option key={u.id} value={u.id}>{u.full_name}</option>
                ))}
              </select>
            </div>

            <div>
              <label className='block text-xs font-medium text-gray-600 mb-1'>Aktion</label>
              <select value={filterAction} onChange={e => setFilterAction(e.target.value)} className={inputClass + ' w-full'}>
                <option value=''>Alle</option>
                {actions.map(a => (
                  <option key={a} value={a}>{a}</option>
                ))}
              </select>
            </div>

            <div>
              <label className='block text-xs font-medium text-gray-600 mb-1'>Entity-Typ</label>
              <select value={filterEntity} onChange={e => setFilterEntity(e.target.value)} className={inputClass + ' w-full'}>
                <option value=''>Alle</option>
                {entityTypes.map(t => (
                  <option key={t} value={t}>{t}</option>
                ))}
              </select>
            </div>

            <div>
              <label className='block text-xs font-medium text-gray-600 mb-1'>Von</label>
              <input type='date' value={filterFrom} onChange={e => setFilterFrom(e.target.value)} className={inputClass + ' w-full'} />
            </div>

            <div>
              <label className='block text-xs font-medium text-gray-600 mb-1'>Bis</label>
              <input type='date' value={filterTo} onChange={e => setFilterTo(e.target.value)} className={inputClass + ' w-full'} />
            </div>
          </div>

          <div className='flex gap-2 mt-3'>
            <button
              onClick={() => load(0)}
              className='px-4 py-1.5 bg-blue-600 text-white text-sm rounded-md hover:bg-blue-700'
            >
              Filtern
            </button>
            <button
              onClick={() => {
                setFilterUser(''); setFilterAction(''); setFilterEntity('')
                setFilterFrom(''); setFilterTo('')
              }}
              className='px-4 py-1.5 bg-gray-100 text-gray-700 text-sm rounded-md hover:bg-gray-200'
            >
              Zurücksetzen
            </button>
          </div>
        </div>

        {/* Table */}
        {error && (
          <div className='bg-red-50 border border-red-200 text-red-700 rounded-lg px-4 py-3 mb-4 text-sm'>{error}</div>
        )}

        <div className='bg-white rounded-xl border border-gray-200 overflow-hidden'>
          <div className='px-4 py-3 border-b border-gray-100 flex items-center justify-between'>
            <span className='text-sm text-gray-500'>{total.toLocaleString('de-DE')} Einträge gesamt</span>
            {loading && <Spinner />}
          </div>

          <div className='overflow-x-auto'>
            <table className='w-full text-sm'>
              <thead className='bg-gray-50 border-b border-gray-200'>
                <tr>
                  <th className='px-4 py-3 text-left font-medium text-gray-600 whitespace-nowrap'>Zeitstempel</th>
                  <th className='px-4 py-3 text-left font-medium text-gray-600'>Benutzer</th>
                  <th className='px-4 py-3 text-left font-medium text-gray-600'>Aktion</th>
                  <th className='px-4 py-3 text-left font-medium text-gray-600'>Objekt</th>
                  <th className='px-4 py-3 text-left font-medium text-gray-600'>IP</th>
                  <th className='px-4 py-3 text-left font-medium text-gray-600 w-8'></th>
                </tr>
              </thead>
              <tbody className='divide-y divide-gray-100'>
                {entries.length === 0 && !loading && (
                  <tr>
                    <td colSpan={6} className='px-4 py-8 text-center text-gray-400'>
                      Keine Einträge gefunden
                    </td>
                  </tr>
                )}
                {entries.map(e => (
                  <Fragment key={e.id}>
                    <tr
                      className='hover:bg-gray-50 cursor-pointer'
                      onClick={() => setExpanded(expanded === e.id ? null : e.id)}
                    >
                      <td className='px-4 py-3 text-gray-500 whitespace-nowrap font-mono text-xs'>
                        {formatTs(e.created_at)}
                      </td>
                      <td className='px-4 py-3 text-gray-900'>
                        {e.user_name ?? <span className='text-gray-400 italic'>System</span>}
                      </td>
                      <td className='px-4 py-3'>
                        <span className={`inline-flex px-2 py-0.5 rounded-full text-xs font-medium ${actionBadgeColor(e.action)}`}>
                          {e.action}
                        </span>
                      </td>
                      <td className='px-4 py-3 text-gray-600'>
                        {e.entity_type && (
                          <span className='font-medium'>{e.entity_type}</span>
                        )}
                        {e.entity_id && (
                          <span className='text-gray-400 text-xs ml-1 font-mono'>
                            {e.entity_id.slice(0, 8)}…
                          </span>
                        )}
                      </td>
                      <td className='px-4 py-3 text-gray-500 font-mono text-xs'>
                        {e.ip_address ?? '–'}
                      </td>
                      <td className='px-4 py-3 text-gray-400'>
                        {(e.old_value || e.new_value) && (
                          <svg
                            className={`w-4 h-4 transition-transform ${expanded === e.id ? 'rotate-90' : ''}`}
                            fill='none' stroke='currentColor' viewBox='0 0 24 24'
                          >
                            <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M9 5l7 7-7 7' />
                          </svg>
                        )}
                      </td>
                    </tr>

                    {expanded === e.id && (e.old_value || e.new_value) && (
                      <tr className='bg-gray-50'>
                        <td colSpan={6} className='px-6 py-4'>
                          <div className='grid grid-cols-1 md:grid-cols-2 gap-4'>
                            <JsonBlock label='Vorher' val={e.old_value} />
                            <JsonBlock label='Nachher' val={e.new_value} />
                          </div>
                        </td>
                      </tr>
                    )}
                  </Fragment>
                ))}
              </tbody>
            </table>
          </div>

          {/* Pagination */}
          {totalPages > 1 && (
            <div className='px-4 py-3 border-t border-gray-100 flex items-center justify-between'>
              <span className='text-sm text-gray-500'>
                Seite {currentPage} von {totalPages}
              </span>
              <div className='flex gap-2'>
                <button
                  disabled={offset === 0}
                  onClick={() => load(Math.max(0, offset - PAGE_SIZE))}
                  className='px-3 py-1 text-sm border border-gray-300 rounded-md disabled:opacity-40 hover:bg-gray-50'
                >
                  ← Zurück
                </button>
                <button
                  disabled={offset + PAGE_SIZE >= total}
                  onClick={() => load(offset + PAGE_SIZE)}
                  className='px-3 py-1 text-sm border border-gray-300 rounded-md disabled:opacity-40 hover:bg-gray-50'
                >
                  Weiter →
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    </Layout>
  )
}
