'use client'

import { useEffect, useMemo, useState } from 'react'
import type { FormEvent, ReactNode } from 'react'
import { BarChart3, ChevronRight, CircleHelp, FileText, LayoutDashboard, Mail, Menu, Settings, ShieldCheck, Users, X } from 'lucide-react'
import { djangoUrl } from '@/lib/site-content'
import type { DashboardData } from '@/components/admin-dashboard'
import { DashboardToast, type DashboardToastMessage } from '@/components/dashboard-toast'
import { DashboardLogoutButton, DashboardProfileMenu } from '@/components/dashboard-profile-menu'

export type ManagementField = {
  name: string
  label: string
  type: string
  required: boolean
  helpText: string
  choices: Array<{ value: string; label: string }>
  initial: string | string[] | boolean | null
}

export type ManagementData = {
  kind: string
  label?: string
  singular?: string
  fields?: ManagementField[]
  values?: Record<string, unknown>
  items?: Array<Record<string, any>>
  sections?: Array<{ key: string; label: string; count: number; canChange: boolean; canDelete?: boolean; items: Array<Record<string, any>> }>
  canAdd?: boolean
  canChange?: boolean
  canDelete?: boolean
}

const iconFor = (key: string) => {
  if (key === 'dashboard') return LayoutDashboard
  if (key === 'messages') return Mail
  if (key === 'requests') return FileText
  if (key === 'users') return Users
  if (key === 'settings') return Settings
  if (key === 'faqs') return CircleHelp
  return BarChart3
}

function currentArea(path: string[]) {
  return path[0] === 'content' ? path[1] || '' : path[0] || ''
}

function pageTitle(path: string[], data: ManagementData | null) {
  if (data?.label) return data.label
  if (path[0] === 'content') return ({ news: 'News', projects: 'Projects', faqs: 'Questions & answers', partners: 'Partners' } as Record<string, string>)[path[1]] || 'Content'
  if (path[0] === 'messages') return 'Public messages'
  if (path[0] === 'requests') return 'Requests'
  if (path[0] === 'users') return 'Users'
  if (path[0] === 'settings') return 'Settings'
  return 'Dashboard'
}

function apiUrl(resource: string) {
  return djangoUrl('/api/dashboard/manage/' + resource + '/')
}

async function dashboardFetch(resource: string, init: RequestInit = {}) {
  const method = (init.method || 'GET').toUpperCase()
  const headers = new Headers(init.headers)
  headers.set('Accept', 'application/json')
  if (method !== 'GET' && method !== 'HEAD') {
    const csrfResponse = await fetch(djangoUrl('/csrf/'), { credentials: 'include', cache: 'no-store' })
    if (!csrfResponse.ok) throw new Error('Unable to prepare the dashboard action. Refresh the page and try again.')
    const csrfPayload = await csrfResponse.json() as { csrfToken?: string }
    if (!csrfPayload.csrfToken) throw new Error('The dashboard security token is missing. Refresh the page and try again.')
    headers.set('X-CSRFToken', csrfPayload.csrfToken)
  }
  if (!(typeof FormData !== 'undefined' && init.body instanceof FormData)) headers.set('Content-Type', 'application/json')
  const response = await fetch(apiUrl(resource), { ...init, headers, credentials: 'include', cache: 'no-store' })
  const payload = await response.json().catch(() => ({}))
  if (!response.ok) {
    const error = new Error(typeof payload.detail === 'string' ? payload.detail : 'The dashboard request failed.') as Error & { fieldErrors?: Record<string, unknown> }
    error.fieldErrors = payload.errors
    throw error
  }
  return payload
}

