import { zodResolver } from '@hookform/resolvers/zod'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Plus, Trash2 } from 'lucide-react'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import { z } from 'zod'
import { qk } from '@/shared/api/query-keys'
import { useApiError } from '@/shared/lib/use-api-error'
import { Badge } from '@/shared/ui/badge'
import { Button } from '@/shared/ui/button'
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/shared/ui/dialog'
import { Input } from '@/shared/ui/input'
import { Label } from '@/shared/ui/label'
import { sortRows, useTableSort } from '@/shared/lib/table-sort'
import { SortHeader } from '@/shared/ui/sortable'
import { createRole, deleteRole, listRoles, updateRole } from './api'

const schema = z.object({ name: z.string().min(1).max(64) })

export function RolesPanel() {
  const { t } = useTranslation()
  const queryClient = useQueryClient()
  const { data: roles, isLoading } = useQuery({ queryKey: qk.roles.all, queryFn: listRoles })
  const { sort, toggle } = useTableSort('name', false)
  const sortedRoles = sortRows(roles ?? [], sort, {
    name: (r) => r.name.toLowerCase(),
    system: (r) => r.isSystem,
  })

  const invalidate = () => queryClient.invalidateQueries({ queryKey: qk.roles.all })
  const onError = useApiError()

  const createMutation = useMutation({
    mutationFn: (name: string) => createRole(name),
    onSuccess: invalidate,
  })

  const deleteMutation = useMutation({
    mutationFn: (id: string) => deleteRole(id),
    onSuccess: invalidate,
    onError,
  })

  const renameMutation = useMutation({
    mutationFn: ({ id, name }: Readonly<{ id: string; name: string }>) => updateRole(id, name),
    onSuccess: invalidate,
    onError,
  })

  const [open, setOpen] = useState(false)
  const { register, handleSubmit, reset } = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
  })

  const onCreate = async (values: z.infer<typeof schema>) => {
    try {
      await createMutation.mutateAsync(values.name)
      reset()
      setOpen(false)
    } catch (error) {
      onError(error)
    }
  }

  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center justify-between">
        <h2 className="crt-glow text-xl font-semibold">{t('admin.roles.title')}</h2>
        <Dialog open={open} onOpenChange={setOpen}>
          <DialogTrigger asChild>
            <Button size="sm">
              <Plus className="h-4 w-4" /> {t('admin.roles.create')}
            </Button>
          </DialogTrigger>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>{t('admin.roles.create')}</DialogTitle>
            </DialogHeader>
            <form className="flex flex-col gap-4" onSubmit={handleSubmit(onCreate)}>
              <div className="flex flex-col gap-1.5">
                <Label htmlFor="roleName">{t('admin.roles.name')}</Label>
                <Input id="roleName" {...register('name')} />
              </div>
              <DialogFooter>
                <Button type="submit" disabled={createMutation.isPending}>
                  {t('common.create')}
                </Button>
              </DialogFooter>
            </form>
          </DialogContent>
        </Dialog>
      </div>

      <div className="crt-panel overflow-x-auto rounded-md">
        <table className="w-full text-sm">
          <thead className="border-b border-border text-left text-muted-foreground">
            <tr>
              <SortHeader
                label={t('admin.roles.name')}
                sortKey="name"
                sort={sort}
                onToggle={toggle}
              />
              <SortHeader
                label={t('admin.roles.system')}
                sortKey="system"
                sort={sort}
                onToggle={toggle}
              />
              <th className="px-4 py-2 font-medium">{t('common.actions')}</th>
            </tr>
          </thead>
          <tbody>
            {isLoading && (
              <tr>
                <td className="px-4 py-3 text-muted-foreground" colSpan={3}>
                  {t('common.loading')}
                </td>
              </tr>
            )}
            {sortedRoles.map((role) => (
              <tr key={role.id} className="border-b border-border last:border-0">
                <td className="px-4 py-2">{role.name}</td>
                <td className="px-4 py-2">
                  {role.isSystem ? (
                    <Badge variant="muted">{t('common.yes')}</Badge>
                  ) : (
                    t('common.no')
                  )}
                </td>
                <td className="px-4 py-2">
                  <div className="flex gap-2">
                    <Button
                      size="sm"
                      variant="outline"
                      disabled={role.isSystem}
                      onClick={() => {
                        const nextName = window.prompt(t('admin.roles.rename'), role.name)
                        if (nextName && nextName !== role.name)
                          renameMutation.mutate({ id: role.id, name: nextName })
                      }}
                    >
                      {t('admin.roles.rename')}
                    </Button>
                    <Button
                      size="sm"
                      variant="destructive"
                      disabled={role.isSystem}
                      onClick={() => deleteMutation.mutate(role.id)}
                    >
                      <Trash2 className="h-4 w-4" />
                    </Button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}
