import {
  startTransition,
  useDeferredValue,
  useEffect,
  useMemo,
  useState,
} from 'react'
import { z } from 'zod'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
  ArrowLeft,
  FilterX,
  KeyRound,
  Loader2,
  PencilLine,
  Plus,
  RefreshCw,
  Search,
  Trash2,
} from 'lucide-react'
import { toast } from 'sonner'
import {
  createRole,
  deleteRole,
  fetchPermissionsCatalog,
  fetchRoles,
  updateRole,
} from '@/lib/api/roles'
import type { AdminRoleRecord, PermissionGroup } from '@/lib/api/types'
import { handleServerError } from '@/lib/handle-server-error'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from '@/components/ui/card'
import { Checkbox } from '@/components/ui/checkbox'
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { ConfirmDialog } from '@/components/confirm-dialog'
import { Main } from '@/components/layout/main'
import { RolesHeader } from './components/roles-header'

const roleFormSchema = z.object({
  name: z.string().min(2, 'Rol adı en az 2 karakter olmalıdır'),
  permissions: z.array(z.string()).min(1, 'En az bir permission seçiniz'),
})

type RoleFormValues = z.infer<typeof roleFormSchema>

function getPermissionModuleLabel(permission: string) {
  const labels: Record<string, string> = {
    announcement: 'Duyurular', category: 'Kategoriler', comment: 'Yorumlar', course: 'Eğitimler', faq: 'SSS', 'guide-card': 'Rehber Kartları', 'hero-slide': 'Hero Slaytları', lead: 'Başvurular', menu: 'Menüler', page: 'Sayfalar', 'page-block': 'Sayfa Blokları', role: 'Roller', schedule: 'Eğitim Takvimi', setting: 'Ayarlar', user: 'Kullanıcılar',
  }
  const parts = permission.split('-').filter(Boolean)
  const actionTokens = new Set(['create', 'view', 'any', 'update', 'delete', 'force', 'restore', 'reorder', 'publish', 'unpublish', 'assign', 'sync', 'list'])
  while (parts.length > 1 && actionTokens.has(parts[0])) parts.shift()
  const moduleKey = parts.join('-') || 'general'
  return labels[moduleKey] ?? moduleKey
}

function regroupPermissions(groups: PermissionGroup[]): PermissionGroup[] {
  const allPermissions = groups.flatMap((group) => group.permissions)
  const grouped = new Map<string, string[]>()
  for (const permission of allPermissions) {
    const label = getPermissionModuleLabel(permission)
    const current = grouped.get(label) ?? []
    current.push(permission)
    grouped.set(label, current)
  }
  return Array.from(grouped.entries())
    .map(([group, permissions]) => ({ group, permissions: permissions.sort((left, right) => left.localeCompare(right)) }))
    .sort((left, right) => left.group.localeCompare(right.group, 'tr'))
}