function DeleteAction({ resource, id, label, onError }: { resource: string; id: string | number; label: string; onError: (message: string) => void }) {
  const [deleting, setDeleting] = useState(false)
  const remove = async () => {
    if (deleting || !window.confirm('Delete this ' + label + '?')) return
    setDeleting(true)
    try {
      await dashboardFetch(resource + '/' + id, { method: 'DELETE' })
      window.location.reload()
    } catch (reason) {
      onError(reason instanceof Error ? reason.message : 'Unable to delete this ' + label + '.')
      setDeleting(false)
    }
  }
  return <button type="button" disabled={deleting} onClick={remove} className="rounded-lg bg-red-600 px-3 py-2 text-xs font-bold text-white transition hover:bg-red-700 disabled:cursor-wait disabled:opacity-60">{deleting ? 'Deleting...' : 'Delete'}</button>
}

function DashboardChrome({ data, path, title, toast, onCloseToast, children }: { data: DashboardData; path: string[]; title: string; toast: DashboardToastMessage | null; onCloseToast: () => void; children: ReactNode }) {
  const [menuOpen, setMenuOpen] = useState(false)
  const selected = currentArea(path)
  return <div className="min-h-screen bg-[var(--paper)] text-[var(--navy)]">
    <aside className={'fixed inset-y-0 left-0 z-50 flex w-64 flex-col bg-[var(--navy)] px-4 py-6 text-white shadow-2xl transition-transform lg:translate-x-0 ' + (menuOpen ? 'translate-x-0' : '-translate-x-full')}>
      <div className="flex items-center justify-between px-2"><a href="/dashboard" className="flex items-center gap-3" aria-label="RG Admin Panel"><span className="grid size-10 place-items-center rounded-xl border border-[var(--aqua)]/40 bg-[var(--aqua)]/15 text-sm font-black">RG</span><span className="font-display text-xl font-semibold leading-none">Admin Panel</span></a><button type="button" className="rounded-lg p-2 text-white/70 hover:bg-white/10 lg:hidden" onClick={() => setMenuOpen(false)} aria-label="Close navigation"><X size={20} /></button></div>
      <nav className="mt-10 grid gap-1" aria-label="RG Admin Panel navigation">{data.navigation.map((item) => { const Icon = iconFor(item.key); return <a key={item.key} href={item.url} className={'group flex items-center gap-3 rounded-xl px-3 py-3 text-sm font-semibold transition hover:bg-white/10 ' + (item.key === selected ? 'bg-white/15 text-white' : 'text-white/70')}><Icon size={18} className="shrink-0 text-[var(--aqua)]" /><span className="flex-1">{item.label}</span><ChevronRight size={15} className="opacity-0 transition group-hover:opacity-100" /></a> })}</nav>
      <div className="mt-auto rounded-2xl border border-white/10 bg-white/5 p-4"><p className="text-[10px] font-black uppercase tracking-[.18em] text-[var(--aqua)]">Signed in as</p><p className="mt-2 truncate text-sm font-bold">{data.user.name}</p><p className="mt-1 truncate text-xs text-white/55">{data.user.roles.join(' - ') || (data.user.isStaff ? 'Administrator' : 'Dashboard user')}</p></div>
    </aside>
    {menuOpen && <button type="button" className="fixed inset-0 z-40 bg-[var(--navy)]/40 lg:hidden" onClick={() => setMenuOpen(false)} aria-label="Close navigation overlay" />}
    <div className="lg:pl-64"><DashboardToast toast={toast} onClose={onCloseToast} /><header className="sticky top-0 z-30 flex min-h-20 items-center justify-between border-b border-[var(--line)] bg-[var(--paper)]/90 px-5 py-3 backdrop-blur-xl sm:px-8"><div className="flex items-center gap-3"><button type="button" className="rounded-xl border border-[var(--line)] bg-white p-2 text-[var(--navy)] lg:hidden" onClick={() => setMenuOpen(true)} aria-label="Open navigation"><Menu size={20} /></button><div><p className="eyebrow">RG Admin Panel</p><h1 className="font-display text-xl font-semibold sm:text-2xl">{title}</h1></div></div><DashboardProfileMenu name={data.user.name} email={data.user.email} roles={data.user.roles} /></header><main className="mx-auto max-w-[1500px] space-y-7 px-5 py-7 sm:px-8 lg:px-10">{children}<footer className="flex flex-col justify-between gap-3 border-t border-[var(--line)] pt-5 text-xs text-[var(--ink-soft)] sm:flex-row"><span>RG Admin Panel - Permission-aware dashboard</span><DashboardLogoutButton /></footer></main></div>
  </div>
}

