'use client'

import { useState, useMemo } from'react'
import { Search, ChevronDown, ChevronRight, Download } from'lucide-react'
import { AUDIT_SEARCH_PLACEHOLDER } from'@/lib/ui/search-placeholders'
import type { UserSession } from'@/lib/auth/permissions-shared'

export interface AuditEntry {
 id: number
 created_at: string
 actor_id: string | null
 target_user_id: string | null
 action: string
 details: Record<string, unknown> | null
 ip_address: string | null
 actor_display_name?: string | null
 target_display_name?: string | null
 target_email?: string | null
}

interface Props {
 initialEntries: AuditEntry[]
 users: Array<{ id: string; display_name: string; email: string }>
 session: UserSession
}

const PAGE_SIZE = 50

// Action badge color mapping
function getActionBadgeClass(action: string): string {
 const green = ['user.created','login.success','user.reactivated','user.unlocked']
 const blue = ['user.updated','masterdata.imported','masterdata.merge_executed']
 const amber = ['user.role_changed','user.email_changed','password.changed','password.changed_first_login','password.reset_initiated']
 const red = ['user.deleted','user.deactivated','login.failed','user.locked_auto']

 if (green.includes(action)) return'bg-green-100 text-green-800'
 if (blue.includes(action)) return'bg-blue-100 text-blue-800'
 if (amber.includes(action)) return'bg-amber-100 text-amber-800'
 if (red.includes(action)) return'bg-red-100 text-red-800'
 return'bg-muted text-foreground'
}

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

