import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
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 { Card, CardContent, CardHeader, CardTitle } from '@/shared/ui/card'
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/shared/ui/dialog'
import { Input } from '@/shared/ui/input'
import { Label } from '@/shared/ui/label'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/shared/ui/select'
import { useTableSort } from '@/shared/lib/table-sort'
import { SortHeader } from '@/shared/ui/sortable'
import { toast } from '@/shared/ui/toast-store'
import type { UserSummaryDto } from '@/shared/api/types'
import { changeUserRole, listRoles } from '@/features/admin/roles/api'
import { blockUser, createUser, deleteUser, listUsers, resetUserPassword, unblockUser } from './api'

const PAGE_SIZE = 20

export function UsersPanel() {
  const { t } = useTranslation()
  const queryClient = useQueryClient()
  const [page, setPage] = useState(1)
  const [search, setSearch] = useState('')
  const [roleId, setRoleId] = useState<string>('')
  const { sort, toggle } = useTableSort('created', true)
  const sortColumn = (key: string) => {
    setPage(1)
    toggle(key)
  }
  const [newUserName, setNewUserName] = useState('')
  const [newPassword, setNewPassword] = useState('')
  const [newRoleId, setNewRoleId] = useState('')
  const [resetTarget, setResetTarget] = useState<UserSummaryDto | null>(null)

  const { data: roles } = useQuery({ queryKey: qk.roles.all, queryFn: listRoles })
  const { data, isLoading } = useQuery({
    queryKey: qk.users.list(page, search, roleId, sort.key, sort.desc),
    queryFn: () =>
      listUsers({
        page,
        pageSize: PAGE_SIZE,
        search: search || undefined,
        roleId: roleId || undefined,
        sort: sort.key,
        desc: sort.desc,
      }),
  })

  const invalidate = () => queryClient.invalidateQueries({ queryKey: qk.users.all })

  const onError = useApiError()

  const blockMutation = useMutation({ mutationFn: blockUser, onSuccess: invalidate, onError })
  const unblockMutation = useMutation({ mutationFn: unblockUser, onSuccess: invalidate, onError })
  const deleteMutation = useMutation({ mutationFn: deleteUser, onSuccess: invalidate, onError })
  const changeRoleMutation = useMutation({
    mutationFn: ({ userId, roleId: nextRoleId }: Readonly<{ userId: string; roleId: string }>) =>
      changeUserRole(userId, nextRoleId),
    onSuccess: invalidate,
    onError,
  })

  // Роль по умолчанию для новой учётки — «user» (если есть), иначе первая роль.
  const defaultRoleId = roles?.find((r) => r.name === 'user')?.id ?? roles?.[0]?.id ?? ''
  const effectiveNewRoleId = newRoleId || defaultRoleId

  const createMutation = useMutation({
    mutationFn: () =>
      createUser({
        userName: newUserName.trim(),
        password: newPassword,
        roleId: effectiveNewRoleId,
      }),
    onSuccess: () => {
      setNewUserName('')
      setNewPassword('')
      setNewRoleId('')
      toast.success(t('admin.users.created'))
      invalidate()
    },
    onError,
  })

  const canCreate =
    newUserName.trim().length >= 3 && newPassword.length >= 8 && effectiveNewRoleId !== ''

  const totalPages = data ? Math.max(1, Math.ceil(data.total / PAGE_SIZE)) : 1

  return (
    <div className="flex flex-col gap-4">
      <h2 className="crt-glow text-xl font-semibold">{t('admin.users.title')}</h2>

      <Card>
        <CardHeader>
          <CardTitle>{t('admin.users.createTitle')}</CardTitle>
        </CardHeader>
        <CardContent className="flex flex-wrap items-end gap-3">
          <div className="flex flex-col gap-1.5">
            <Label>{t('admin.users.userName')}</Label>
            <Input
              className="w-56"
              value={newUserName}
              onChange={(e) => setNewUserName(e.target.value)}
            />
          </div>
          <div className="flex flex-col gap-1.5">
            <Label>{t('admin.users.password')}</Label>
            <Input
              type="password"
              className="w-56"
              value={newPassword}
              onChange={(e) => setNewPassword(e.target.value)}
            />
          </div>
          <div className="flex flex-col gap-1.5">
            <Label>{t('admin.users.role')}</Label>
            <Select value={effectiveNewRoleId} onValueChange={setNewRoleId}>
              <SelectTrigger className="w-40">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {roles?.map((role) => (
                  <SelectItem key={role.id} value={role.id}>
                    {role.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <Button
            size="sm"
            disabled={!canCreate || createMutation.isPending}
            onClick={() => createMutation.mutate()}
          >
            {t('admin.users.create')}
          </Button>
          <p className="w-full text-xs text-muted-foreground">{t('admin.users.passwordHint')}</p>
        </CardContent>
      </Card>

      <div className="flex flex-wrap gap-2">
        <Input
          className="max-w-xs"
          placeholder={t('common.search')}
          value={search}
          onChange={(e) => {
            setPage(1)
            setSearch(e.target.value)
          }}
        />
        <Select
          value={roleId || 'all'}
          onValueChange={(value) => {
            setPage(1)
            setRoleId(value === 'all' ? '' : value)
          }}
        >
          <SelectTrigger className="max-w-48">
            <SelectValue placeholder={t('admin.users.filterAll')} />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">{t('admin.users.filterAll')}</SelectItem>
            {roles?.map((role) => (
              <SelectItem key={role.id} value={role.id}>
                {role.name}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </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.users.userName')}
                sortKey="username"
                sort={sort}
                onToggle={sortColumn}
              />
              <SortHeader
                label={t('admin.users.role')}
                sortKey="role"
                sort={sort}
                onToggle={sortColumn}
              />
              <SortHeader
                label={t('admin.users.status')}
                sortKey="blocked"
                sort={sort}
                onToggle={sortColumn}
              />
              <SortHeader
                label={t('admin.users.createdAt')}
                sortKey="created"
                sort={sort}
                onToggle={sortColumn}
              />
              <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={5}>
                  {t('common.loading')}
                </td>
              </tr>
            )}
            {data?.items.map((user) => (
              <tr key={user.id} className="border-b border-border last:border-0">
                <td className="px-4 py-2">{user.userName}</td>
                <td className="px-4 py-2">
                  <Select
                    value={roles?.find((r) => r.name === user.role)?.id}
                    onValueChange={(newRoleId) =>
                      changeRoleMutation.mutate({ userId: user.id, roleId: newRoleId })
                    }
                  >
                    <SelectTrigger className="h-8 w-32">
                      <SelectValue>{user.role}</SelectValue>
                    </SelectTrigger>
                    <SelectContent>
                      {roles?.map((role) => (
                        <SelectItem key={role.id} value={role.id}>
                          {role.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </td>
                <td className="px-4 py-2">
                  {user.isBlocked ? (
                    <Badge variant="destructive">{t('admin.users.blocked')}</Badge>
                  ) : (
                    <Badge>{t('admin.users.active')}</Badge>
                  )}
                </td>
                <td className="px-4 py-2 text-muted-foreground">
                  {new Date(user.createdAt).toLocaleDateString()}
                </td>
                <td className="px-4 py-2">
                  <div className="flex gap-2">
                    {user.isBlocked ? (
                      <Button
                        size="sm"
                        variant="outline"
                        onClick={() => unblockMutation.mutate(user.id)}
                      >
                        {t('admin.users.unblock')}
                      </Button>
                    ) : (
                      <Button
                        size="sm"
                        variant="outline"
                        onClick={() => blockMutation.mutate(user.id)}
                      >
                        {t('admin.users.block')}
                      </Button>
                    )}
                    <Button size="sm" variant="outline" onClick={() => setResetTarget(user)}>
                      {t('admin.users.resetPassword')}
                    </Button>
                    <Button
                      size="sm"
                      variant="destructive"
                      onClick={() => deleteMutation.mutate(user.id)}
                    >
                      {t('common.delete')}
                    </Button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {totalPages > 1 && (
        <div className="flex items-center justify-center gap-2 text-sm">
          <Button
            size="sm"
            variant="outline"
            disabled={page <= 1}
            onClick={() => setPage((p) => p - 1)}
          >
            ‹
          </Button>
          <span>
            {page} / {totalPages}
          </span>
          <Button
            size="sm"
            variant="outline"
            disabled={page >= totalPages}
            onClick={() => setPage((p) => p + 1)}
          >
            ›
          </Button>
        </div>
      )}

      {resetTarget && (
        <ResetPasswordDialog
          user={resetTarget}
          onClose={() => setResetTarget(null)}
          onError={onError}
        />
      )}
    </div>
  )
}

function ResetPasswordDialog({
  user,
  onClose,
  onError,
}: Readonly<{
  user: UserSummaryDto
  onClose: () => void
  onError: (e: unknown) => void
}>) {
  const { t } = useTranslation()
  const [password, setPassword] = useState('')

  const reset = useMutation({
    mutationFn: () => resetUserPassword(user.id, password),
    onSuccess: () => {
      toast.success(t('admin.users.passwordReset'))
      onClose()
    },
    onError,
  })

  return (
    <Dialog open onOpenChange={(open) => !open && onClose()}>
      <DialogContent className="max-w-sm">
        <DialogHeader>
          <DialogTitle>{t('admin.users.resetPasswordFor', { name: user.userName })}</DialogTitle>
        </DialogHeader>
        <div className="flex flex-col gap-2">
          <Label>{t('admin.users.newPassword')}</Label>
          <Input
            type="password"
            autoFocus
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
          <p className="text-xs text-muted-foreground">{t('admin.users.passwordHint')}</p>
        </div>
        <DialogFooter>
          <Button variant="outline" size="sm" onClick={onClose}>
            {t('common.cancel')}
          </Button>
          <Button
            size="sm"
            disabled={password.length < 8 || reset.isPending}
            onClick={() => reset.mutate()}
          >
            {t('common.save')}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