function FormPanel({ resource, data, onSaved, onError }: { resource: string; data: ManagementData; onSaved: () => void; onError: (message: string) => void }) {
  const fields = data.fields || []
  const initialValues = data.values || Object.fromEntries(fields.map((field) => [field.name, field.initial ?? (field.type === 'checkbox' ? false : '')]))
  const [values, setValues] = useState<Record<string, any>>(initialValues)
  const [fieldErrors, setFieldErrors] = useState<Record<string, any>>({})
  const [saving, setSaving] = useState(false)
  useEffect(() => setValues(initialValues), [data])
  const update = (name: string, value: any) => setValues((current) => ({ ...current, [name]: value }))
  const submit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault()
    setSaving(true)
    setFieldErrors({})
    const formData = new FormData()
    fields.forEach((field) => {
      const value = values[field.name]
      if (field.type === 'checkbox') formData.append(field.name, value ? 'on' : '')
      else if (Array.isArray(value)) value.forEach((item) => formData.append(field.name, String(item)))
      else if (value !== undefined && value !== null) formData.append(field.name, String(value))
    })
    event.currentTarget.querySelectorAll<HTMLInputElement>('input[type=file]').forEach((input) => { if (input.files?.[0]) formData.set(input.name, input.files[0]) })
    try {
      await dashboardFetch(resource, { method: 'POST', body: formData })
      onSaved()
    } catch (reason) {
      const message = reason instanceof Error ? reason.message : 'Unable to save this form.'
      onError(message)
      setFieldErrors((reason as Error & { fieldErrors?: Record<string, any> }).fieldErrors || {})
    } finally {
      setSaving(false)
    }
  }
  return <form onSubmit={submit} className="rounded-3xl border border-[var(--line)] bg-white p-6 shadow-sm sm:p-8"><div className="grid gap-5 md:grid-cols-2">{fields.map((field) => {
    const value = values[field.name] ?? ''
    if (field.type === 'checkbox') return <label key={field.name} className="flex items-center gap-3 rounded-2xl bg-[var(--mist)] p-4 text-sm font-semibold"><input type="checkbox" name={field.name} checked={Boolean(value)} onChange={(event) => update(field.name, event.target.checked)} />{field.label}</label>
    if (field.type === 'select') return <label key={field.name} className="grid gap-2 text-sm font-semibold"><span>{field.label}{field.required && ' *'}</span><select name={field.name} multiple={Array.isArray(value)} value={Array.isArray(value) ? value.map(String) : String(value)} required={field.required} onChange={(event) => update(field.name, event.target.multiple ? Array.from(event.currentTarget.selectedOptions, (option) => option.value) : event.target.value)} className="min-h-12 rounded-xl border border-[var(--line)] bg-white px-4 py-3">{field.choices.map((choice) => <option key={choice.value} value={choice.value}>{choice.label}</option>)}</select></label>
    if (field.type === 'file') return <label key={field.name} className="grid gap-2 text-sm font-semibold"><span>{field.label}</span><input type="file" name={field.name} className="rounded-xl border border-[var(--line)] bg-white px-4 py-3" /></label>
    return <label key={field.name} className={'grid gap-2 text-sm font-semibold ' + (field.type === 'textarea' ? 'md:col-span-2' : '')}><span>{field.label}{field.required && ' *'}</span>{field.type === 'textarea' ? <textarea name={field.name} value={String(value)} required={field.required} rows={6} onChange={(event) => update(field.name, event.target.value)} className="rounded-xl border border-[var(--line)] bg-white px-4 py-3" /> : <input type={field.type} name={field.name} value={String(value)} required={field.required} onChange={(event) => update(field.name, event.target.value)} className="min-h-12 rounded-xl border border-[var(--line)] bg-white px-4 py-3" />}{fieldErrors[field.name] && <small className="font-normal text-red-700">{Array.isArray(fieldErrors[field.name]) ? fieldErrors[field.name].map((item: any) => item.message).join(' ') : String(fieldErrors[field.name])}</small>}{field.helpText && <small className="font-normal text-[var(--ink-soft)]">{field.helpText}</small>}</label>
  })}</div><div className="mt-7 flex flex-wrap gap-3"><button type="submit" disabled={saving} className="rounded-xl bg-[var(--navy)] px-5 py-3 text-sm font-bold text-white disabled:opacity-50">{saving ? 'Saving...' : 'Save'}</button><a href={'/dashboard/' + (resource.split('/')[0] === 'content' ? 'content/' + resource.split('/')[1] : resource.split('/')[0]) + '/'} className="rounded-xl bg-amber-300 px-5 py-3 text-sm font-bold text-amber-950">Cancel</a></div></form>
}

