import { startTransition, useDeferredValue, useEffect, 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,
  ChevronLeft,
  ChevronRight,
  ChevronsUpDown,
  FilterX,
  Loader2,
  PencilLine,
  Plus,
  RefreshCw,
  Search,
  ShieldCheck,
  Trash2,
} from 'lucide-react'
import { toast } from 'sonner'
import { fetchRoles } from '@/lib/api/roles'
import type { AdminRoleRecord, AdminUserRecord } from '@/lib/api/types'
import { createUser, deleteUser, fetchUsers, updateUser } from '@/lib/api/users'
import { handleServerError } from '@/lib/handle-server-error'
import { getPageNumbers } from '@/lib/utils'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from '@/components/ui/card'
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { ConfirmDialog } from '@/components/confirm-dialog'
import { Main } from '@/components/layout/main'
import { PasswordInput } from '@/components/password-input'
import { UsersHeader } from './components/users-header'

const defaultPerPage = 10

type UserSort = 'newest' | 'oldest' | 'name-asc' | 'name-desc'

type EditorState =
  | { mode: 'create'; user: null }
  | { mode: 'edit'; user: AdminUserRecord }
  | null

function buildUserSchema(isEdit: boolean) {
  return z
    .object({
      name: z.string().min(2, 'Ad soyad en az 2 karakter olmalıdır'),
      email: z.string().email('Geçerli bir e-posta giriniz'),
      role: z.string().min(1, 'Rol seçiniz'),
      password: z.string().optional(),
      passwordConfirmation: z.string().optional(),
    })
    .superRefine((value, ctx) => {
      if (!isEdit && !value.password) {
        ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Yeni kullanıcı için şifre zorunludur', path: ['password'] })
      }
      if (value.password && value.password.length < 6) {
        ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Şifre en az 6 karakter olmalıdır', path: ['password'] })
      }
      if ((value.password || value.passwordConfirmation) && value.password !== value.passwordConfirmation) {
        ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Şifre tekrarı eşleşmiyor', path: ['passwordConfirmation'] })
      }
    })
}

type UserFormValues = z.infer<ReturnType<typeof buildUserSchema>>

function UserEditorPage({ state, roles, isPending, onCancel, onSubmit }: { state: Exclude<EditorState, null>; roles: AdminRoleRecord[]; isPending: boolean; onCancel: () => void; onSubmit: (values: UserFormValues) => Promise<void> }) {
  const user = state.user
  const isEdit = state.mode === 'edit'
  const form = useForm<UserFormValues>({ resolver: zodResolver(buildUserSchema(isEdit)), defaultValues: { name: user?.name ?? '', email: user?.email ?? '', role: user?.role ?? '', password: '', passwordConfirmation: '' } })

  useEffect(() => { form.reset({ name: user?.name ?? '', email: user?.email ?? '', role: user?.role ?? '', password: '', passwordConfirmation: '' }) }, [form, user])

  return (
    <Card className='border-border/70 shadow-sm'>
      <CardHeader className='gap-4 border-b border-border/70 bg-muted/20 md:flex-row md:items-start md:justify-between'>
        <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>{isEdit ? 'Kullanıcıyı düzenle' : 'Yeni kullanıcı oluştur'}</CardTitle>
          <CardDescription>Rol ataması ve erişim bilgileri bu ekran üzerinden yönetilir.</CardDescription>
        </div>
      </CardHeader>
      <CardContent className='p-6'>
        <Form {...form}>
          <form onSubmit={form.handleSubmit(async (values) => { await onSubmit(values) })} className='space-y-6'>
            <div className='grid gap-4 md:grid-cols-2'>
              <FormField control={form.control} name='name' render={({ field }) => (<FormItem><FormLabel>Ad soyad</FormLabel><FormControl><Input {...field} placeholder='Örnek: Ahmet Yılmaz' /></FormControl><FormMessage /></FormItem>)} />
              <FormField control={form.control} name='email' render={({ field }) => (<FormItem><FormLabel>E-posta</FormLabel><FormControl><Input {...field} placeholder='ahmet@bogazici.com.tr' /></FormControl><FormMessage /></FormItem>)} />
            </div>
            <FormField control={form.control} name='role' render={({ field }) => (<FormItem><FormLabel>Rol</FormLabel><Select value={field.value} onValueChange={field.onChange}><FormControl><SelectTrigger className='w-full'><SelectValue placeholder='Bir rol seçiniz' /></SelectTrigger></FormControl><SelectContent>{roles.map((role) => (<SelectItem key={role.id} value={role.name}>{role.name}</SelectItem>))}</SelectContent></Select><FormMessage /></FormItem>)} />
            <div className='grid gap-4 md:grid-cols-2'>
              <FormField control={form.control} name='password' render={({ field }) => (<FormItem><FormLabel>{isEdit ? 'Yeni şifre' : 'Şifre'}</FormLabel><FormControl><PasswordInput {...field} placeholder={isEdit ? 'Değiştirmek istemiyorsanız boş bırakın' : 'En az 6 karakter'} /></FormControl><FormMessage /></FormItem>)} />
              <FormField control={form.control} name='passwordConfirmation' render={({ field }) => (<FormItem><FormLabel>Şifre tekrarı</FormLabel><FormControl><PasswordInput {...field} placeholder='Şifreyi tekrar girin' /></FormControl><FormMessage /></FormItem>)} />
            </div>
            <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' /> : null}{isEdit ? 'Kaydet' : 'Kullanıcıyı oluştur'}</Button>
            </div>
          </form>
        </Form>
      </CardContent>
    </Card>
  )
}