function RoleEditorPage({ role, groups, isPending, onCancel, onSubmit }: { role: AdminRoleRecord | null; groups: PermissionGroup[]; isPending: boolean; onCancel: () => void; onSubmit: (values: RoleFormValues) => Promise<void> }) {
  const form = useForm<RoleFormValues>({ resolver: zodResolver(roleFormSchema), defaultValues: { name: role?.name ?? '', permissions: role?.permissions ?? [] } })
  useEffect(() => { form.reset({ name: role?.name ?? '', permissions: role?.permissions ?? [] }) }, [form, role])
  const groupedPermissions = useMemo(() => regroupPermissions(groups), [groups])
  const allPermissions = useMemo(() => groupedPermissions.flatMap((group) => group.permissions), [groupedPermissions])

  return (
    <Card className='border-border/70 shadow-sm'>
      <CardHeader className='gap-4 border-b border-border/70 bg-muted/20'>
        <div className='space-y-1'>
          <Button type='button' variant='ghost' size='sm' className='-ml-2 h-8 rounded-lg px-2 text-muted-foreground' onClick={onCancel}><ArrowLeft />Listeye dön</Button>
          <CardTitle>{role ? 'Rolü düzenle' : 'Yeni rol oluştur'}</CardTitle>
          <CardDescription>Permission seçimi doğrudan `/api/admin/permissions` kaynağından beslenir.</CardDescription>
        </div>
      </CardHeader>
      <CardContent className='p-6'>
        <Form {...form}>
          <form onSubmit={form.handleSubmit(async (values) => { await onSubmit(values) })} className='space-y-5 px-6 py-5'>
            <FormField control={form.control} name='name' render={({ field }) => (<FormItem><FormLabel>Rol adı</FormLabel><FormControl><Input {...field} placeholder='Örnek: content-manager' /></FormControl><FormMessage /></FormItem>)} />
            <FormField control={form.control} name='permissions' render={({ field }) => (
              <FormItem>
                <FormLabel>Permission matrisi</FormLabel>
                <div className='rounded-2xl border border-border/70 bg-muted/10 p-4'>
                  <div className='mb-4 flex flex-wrap items-center justify-between gap-3 rounded-2xl border border-border/60 bg-background p-4'>
                    <div><p className='text-sm font-semibold text-foreground'>Genel aksiyonlar</p><p className='text-sm text-muted-foreground'>Tüm modüller için seçimleri tek adımda yönetin.</p></div>
                    <div className='flex flex-wrap gap-2'>
                      <Button type='button' size='sm' className='rounded-xl bg-emerald-600 text-white hover:bg-emerald-700' onClick={() => field.onChange(allPermissions)}>Tümünü seç</Button>
                      <Button type='button' size='sm' className='rounded-xl bg-rose-600 text-white hover:bg-rose-700' onClick={() => field.onChange([])}>Tümünü kaldır</Button>
                    </div>
                  </div>
                  <div className='grid gap-4 lg:grid-cols-2 xl:grid-cols-3'>
                    {groupedPermissions.map((group) => {
                      const selectedCount = group.permissions.filter((permission) => field.value.includes(permission)).length
                      return (
                        <div key={group.group} className='rounded-2xl border border-border/60 bg-background p-4 shadow-sm'>
                          <div className='mb-4 flex items-center justify-between gap-3'>
                            <div><p className='text-sm font-semibold text-foreground'>{group.group}</p><p className='text-xs text-muted-foreground'>{group.permissions.length} yetki</p></div>
                            <Badge className={selectedCount > 0 ? 'rounded-full bg-emerald-100 text-emerald-700 hover:bg-emerald-100' : 'rounded-full bg-muted text-muted-foreground hover:bg-muted'}>{selectedCount}/{group.permissions.length}</Badge>
                          </div>
                          <div className='mb-3 flex flex-wrap gap-2'>
                            <Button type='button' size='sm' className='h-8 rounded-lg bg-emerald-50 px-2 text-xs text-emerald-700 hover:bg-emerald-100' onClick={() => { field.onChange(Array.from(new Set([...field.value, ...group.permissions]))) }}>Tümünü seç</Button>
                            <Button type='button' size='sm' className='h-8 rounded-lg bg-rose-50 px-2 text-xs text-rose-700 hover:bg-rose-100' onClick={() => { field.onChange(field.value.filter((item) => !group.permissions.includes(item))) }}>Tümünü kaldır</Button>
                          </div>
                          <div className='space-y-2'>
                            {group.permissions.map((permission) => {
                              const checked = field.value.includes(permission)
                              return (
                                <label key={permission} className={checked ? 'flex min-h-11 items-center gap-3 rounded-xl border border-emerald-200 bg-emerald-50/70 px-3 py-2.5 text-sm hover:bg-emerald-50' : 'flex min-h-11 items-center gap-3 rounded-xl border border-border/60 px-3 py-2.5 text-sm hover:bg-muted/30'}>
                                  <Checkbox checked={checked} onCheckedChange={(nextChecked) => { if (nextChecked) { field.onChange([...field.value, permission]); return } field.onChange(field.value.filter((item) => item !== permission)) }} />
                                  <span className='leading-5 break-words'>{permission}</span>
                                </label>
                              )
                            })}
                          </div>
                        </div>
                      )
                    })}
                  </div>
                </div>
                <FormMessage />
              </FormItem>
            )} />
            <div className='flex flex-wrap justify-end gap-3 border-t border-border/70 pt-6'>
              <Button type='button' variant='outline' onClick={onCancel}>Vazgeç</Button>
              <Button type='submit' className='rounded-xl' disabled={isPending}>{isPending && <Loader2 className='animate-spin' />}{role ? 'Kaydet' : 'Rol oluştur'}</Button>
            </div>
          </form>
        </Form>
      </CardContent>
    </Card>
  )
}