export default function AuditClient({ initialEntries, users }: Props) {
 const [entries, setEntries] = useState<AuditEntry[]>(initialEntries)
 const [search, setSearch] = useState('')
 const [filterActor, setFilterActor] = useState('')
 const [filterTarget, setFilterTarget] = useState('')
 const [filterFrom, setFilterFrom] = useState('')
 const [filterTo, setFilterTo] = useState('')
 const [filterActions, setFilterActions] = useState<string[]>([])
 const [actionDropdownOpen, setActionDropdownOpen] = useState(false)
 const [expandedId, setExpandedId] = useState<number | null>(null)
 const [page, setPage] = useState(1)
 const [loadingMore, setLoadingMore] = useState(false)

 // Unique action types from loaded entries
 const actionTypes = useMemo(() => {
 const set = new Set<string>()
 entries.forEach((e) => set.add(e.action))
 return Array.from(set).sort()
 }, [entries])

 const filtered = useMemo(() => {
 const q = search.toLowerCase()
 return entries.filter((e) => {
 if (filterActions.length > 0 && !filterActions.includes(e.action)) return false
 if (filterActor && e.actor_id !== filterActor) return false
 if (filterTarget && e.target_user_id !== filterTarget) return false
 if (filterFrom && e.created_at < filterFrom) return false
 if (filterTo && e.created_at > filterTo +'T23:59:59') return false
 if (q) {
 const haystack = [
 e.actor_display_name ??'',
 e.target_display_name ??'',
 e.action,
 JSON.stringify(e.details ?? {}),
 ].join('').toLowerCase()
 if (!haystack.includes(q)) return false
 }
 return true
 })
 }, [entries, search, filterActions, filterActor, filterTarget, filterFrom, filterTo])

 const paginated = filtered.slice(0, page * PAGE_SIZE)
 const hasMore = paginated.length < filtered.length

 async function loadMore() {
 if (filtered.length > entries.length) {
 // Still have local pages
 setPage((p) => p + 1)
 return
 }
 setLoadingMore(true)
 const params = new URLSearchParams({
 offset: String(entries.length),
 limit:'50',
 })
 if (filterActions.length > 0) params.set('action', filterActions.join(','))
 if (filterActor) params.set('actorId', filterActor)
 if (filterTarget) params.set('targetUserId', filterTarget)
 if (filterFrom) params.set('from', filterFrom)
 if (filterTo) params.set('to', filterTo)
 if (search) params.set('search', search)

 const res = await fetch(`/api/admin/audit?${params.toString()}`)
 if (res.ok) {
 const data = await res.json() as AuditEntry[]
 setEntries((prev) => [...prev, ...data])
 setPage((p) => p + 1)
 }
 setLoadingMore(false)
 }

 async function exportExcel() {
 const { default: ExcelJS } = await import('exceljs')
 const workbook = new ExcelJS.Workbook()
 const sheet = workbook.addWorksheet('Audit Log')

 sheet.columns = [
 { header:'Zeitpunkt', key:'created_at', width: 20 },
 { header:'Akteur', key:'actor', width: 25 },
 { header:'Aktion', key:'action', width: 30 },
 { header:'Ziel-Benutzer', key:'target', width: 25 },
 { header:'Details', key:'details', width: 40 },
 { header:'IP', key:'ip_address', width: 18 },
 ]

 for (const e of filtered) {
 sheet.addRow({
 created_at: formatDateTime(e.created_at),
 actor: e.actor_display_name ?? e.actor_id ??'—',
 action: e.action,
 target: e.target_display_name ?? e.target_user_id ??'—',
 details: JSON.stringify(e.details ?? {}),
 ip_address: e.ip_address ??'—',
 })
 }

 const buffer = await workbook.xlsx.writeBuffer()
 const blob = new Blob([buffer], { type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
 const url = URL.createObjectURL(blob)
 const a = document.createElement('a')
 a.href = url
 a.download = `audit-log-${new Date().toISOString().slice(0, 10)}.xlsx`
 a.click()
 URL.revokeObjectURL(url)
 }

 function toggleActionFilter(action: string) {
 setFilterActions((prev) =>
 prev.includes(action) ? prev.filter((a) => a !== action) : [...prev, action]
 )
 setPage(1)
 }

 return (
 <div className="space-y-5">
 {/* Header */}
 <div className="flex items-center justify-between gap-4 flex-wrap">
 <div>
 <h1 className="text-xl font-bold text-foreground">Audit Log</h1>
 <p className="text-sm text-muted-foreground mt-0.5">{filtered.length} Einträge</p>
 </div>
 <button
 onClick={() => void exportExcel()}
 className="flex items-center gap-2 h-10 px-4 border border-border bg-card text-foreground rounded-lg text-sm font-medium hover:bg-background transition-colors"
 >
 <Download size={15} />
 Als Excel exportieren
 </button>
 </div>

 {/* Filters */}
 <div className="flex flex-wrap gap-3">
 {/* Search */}
 <div className="relative flex-1 min-w-48">
 <Search size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"/>
 <input
 type="text"
 value={search}
 onChange={(e) => { setSearch(e.target.value); setPage(1) }}
 placeholder={AUDIT_SEARCH_PLACEHOLDER}
 className="w-full h-9 pl-9 pr-3 rounded-lg border border-border bg-card text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary"
 />
 </div>

 {/* Action filter dropdown */}
 <div className="relative">
 <button
 onClick={() => setActionDropdownOpen((o) => !o)}
 className="h-9 px-3 flex items-center gap-2 rounded-lg border border-border bg-card text-sm text-foreground focus:outline-none hover:bg-background"
 >
 Aktionen
 {filterActions.length > 0 && (
 <span className="ml-1 px-1.5 py-0.5 text-xs bg-primary text-white rounded-full">
 {filterActions.length}
 </span>
 )}
 <ChevronDown size={14} />
 </button>
 {actionDropdownOpen && (
 <div className="absolute z-20 top-full mt-1 left-0 bg-card border border-border rounded-lg shadow-lg p-2 min-w-56 max-h-64 overflow-y-auto">
 {actionTypes.map((a) => (
 <label key={a} className="flex items-center gap-2 px-2 py-1.5 hover:bg-background rounded cursor-pointer text-sm text-foreground">
 <input
 type="checkbox"
 checked={filterActions.includes(a)}
 onChange={() => toggleActionFilter(a)}
 className="accent-primary"
 />
 {a}
 </label>
 ))}
 </div>
 )}
 </div>

 {/* Actor filter */}
 <select
 value={filterActor}
 onChange={(e) => { setFilterActor(e.target.value); setPage(1) }}
 className="h-9 px-3 rounded-lg border border-border bg-card text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary"
 >
 <option value="">Alle Akteure</option>
 {users.map((u) => (
 <option key={u.id} value={u.id}>{u.display_name}</option>
 ))}
 </select>

 {/* Target filter */}
 <select
 value={filterTarget}
 onChange={(e) => { setFilterTarget(e.target.value); setPage(1) }}
 className="h-9 px-3 rounded-lg border border-border bg-card text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary"
 >
 <option value="">Alle Ziel-Benutzer</option>
 {users.map((u) => (
 <option key={u.id} value={u.id}>{u.display_name}</option>
 ))}
 </select>

 {/* Date range */}
 <input
 type="date"
 value={filterFrom}
 onChange={(e) => { setFilterFrom(e.target.value); setPage(1) }}
 className="h-9 px-3 rounded-lg border border-border bg-card text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary"
 />
 <input
 type="date"
 value={filterTo}
 onChange={(e) => { setFilterTo(e.target.value); setPage(1) }}
 className="h-9 px-3 rounded-lg border border-border bg-card text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary"
 />
 </div>

 {/* Table */}
 <div className="bg-card rounded-xl border border-border overflow-hidden">
 <div className="overflow-x-auto">
 <table className="w-full text-sm">
 <thead>
 <tr className="border-b border-border bg-background">
 <th className="w-6 px-4 py-3"/>
 <th className="text-left px-4 py-3 font-semibold text-muted-foreground text-xs uppercase tracking-wider">Zeitpunkt</th>
 <th className="text-left px-4 py-3 font-semibold text-muted-foreground text-xs uppercase tracking-wider">Akteur</th>
 <th className="text-left px-4 py-3 font-semibold text-muted-foreground text-xs uppercase tracking-wider">Aktion</th>
 <th className="text-left px-4 py-3 font-semibold text-muted-foreground text-xs uppercase tracking-wider hidden md:table-cell">Ziel-Benutzer</th>
 <th className="text-left px-4 py-3 font-semibold text-muted-foreground text-xs uppercase tracking-wider hidden lg:table-cell">Details</th>
 <th className="text-left px-4 py-3 font-semibold text-muted-foreground text-xs uppercase tracking-wider hidden xl:table-cell">IP</th>
 </tr>
 </thead>
 <tbody className="divide-y divide-border">
 {paginated.length === 0 && (
 <tr>
 <td colSpan={7} className="px-4 py-10 text-center text-muted-foreground text-sm">
 Keine Einträge gefunden.
 </td>
 </tr>
 )}
 {paginated.map((entry) => {
 const isExpanded = expandedId === entry.id
 return (
 <>
 <tr
 key={entry.id}
 className="hover:bg-background transition-colors cursor-pointer"
 onClick={() => setExpandedId(isExpanded ? null : entry.id)}
 >
 <td className="px-4 py-3 text-muted-foreground">
 {isExpanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
 </td>
 <td className="px-4 py-3 text-foreground whitespace-nowrap font-mono text-xs">
 {formatDateTime(entry.created_at)}
 </td>
 <td className="px-4 py-3 text-foreground">
 {entry.actor_display_name ?? <span className="text-muted-foreground">System</span>}
 </td>
 <td className="px-4 py-3">
 <span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${getActionBadgeClass(entry.action)}`}>
 {entry.action}
 </span>
 </td>
 <td className="px-4 py-3 text-foreground hidden md:table-cell">
 {entry.target_display_name ?? <span className="text-muted-foreground">—</span>}
 {entry.target_email && (
 <p className="text-xs text-muted-foreground">{entry.target_email}</p>
 )}
 </td>
 <td className="px-4 py-3 text-muted-foreground hidden lg:table-cell max-w-xs truncate">
 {entry.details ? JSON.stringify(entry.details).slice(0, 80) :'—'}
 </td>
 <td className="px-4 py-3 text-muted-foreground hidden xl:table-cell font-mono text-xs">
 {entry.ip_address ??'—'}
 </td>
 </tr>
 {isExpanded && (
 <tr key={`${entry.id}-expanded`} className="bg-background">
 <td colSpan={7} className="px-6 py-4">
 <pre className="text-xs text-foreground bg-card border border-border rounded-lg p-4 overflow-x-auto font-mono whitespace-pre-wrap">
 {JSON.stringify(entry.details, null, 2)}
 </pre>
 </td>
 </tr>
 )}
 </>
 )
 })}
 </tbody>
 </table>
 </div>
 </div>

 {/* Load more */}
 {hasMore && (
 <div className="flex justify-center">
 <button
 onClick={() => void loadMore()}
 disabled={loadingMore}
 className="h-10 px-6 border border-border bg-card text-foreground rounded-lg text-sm font-medium hover:bg-background disabled:opacity-50 transition-colors"
 >
 {loadingMore ?'Laden…':'Mehr laden'}
 </button>
 </div>
 )}
 </div>
 )
}