export function UsersPage() {
  const queryClient = useQueryClient()
  const [search, setSearch] = useState('')
  const [roleFilter, setRoleFilter] = useState('all')
  const [sortBy, setSortBy] = useState<UserSort>('newest')
  const [perPage, setPerPage] = useState(defaultPerPage)
  const [page, setPage] = useState(1)
  const [editorState, setEditorState] = useState<EditorState>(null)
  const [userToDelete, setUserToDelete] = useState<AdminUserRecord | null>(null)
  const deferredSearch = useDeferredValue(search)

  const rolesQuery = useQuery({ queryKey: ['roles', 'all'], queryFn: fetchRoles })
  const usersQuery = useQuery({ queryKey: ['users', page, perPage, deferredSearch, roleFilter], queryFn: () => fetchUsers({ page, perPage, search: deferredSearch || undefined, role: roleFilter === 'all' ? undefined : roleFilter }) })

  const hasActiveFilters = search.trim().length > 0 || roleFilter !== 'all' || sortBy !== 'newest' || perPage !== defaultPerPage

  const visibleUsers = [...(usersQuery.data?.items ?? [])].sort((left, right) => {
    switch (sortBy) {
      case 'oldest': return new Date(left.createdAt ?? 0).getTime() - new Date(right.createdAt ?? 0).getTime()
      case 'name-asc': return left.name.localeCompare(right.name, 'tr')
      case 'name-desc': return right.name.localeCompare(left.name, 'tr')
      case 'newest': default: return new Date(right.createdAt ?? 0).getTime() - new Date(left.createdAt ?? 0).getTime()
    }
  })

  function resetFilters() { startTransition(() => { setSearch(''); setRoleFilter('all'); setSortBy('newest'); setPerPage(defaultPerPage); setPage(1) }) }

  const upsertMutation = useMutation({
    mutationFn: async (values: UserFormValues) => {
      const payload = { name: values.name, email: values.email, role: values.role, ...(values.password ? { password: values.password, password_confirmation: values.passwordConfirmation } : {}) }
      if (editorState?.mode === 'edit') return updateUser(editorState.user.id, payload)
      return createUser(payload)
    },
    onSuccess: async () => { toast.success('Kullanıcı kaydedildi'); await queryClient.invalidateQueries({ queryKey: ['users'] }); setEditorState(null) },
    onError: handleServerError,
  })

  const deleteMutation = useMutation({
    mutationFn: async (userId: number | string) => deleteUser(userId),
    onSuccess: async () => { toast.success('Kullanıcı silindi'); await queryClient.invalidateQueries({ queryKey: ['users'] }); setUserToDelete(null) },
    onError: handleServerError,
  })

  const pageNumbers = getPageNumbers(page, usersQuery.data?.meta.lastPage ?? 1)

  return (
    <>
      <UsersHeader />
      <Main className='space-y-6'>
        {editorState ? (
          <UserEditorPage state={editorState} roles={rolesQuery.data ?? []} isPending={upsertMutation.isPending} onCancel={() => setEditorState(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>Kullanıcı listesi</CardTitle><CardDescription>Swagger sözleşmesine göre `/api/admin/users` kaynağı üzerinden beslenir.</CardDescription></div>
                <div className='flex flex-wrap gap-2'>
                  <Button variant='outline' className='rounded-xl' onClick={() => usersQuery.refetch()}><RefreshCw className={usersQuery.isFetching ? 'animate-spin' : ''} />Yenile</Button>
                  <Button className='rounded-xl' onClick={() => setEditorState({ mode: 'create', user: null })}><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 xl:grid-cols-[minmax(260px,1.3fr)_220px_220px_180px_auto]'>
                  <div className='space-y-2'><p className='text-xs font-semibold tracking-[0.2em] text-muted-foreground uppercase'>Arama</p><div className='relative'><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) => { const nextValue = event.target.value; startTransition(() => { setSearch(nextValue); setPage(1) }) }} placeholder='Ad veya e-posta ile ara' className='pl-9' /></div></div>
                  <div className='space-y-2'><p className='text-xs font-semibold tracking-[0.2em] text-muted-foreground uppercase'>Rol</p><Select value={roleFilter} onValueChange={(value) => startTransition(() => { setRoleFilter(value); setPage(1) })}><SelectTrigger className='w-full'><SelectValue placeholder='Tüm roller' /></SelectTrigger><SelectContent><SelectItem value='all'>Tüm roller</SelectItem>{(rolesQuery.data ?? []).map((role) => (<SelectItem key={role.id} value={role.name}>{role.name}</SelectItem>))}</SelectContent></Select></div>
                  <div className='space-y-2'><p className='text-xs font-semibold tracking-[0.2em] text-muted-foreground uppercase'>Sıralama</p><Select value={sortBy} onValueChange={(value: UserSort) => setSortBy(value)}><SelectTrigger className='w-full'><SelectValue placeholder='En yeni önce' /></SelectTrigger><SelectContent><SelectItem value='newest'>En yeni önce</SelectItem><SelectItem value='oldest'>En eski önce</SelectItem><SelectItem value='name-asc'>Ada göre A-Z</SelectItem><SelectItem value='name-desc'>Ada göre Z-A</SelectItem></SelectContent></Select></div>
                  <div className='space-y-2'><p className='text-xs font-semibold tracking-[0.2em] text-muted-foreground uppercase'>Sayfa boyutu</p><Select value={String(perPage)} onValueChange={(value) => startTransition(() => { setPerPage(Number(value)); setPage(1) })}><SelectTrigger className='w-full'><SelectValue placeholder='10 kayıt' /></SelectTrigger><SelectContent><SelectItem value='10'>10 kayıt</SelectItem><SelectItem value='25'>25 kayıt</SelectItem><SelectItem value='50'>50 kayıt</SelectItem></SelectContent></Select></div>
                  <div className='flex items-end justify-end'><Button variant='outline' className='rounded-xl' onClick={resetFilters} disabled={!hasActiveFilters}><FilterX />Temizle</Button></div>
                </div>
                <div className='mt-3 flex flex-wrap gap-2'>
                  {search.trim() ? (<Badge variant='outline' className='rounded-full px-3 py-1'>Arama: {search}</Badge>) : null}
                  {roleFilter !== 'all' ? (<Badge variant='outline' className='rounded-full px-3 py-1'>Rol: {roleFilter}</Badge>) : null}
                  {sortBy !== 'newest' ? (<Badge variant='outline' className='rounded-full px-3 py-1'><ChevronsUpDown className='size-3.5' />{sortBy === 'oldest' ? 'En eski önce' : sortBy === 'name-asc' ? 'Ada göre A-Z' : 'Ada göre Z-A'}</Badge>) : null}
                  {perPage !== defaultPerPage ? (<Badge variant='outline' className='rounded-full px-3 py-1'>{perPage} kayıt</Badge>) : null}
                </div>
              </div>
            </CardHeader>
            <CardContent className='space-y-4'>
              <div className='rounded-2xl border border-border/70'>
                <Table>
                  <TableHeader><TableRow><TableHead className='px-4'>Kullanıcı</TableHead><TableHead>Rol</TableHead><TableHead>Durum</TableHead><TableHead>Oluşturma</TableHead><TableHead className='w-[180px] text-right'>İşlemler</TableHead></TableRow></TableHeader>
                  <TableBody>
                    {usersQuery.isLoading ? (
                      <TableRow><TableCell colSpan={5} className='h-28 text-center text-muted-foreground'><Loader2 className='mx-auto mb-2 size-5 animate-spin' />Kullanıcılar yükleniyor...</TableCell></TableRow>
                    ) : visibleUsers.length ? (
                      visibleUsers.map((user) => (
                        <TableRow key={user.id}>
                          <TableCell className='px-4 py-4'><div><p className='font-medium text-foreground'>{user.name}</p><p className='text-sm text-muted-foreground'>{user.email}</p></div></TableCell>
                          <TableCell><Badge variant='outline' className='rounded-full'><ShieldCheck className='size-3.5' />{user.role}</Badge></TableCell>
                          <TableCell><Badge className={user.status === 'active' ? 'rounded-full bg-emerald-600 text-white hover:bg-emerald-600' : 'rounded-full bg-slate-500 text-white hover:bg-slate-500'}>{user.status}</Badge></TableCell>
                          <TableCell className='text-muted-foreground'>{user.createdAt ? new Date(user.createdAt).toLocaleDateString('tr-TR') : '-'}</TableCell>
                          <TableCell className='py-4'>
                            <div className='flex justify-end gap-2'>
                              <Button variant='outline' size='sm' className='rounded-xl' onClick={() => setEditorState({ mode: 'edit', user })}><PencilLine />Düzenle</Button>
                              <Button variant='destructive' size='sm' className='rounded-xl' onClick={() => setUserToDelete(user)}><Trash2 />Sil</Button>
                            </div>
                          </TableCell>
                        </TableRow>
                      ))
                    ) : (
                      <TableRow><TableCell colSpan={5} className='h-28 text-center text-muted-foreground'>Filtrelere uygun kullanıcı bulunamadı.</TableCell></TableRow>
                    )}
                  </TableBody>
                </Table>
              </div>
              <div className='flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between'>
                <p className='text-sm text-muted-foreground'>Toplam {usersQuery.data?.meta.total ?? 0} kayıt. Sayfa {page} / {usersQuery.data?.meta.lastPage ?? 1}</p>
                <div className='flex flex-wrap items-center gap-2'>
                  <Button variant='outline' size='sm' onClick={() => startTransition(() => setPage((current) => Math.max(1, current - 1)))} disabled={page === 1}><ChevronLeft /></Button>
                  {pageNumbers.map((item, index) => item === '...' ? (<span key={`${item}-${index}`} className='px-2 text-sm text-muted-foreground'>...</span>) : (<Button key={item} size='sm' variant={item === page ? 'default' : 'outline'} onClick={() => startTransition(() => setPage(Number(item)))}>{item}</Button>))}
                  <Button variant='outline' size='sm' onClick={() => startTransition(() => setPage((current) => Math.min(usersQuery.data?.meta.lastPage ?? 1, current + 1)))} disabled={page === (usersQuery.data?.meta.lastPage ?? 1)}><ChevronRight /></Button>
                </div>
              </div>
            </CardContent>
          </Card>
        )}
      </Main>
      <ConfirmDialog open={!!userToDelete} onOpenChange={(open) => { if (!open) setUserToDelete(null) }} title='Kullanıcıyı silmek istediğinize emin misiniz?' desc={`${userToDelete?.name ?? 'Bu kullanıcı'} kaydı kalıcı olarak silinecek. Bu işlem geri alınamaz.`} confirmText='Evet, sil' cancelBtnText='İptal' destructive isLoading={deleteMutation.isPending} handleConfirm={() => { if (userToDelete) deleteMutation.mutate(userToDelete.id) }} />
    </>
  )
}