export function RolesPage() {
  const queryClient = useQueryClient()
  const [search, setSearch] = useState('')
  const [editorOpen, setEditorOpen] = useState(false)
  const [activeRole, setActiveRole] = useState<AdminRoleRecord | null>(null)
  const [roleToDelete, setRoleToDelete] = useState<AdminRoleRecord | null>(null)
  const deferredSearch = useDeferredValue(search)

  const rolesQuery = useQuery({ queryKey: ['roles'], queryFn: fetchRoles })
  const permissionsQuery = useQuery({ queryKey: ['permissions-catalog'], queryFn: fetchPermissionsCatalog })

  const upsertMutation = useMutation({
    mutationFn: async (values: RoleFormValues) => { if (activeRole) return updateRole(activeRole.id, values); return createRole(values) },
    onSuccess: async () => { toast.success('Rol kaydedildi'); await queryClient.invalidateQueries({ queryKey: ['roles'] }); setEditorOpen(false); setActiveRole(null) },
    onError: handleServerError,
  })

  const deleteMutation = useMutation({
    mutationFn: async (roleId: number | string) => deleteRole(roleId),
    onSuccess: async () => { toast.success('Rol silindi'); await queryClient.invalidateQueries({ queryKey: ['roles'] }); setRoleToDelete(null) },
    onError: handleServerError,
  })

  const filteredRoles = useMemo(() => {
    const roles = rolesQuery.data ?? []
    if (!deferredSearch) return roles
    return roles.filter((role) => role.name.toLowerCase().includes(deferredSearch.toLowerCase()))
  }, [deferredSearch, rolesQuery.data])

  return (
    <>
      <RolesHeader />
      <Main className='space-y-6'>
        {editorOpen ? (
          <RoleEditorPage role={activeRole} groups={permissionsQuery.data ?? []} isPending={upsertMutation.isPending} onCancel={() => { setEditorOpen(false); setActiveRole(null) }} onSubmit={async (values) => { await upsertMutation.mutateAsync(values) }} />
        ) : (
          <Card>
            <CardHeader className='gap-4'>
              <div className='flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between'>
                <div><CardTitle>Rol listesi</CardTitle><CardDescription>Permission grupları dinamik olarak backend tarafından oluşturulur.</CardDescription></div>
                <div className='flex flex-wrap gap-2'>
                  <Button variant='outline' className='rounded-xl' onClick={() => rolesQuery.refetch()}><RefreshCw className={rolesQuery.isFetching ? 'animate-spin' : ''} />Yenile</Button>
                  <Button className='rounded-xl' onClick={() => { setActiveRole(null); setEditorOpen(true) }}><Plus />Ekle</Button>
                </div>
              </div>
              <div className='rounded-2xl border border-dashed border-border/70 bg-muted/20 p-4'>
                <div className='grid gap-3 md:grid-cols-[minmax(280px,1fr)_auto]'>
                  <div className='space-y-2'><p className='text-xs font-semibold tracking-[0.2em] text-muted-foreground uppercase'>Arama</p><div className='relative min-w-[280px]'><Search className='pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground' /><Input value={search} onChange={(event) => startTransition(() => setSearch(event.target.value))} className='pl-9' placeholder='Rol ara' /></div></div>
                  <div className='flex items-end justify-end'><Button variant='outline' className='rounded-xl' onClick={() => setSearch('')} disabled={!search}><FilterX />Temizle</Button></div>
                </div>
              </div>
            </CardHeader>
            <CardContent>
              <div className='rounded-2xl border border-border/70'>
                <Table>
                  <TableHeader><TableRow><TableHead className='px-4'>Rol</TableHead><TableHead>Permission sayısı</TableHead><TableHead>Önizleme</TableHead><TableHead className='w-[180px] text-right'>İşlemler</TableHead></TableRow></TableHeader>
                  <TableBody>
                    {rolesQuery.isLoading ? (
                      <TableRow><TableCell colSpan={4} className='h-28 text-center text-muted-foreground'><Loader2 className='mx-auto mb-2 size-5 animate-spin' />Roller yükleniyor...</TableCell></TableRow>
                    ) : filteredRoles.length ? (
                      filteredRoles.map((role) => (
                        <TableRow key={role.id}>
                          <TableCell className='px-4 py-4'><div><p className='font-medium text-foreground'>{role.name}</p><p className='text-sm text-muted-foreground'>{role.isSystem ? 'Sistem rolü' : 'Özel rol'}</p></div></TableCell>
                          <TableCell><Badge variant='outline' className='rounded-full'><KeyRound className='size-3.5' />{role.permissionCount}</Badge></TableCell>
                          <TableCell>
                            <div className='flex flex-wrap gap-2'>
                              {role.permissions.slice(0, 3).map((permission) => (<Badge key={permission} variant='secondary' className='rounded-full'>{permission}</Badge>))}
                              {role.permissions.length > 3 && (<Badge variant='outline' className='rounded-full'>+{role.permissions.length - 3}</Badge>)}
                            </div>
                          </TableCell>
                          <TableCell>
                            <div className='flex justify-end gap-2'>
                              <Button variant='outline' size='sm' className='rounded-xl' onClick={() => { setActiveRole(role); setEditorOpen(true) }}><PencilLine />Düzenle</Button>
                              <Button variant='destructive' size='sm' className='rounded-xl' onClick={() => setRoleToDelete(role)}><Trash2 />Sil</Button>
                            </div>
                          </TableCell>
                        </TableRow>
                      ))
                    ) : (
                      <TableRow><TableCell colSpan={4} className='h-28 text-center text-muted-foreground'>Filtreye uygun rol bulunamadı.</TableCell></TableRow>
                    )}
                  </TableBody>
                </Table>
              </div>
            </CardContent>
          </Card>
        )}
      </Main>
      <ConfirmDialog open={!!roleToDelete} onOpenChange={(open) => { if (!open) setRoleToDelete(null) }} title='Rolü silmek istediğinize emin misiniz?' desc={`${roleToDelete?.name ?? 'Bu rol'} silinecek ve bağlı kullanıcıların erişimleri etkilenebilir. Bu işlem geri alınamaz.`} confirmText='Evet, sil' cancelBtnText='İptal' destructive isLoading={deleteMutation.isPending} handleConfirm={() => { if (roleToDelete) deleteMutation.mutate(roleToDelete.id) }} />
    </>
  )
}
