'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { Ban, Crown, FileText, KeyRound, Loader2, Search, ShieldPlus, UserCheck, UserCog } from 'lucide-react';
import { UserDocumentsDialog } from '@/components/documents/user-documents-dialog';
import { AdminShell } from '@/components/id/admin-shell';
import { useAuth } from '@/components/id/auth-provider';
import { useToast } from '@/components/id/toast-provider';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { AdminRole, AdminUser, apiFetch } from '@/lib/api';

const statusLabels: Record<string, string> = {
  ACTIVE: 'Активен',
  SUSPENDED: 'Заблокирован',
  DELETED: 'Удалён'
};

const roleLabels: Record<string, string> = {
  admin: 'Администратор',
  moderator: 'Модератор',
  manager: 'Менеджер',
  'super-admin': 'Супер-админ'
};

export default function AdminUsersPage() {
  const { token, user: currentUser } = useAuth();
  const { showToast } = useToast();
  const [users, setUsers] = useState<AdminUser[]>([]);
  const [roles, setRoles] = useState<AdminRole[]>([]);
  const [search, setSearch] = useState('');
  const [loading, setLoading] = useState(true);
  const [selectedUser, setSelectedUser] = useState<AdminUser | null>(null);
  const [password, setPassword] = useState('');
  const [actionLoading, setActionLoading] = useState(false);
  const [dialog, setDialog] = useState<'password' | 'roles' | null>(null);
  const [documentsUser, setDocumentsUser] = useState<AdminUser | null>(null);

  const loadUsers = useCallback(async () => {
    if (!token) return;
    setLoading(true);
    try {
      const response = await apiFetch<{ users: AdminUser[] }>(`/admin/users${search ? `?search=${encodeURIComponent(search)}` : ''}`, {}, token);
      setUsers(response.users ?? []);
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось загрузить пользователей');
    } finally {
      setLoading(false);
    }
  }, [search, showToast, token]);

  useEffect(() => {
    void loadUsers();
  }, [loadUsers]);

  useEffect(() => {
    if (!token || !currentUser?.canManageRoles) return;
    apiFetch<{ roles: AdminRole[] }>('/admin/rbac/roles', {}, token)
      .then((response) => setRoles(response.roles ?? []))
      .catch(() => undefined);
  }, [currentUser?.canManageRoles, token]);

  const assignableRoles = useMemo(() => roles.filter((role) => role.slug !== 'super-admin'), [roles]);

  async function handleSuspend(user: AdminUser) {
    if (!token) return;
    setActionLoading(true);
    try {
      await apiFetch(`/admin/users/${user.id}/suspend`, { method: 'POST' }, token);
      showToast('Пользователь заблокирован');
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось заблокировать пользователя');
    } finally {
      setActionLoading(false);
    }
  }

  async function handleUnsuspend(user: AdminUser) {
    if (!token) return;
    setActionLoading(true);
    try {
      await apiFetch(`/admin/users/${user.id}`, {
        method: 'PATCH',
        body: JSON.stringify({ status: 'ACTIVE' })
      }, token);
      showToast('Пользователь разблокирован');
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось разблокировать пользователя');
    } finally {
      setActionLoading(false);
    }
  }

  async function handleResetPassword() {
    if (!token || !selectedUser || password.length < 8) return;
    setActionLoading(true);
    try {
      await apiFetch(`/admin/users/${selectedUser.id}/reset-password`, { method: 'POST', body: JSON.stringify({ newPassword: password }) }, token);
      showToast('Пароль обновлён');
      setDialog(null);
      setPassword('');
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось сбросить пароль');
    } finally {
      setActionLoading(false);
    }
  }

  async function handleToggleSuperAdmin(user: AdminUser) {
    if (!token || !currentUser?.canManageRoles) return;
    setActionLoading(true);
    try {
      await apiFetch(`/admin/users/${user.id}/super-admin`, {
        method: 'PATCH',
        body: JSON.stringify({ isSuperAdmin: !user.isSuperAdmin })
      }, token);
      showToast(user.isSuperAdmin ? 'Права супер-админа сняты' : 'Пользователь назначен супер-админом');
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось изменить права');
    } finally {
      setActionLoading(false);
    }
  }

  async function handleAssignRole(roleSlug: string) {
    if (!token || !selectedUser) return;
    setActionLoading(true);
    try {
      const response = await apiFetch<{ roles: string[] }>(`/admin/rbac/users/${selectedUser.id}/roles`, {
        method: 'POST',
        body: JSON.stringify({ roleSlug })
      }, token);
      setSelectedUser({ ...selectedUser, roles: response.roles ?? [] });
      showToast('Роль назначена');
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось назначить роль');
    } finally {
      setActionLoading(false);
    }
  }

  async function handleRemoveRole(roleSlug: string) {
    if (!token || !selectedUser) return;
    setActionLoading(true);
    try {
      await apiFetch(`/admin/rbac/users/${selectedUser.id}/roles/${roleSlug}`, { method: 'DELETE' }, token);
      setSelectedUser({ ...selectedUser, roles: (selectedUser.roles ?? []).filter((role) => role !== roleSlug) });
      showToast('Роль снята');
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось снять роль');
    } finally {
      setActionLoading(false);
    }
  }

  function renderRoles(user: AdminUser) {
    const userRoles = user.roles ?? [];
    const labels = user.isSuperAdmin ? ['Супер-админ', ...userRoles.map((role) => roleLabels[role] ?? role)] : userRoles.map((role) => roleLabels[role] ?? role);
    if (!labels.length) return 'Пользователь';
    return labels.join(', ');
  }

  return (
    <AdminShell active="/admin/users">
      <div className="mb-6 flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
        <div>
          <h2 className="text-2xl font-medium">Пользователи</h2>
          <p className="text-sm text-[#667085]">Поиск, блокировка, сброс пароля и управление доступом</p>
        </div>
        <div className="relative w-full max-w-sm">
          <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#667085]" />
          <Input value={search} onChange={(event) => setSearch(event.target.value)} placeholder="Поиск по имени, почте или телефону" className="pl-10" />
        </div>
      </div>

      <div className="overflow-hidden rounded-[24px] border border-[#eceef4] bg-white">
        {loading ? (
          <div className="flex items-center justify-center gap-2 py-16 text-[#667085]">
            <Loader2 className="h-5 w-5 animate-spin" />
            Загрузка...
          </div>
        ) : (
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Пользователь</TableHead>
                <TableHead>Телефон</TableHead>
                <TableHead>Роли</TableHead>
                <TableHead>Статус</TableHead>
                <TableHead className="text-right">Действия</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {users.map((user) => (
                <TableRow key={user.id}>
                  <TableCell>
                    <div className="font-medium">{user.displayName}</div>
                    <div className="text-sm text-[#667085]">{user.email ?? user.username ?? '—'}</div>
                  </TableCell>
                  <TableCell>{user.phone ?? '—'}</TableCell>
                  <TableCell>{renderRoles(user)}</TableCell>
                  <TableCell>
                    <span className="rounded-full bg-[#f4f5f8] px-3 py-1 text-xs font-semibold">{statusLabels[user.status] ?? user.status}</span>
                  </TableCell>
                  <TableCell>
                    <div className="flex justify-end gap-2">
                      {currentUser?.canManageUsers ? (
                        <>
                          <Button
                            variant="secondary"
                            size="icon"
                            aria-label="Сбросить пароль"
                            disabled={actionLoading}
                            onClick={() => {
                              setSelectedUser(user);
                              setPassword('');
                              setDialog('password');
                            }}
                          >
                            <KeyRound className="h-4 w-4" />
                          </Button>
                          <Button variant="secondary" size="icon" aria-label="Заблокировать" disabled={actionLoading || user.status === 'SUSPENDED'} onClick={() => void handleSuspend(user)}>
                            <Ban className="h-4 w-4" />
                          </Button>
                          <Button variant="secondary" size="icon" aria-label="Разблокировать" disabled={actionLoading || user.status !== 'SUSPENDED'} onClick={() => void handleUnsuspend(user)}>
                            <UserCheck className="h-4 w-4" />
                          </Button>
                        </>
                      ) : null}
                      {currentUser?.canViewUserDocuments ? (
                        <Button
                          variant="secondary"
                          size="icon"
                          aria-label="Документы пользователя"
                          disabled={actionLoading}
                          onClick={() => setDocumentsUser(user)}
                        >
                          <FileText className="h-4 w-4" />
                        </Button>
                      ) : null}
                      {currentUser?.canManageRoles ? (
                        <>
                          <Button
                            variant="secondary"
                            size="icon"
                            aria-label="Управление ролями"
                            disabled={actionLoading}
                            onClick={() => {
                              setSelectedUser(user);
                              setDialog('roles');
                            }}
                          >
                            <UserCog className="h-4 w-4" />
                          </Button>
                          <Button
                            variant={user.isSuperAdmin ? 'default' : 'secondary'}
                            size="icon"
                            aria-label="Супер-админ"
                            disabled={actionLoading || user.id === currentUser?.id}
                            onClick={() => void handleToggleSuperAdmin(user)}
                          >
                            <Crown className="h-4 w-4" />
                          </Button>
                        </>
                      ) : null}
                    </div>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        )}
      </div>

      <Dialog open={dialog === 'password'} onOpenChange={(open) => !open && setDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Сброс пароля</DialogTitle>
          </DialogHeader>
          <p className="mb-4 text-sm text-[#667085]">Новый пароль для {selectedUser?.displayName}</p>
          <Input type="password" value={password} onChange={(event) => setPassword(event.target.value)} placeholder="Минимум 8 символов" />
          <Button className="mt-4 w-full" disabled={actionLoading || password.length < 8} onClick={() => void handleResetPassword()}>
            {actionLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : 'Сохранить пароль'}
          </Button>
        </DialogContent>
      </Dialog>

      <Dialog open={dialog === 'roles'} onOpenChange={(open) => !open && setDialog(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Роли и доступ</DialogTitle>
          </DialogHeader>
          <p className="mb-4 text-sm text-[#667085]">{selectedUser?.displayName}</p>
          <div className="space-y-2">
            {(selectedUser?.roles ?? []).map((role) => (
              <div key={role} className="flex items-center justify-between rounded-xl bg-[#f4f5f8] px-3 py-2">
                <span>{roleLabels[role] ?? role}</span>
                <Button variant="ghost" size="sm" disabled={actionLoading} onClick={() => void handleRemoveRole(role)}>
                  Снять
                </Button>
              </div>
            ))}
            {!(selectedUser?.roles ?? []).length ? <p className="text-sm text-[#667085]">Роли не назначены</p> : null}
          </div>
          <div className="mt-4 space-y-2">
            <p className="text-sm font-medium">Назначить роль</p>
            {assignableRoles.map((role) => (
              <Button
                key={role.id}
                variant="secondary"
                className="w-full justify-start"
                disabled={actionLoading || (selectedUser?.roles ?? []).includes(role.slug)}
                onClick={() => void handleAssignRole(role.slug)}
              >
                <ShieldPlus className="mr-2 h-4 w-4" />
                {role.name}
              </Button>
            ))}
          </div>
        </DialogContent>
      </Dialog>

      {documentsUser ? (
        <UserDocumentsDialog
          open={Boolean(documentsUser)}
          onOpenChange={(open) => {
            if (!open) setDocumentsUser(null);
          }}
          targetUserId={documentsUser.id}
          targetUserName={documentsUser.displayName}
          token={token}
        />
      ) : null}
    </AdminShell>
  );
}