function ListPage({ path, resource, data, onError }: { path: string[]; resource: string; data: ManagementData; onError: (message: string) => void }) {
  const [requestFilter, setRequestFilter] = useState(data.sections?.[0]?.key || '')
  if (data.kind === 'requests') {
    const section = data.sections?.find((item) => item.key === requestFilter) || data.sections?.[0]
    return <section className="space-y-5"><div className="flex flex-wrap gap-3">{data.sections?.map((item) => <button type="button" key={item.key} onClick={() => setRequestFilter(item.key)} className={'rounded-full px-5 py-3 text-sm font-bold ' + (item.key === section?.key ? 'bg-[var(--navy)] text-white' : 'border border-[var(--line)] bg-white text-[var(--teal)]')}>{item.label} <span className="ml-1 opacity-70">{item.count}</span></button>)}</div>{section && <div className="overflow-hidden rounded-3xl border border-[var(--line)] bg-white shadow-sm"><div className="overflow-x-auto"><table className="w-full text-left text-sm"><thead className="bg-[var(--mist)] text-xs uppercase tracking-wide text-[var(--ink-soft)]"><tr><th className="px-5 py-4">Reference</th><th className="px-5 py-4">Customer</th><th className="px-5 py-4">Status</th><th className="px-5 py-4">Actions</th></tr></thead><tbody>{section.items.map((item) => <tr key={item.id} className="border-t border-[var(--line)]"><td className="px-5 py-4 font-bold">{item.reference || item.id}</td><td className="px-5 py-4">{item.fullName}<br /><span className="text-xs text-[var(--ink-soft)]">{item.email}</span></td><td className="px-5 py-4"><span className="rounded-full bg-[var(--mist)] px-3 py-1 text-xs font-bold">{item.status}</span></td><td className="px-5 py-4"><div className="inline-flex gap-2">{section.canChange && <a className="rounded-lg border border-[var(--line)] px-3 py-2 text-xs font-bold text-[var(--teal)]" href={'/dashboard/requests/' + section.key + '/' + item.id + '/'}>Open</a>}{section.canDelete && <DeleteAction resource={'requests/' + section.key} id={item.id} label="request" onError={onError} />}</div></td></tr>)}</tbody></table>{!section.items.length && <p className="p-8 text-sm text-[var(--ink-soft)]">No {section.label.toLowerCase()} yet.</p>}</div></div>}</section>
  }
  if (data.kind === 'users') return <section className="space-y-5"><div className="flex items-center justify-between gap-4"><p className="text-sm text-[var(--ink-soft)]">{(data.items || []).length} users</p><a href="/dashboard/users/new/" className="rounded-xl bg-[var(--navy)] px-5 py-3 text-sm font-bold text-white">Add user</a></div><div className="overflow-hidden rounded-3xl border border-[var(--line)] bg-white shadow-sm"><div className="overflow-x-auto"><table className="min-w-full text-left text-sm"><thead className="bg-[var(--mist)] text-xs uppercase tracking-wide text-[var(--ink-soft)]"><tr><th className="px-5 py-4">User</th><th className="px-5 py-4">Role</th><th className="px-5 py-4">Status</th><th className="px-5 py-4">Joined</th><th className="px-5 py-4 text-right">Actions</th></tr></thead><tbody>{(data.items || []).map((item) => <tr key={item.id} className="border-t border-[var(--line)] transition hover:bg-[var(--mist)]/40"><td className="px-5 py-4"><p className="font-bold">{item.name}</p><p className="mt-1 text-xs text-[var(--ink-soft)]">{item.email || item.username}</p></td><td className="px-5 py-4">{item.roles?.join(' - ') || (item.isStaff ? 'Administrator' : 'Dashboard user')}</td><td className="px-5 py-4"><span className={'rounded-full px-3 py-1 text-xs font-bold ' + (item.isActive ? 'bg-emerald-50 text-emerald-700' : 'bg-slate-100 text-slate-600')}>{item.isActive ? 'Active' : 'Inactive'}</span></td><td className="px-5 py-4 text-xs text-[var(--ink-soft)]">{item.dateJoined?.slice(0, 10)}</td><td className="px-5 py-4 text-right"><div className="inline-flex gap-2"><a href={'/dashboard/users/' + item.id + '/edit/'} className="rounded-lg border border-[var(--line)] px-3 py-2 text-xs font-bold text-[var(--teal)]">Edit</a>{item.id !== undefined && <DeleteAction resource="users" id={item.id} label="user" onError={onError} />}</div></td></tr>)}</tbody></table>{!(data.items || []).length && <p className="p-10 text-center text-sm text-[var(--ink-soft)]">No users yet.</p>}</div></div></section>
  if (data.kind === 'messages') return <section className="space-y-5"><p className="text-sm text-[var(--ink-soft)]">{(data.items || []).length} messages</p><div className="overflow-hidden rounded-3xl border border-[var(--line)] bg-white shadow-sm"><div className="overflow-x-auto"><table className="min-w-full text-left text-sm"><thead className="bg-[var(--mist)] text-xs uppercase tracking-wide text-[var(--ink-soft)]"><tr><th className="px-5 py-4">Subject</th><th className="px-5 py-4">Sender</th><th className="px-5 py-4">Status</th><th className="px-5 py-4">Received</th><th className="px-5 py-4 text-right">Actions</th></tr></thead><tbody>{(data.items || []).map((item) => <tr key={item.id} className="border-t border-[var(--line)] transition hover:bg-[var(--mist)]/40"><td className="max-w-sm px-5 py-4"><p className="truncate font-bold">{item.subject || 'Public message'}</p><p className="mt-1 truncate text-xs text-[var(--ink-soft)]">{item.message}</p></td><td className="px-5 py-4"><p className="font-semibold">{item.fullName}</p><p className="mt-1 text-xs text-[var(--ink-soft)]">{item.email}</p></td><td className="px-5 py-4"><span className="rounded-full bg-[var(--mist)] px-3 py-1 text-xs font-bold">{item.status}</span></td><td className="px-5 py-4 text-xs text-[var(--ink-soft)]">{item.createdAt?.slice(0, 10)}</td><td className="px-5 py-4 text-right"><div className="inline-flex gap-2">{data.canChange && <a href={'/dashboard/messages/' + item.id + '/'} className="rounded-lg border border-[var(--line)] px-3 py-2 text-xs font-bold text-[var(--teal)]">Open</a>}{data.canDelete && <DeleteAction resource="messages" id={item.id} label="message" onError={onError} />}</div></td></tr>)}</tbody></table>{!(data.items || []).length && <p className="p-10 text-center text-sm text-[var(--ink-soft)]">No public messages yet.</p>}</div></div></section>
  const items = data.items || []
  return <section className="space-y-5"><div className="flex items-center justify-between gap-4"><p className="text-sm text-[var(--ink-soft)]">{items.length} record{items.length === 1 ? '' : 's'}</p>{data.canAdd && <a href={'/dashboard/content/' + path[1] + '/new/'} className="rounded-xl bg-[var(--navy)] px-5 py-3 text-sm font-bold text-white">Add {data.singular}</a>}</div><div className="overflow-hidden rounded-3xl border border-[var(--line)] bg-white shadow-sm"><div className="overflow-x-auto"><table className="min-w-full text-left text-sm"><thead className="bg-[var(--mist)] text-xs uppercase tracking-wide text-[var(--ink-soft)]"><tr><th className="px-5 py-4">Title</th><th className="px-5 py-4">Status</th><th className="px-5 py-4">Updated</th><th className="px-5 py-4 text-right">Actions</th></tr></thead><tbody>{items.map((item) => <tr key={item.id} className="border-t border-[var(--line)] transition hover:bg-[var(--mist)]/40"><td className="max-w-xl px-5 py-4"><p className="truncate font-bold">{item.title}</p><p className="mt-1 truncate text-xs text-[var(--ink-soft)]">{item.summary}</p></td><td className="px-5 py-4"><span className="rounded-full bg-[var(--mist)] px-3 py-1 text-xs font-bold">{item.status}</span></td><td className="px-5 py-4 text-xs text-[var(--ink-soft)]">{item.updatedAt?.slice(0, 10)}</td><td className="px-5 py-4 text-right"><div className="inline-flex gap-2">{data.canChange && <a href={'/dashboard/content/' + path[1] + '/' + item.id + '/edit/'} className="rounded-lg border border-[var(--line)] px-3 py-2 text-xs font-bold text-[var(--teal)]">Edit</a>}{data.canDelete && <DeleteAction resource={resource} id={item.id} label={data.singular || 'record'} onError={onError} />}</div></td></tr>)}</tbody></table>{!items.length && <p className="p-10 text-center text-sm text-[var(--ink-soft)]">No records yet.</p>}</div></div></section>
}

export function DashboardWorkspace({ path, resource, initialDashboard, initialData, initialError }: { path: string[]; resource: string; initialDashboard: DashboardData | null; initialData: ManagementData | null; initialError: string }) {
  const [dashboard] = useState(initialDashboard)
  const [data] = useState(initialData)
  const [error] = useState(initialError)
  const [toast, setToast] = useState<DashboardToastMessage | null>(initialError ? { message: initialError } : null)
  const isForm = path.includes('new') || path.includes('edit') || (path[0] === 'messages' && path.length > 1) || (path[0] === 'requests' && path.length > 2) || (path[0] === 'users' && path.length > 1) || path[0] === 'settings'
  const title = useMemo(() => pageTitle(path, data), [path, data])
  useEffect(() => {
    if (!toast) return
    const timeout = window.setTimeout(() => setToast(null), 5000)
    return () => window.clearTimeout(timeout)
  }, [toast])
  const showError = (message: string) => setToast({ message })
  if (error || !dashboard || !data) return <main className="grid min-h-screen place-items-center bg-[var(--paper)] px-6 text-center"><DashboardToast toast={toast || { message: error || 'The dashboard area could not be loaded.' }} onClose={() => setToast(null)} /><div className="max-w-md rounded-3xl border border-[var(--line)] bg-white p-10 shadow-xl"><ShieldCheck className="mx-auto text-[var(--teal)]" size={40} /><h1 className="mt-5 font-display text-4xl">Dashboard access</h1><p className="mt-4 text-sm text-[var(--ink-soft)]">{error || 'The dashboard area could not be loaded.'}</p><a href="/login" className="mt-7 inline-flex rounded-full bg-[var(--navy)] px-6 py-3 text-sm font-bold text-white">Sign in</a></div></main>
  return <DashboardChrome data={dashboard} path={path} title={title} toast={toast} onCloseToast={() => setToast(null)}>{isForm ? <FormPanel resource={resource} data={data} onError={showError} onSaved={() => { window.location.href = '/dashboard/' + (path[0] === 'content' ? 'content/' + path[1] : path[0]) + '/' }} /> : <ListPage path={path} resource={resource} data={data} onError={showError} />}</DashboardChrome>
}
