'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import { Ban, BadgeCheck, Crown, FileText, KeyRound, Loader2, Search, ShieldOff, ShieldPlus, UserCheck, UserCog } from 'lucide-react';
import { VerificationBadge } from '@/components/id/verification-badge';
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 { AdminPermission, AdminRole, AdminUser, adminDisableUserTotp, apiFetch, fetchUserTotpStatus } from '@/lib/api';
import { getAdminLandingPath } from '@/lib/admin-access';
import { DEFAULT_VERIFICATION_ICON, VERIFICATION_ICON_OPTIONS } from '@/lib/verification-icons';

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

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

const DEFAULT_USER_ROLE = 'user';

export default function AdminUsersPage() {
  const router = useRouter();
  const { token, user: currentUser } = useAuth();
  const { showToast } = useToast();
  const [users, setUsers] = useState<AdminUser[]>([]);
  const [roles, setRoles] = useState<AdminRole[]>([]);
  const [permissions, setPermissions] = useState<AdminPermission[]>([]);
  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' | 'verification' | null>(null);
  const [documentsUser, setDocumentsUser] = useState<AdminUser | null>(null);
  const [verificationIcon, setVerificationIcon] = useState(DEFAULT_VERIFICATION_ICON);

  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(() => {
    if (!currentUser) return;
    if (!currentUser.canViewUsers && !currentUser.canManageUsers) {
      router.replace(getAdminLandingPath(currentUser));
    }
  }, [currentUser, router]);

  useEffect(() => {
    if (!currentUser?.canViewUsers && !currentUser?.canManageUsers) return;
    void loadUsers();
  }, [currentUser?.canManageUsers, currentUser?.canViewUsers, loadUsers]);

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

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

  const permissionLabelBySlug = useMemo(
    () => Object.fromEntries(permissions.map((permission) => [permission.slug, permission.name])),
    [permissions]
  );

  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);
    }
  }

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

  async function handleRemovePermission(permissionSlug: string) {
    if (!token || !selectedUser) return;
    setActionLoading(true);
    try {
      const response = await apiFetch<{ permissions: string[] }>(`/admin/rbac/users/${selectedUser.id}/permissions/${permissionSlug}`, {
        method: 'DELETE'
      }, token);
      setSelectedUser({ ...selectedUser, directPermissions: response.permissions ?? [] });
      showToast('Право снято');
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось снять право');
    } finally {
      setActionLoading(false);
    }
  }

  async function handleSaveVerification() {
    if (!token || !selectedUser) return;
    setActionLoading(true);
    try {
      const updated = await apiFetch<AdminUser>(`/admin/users/${selectedUser.id}/verification`, {
        method: 'PATCH',
        body: JSON.stringify({
          isVerified: true,
          verificationIcon
        })
      }, token);
      showToast('Пользователь верифицирован');
      setSelectedUser(updated);
      setDialog(null);
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось верифицировать пользователя');
    } finally {
      setActionLoading(false);
    }
  }

  async function handleRemoveVerification() {
    if (!token || !selectedUser) return;
    setActionLoading(true);
    try {
      await apiFetch<AdminUser>(`/admin/users/${selectedUser.id}/verification`, {
        method: 'PATCH',
        body: JSON.stringify({ isVerified: false })
      }, token);
      showToast('Верификация снята');
      setSelectedUser({ ...selectedUser, isVerified: false, verificationIcon: undefined });
      setDialog(null);
      await loadUsers();
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось снять верификацию');
    } finally {
      setActionLoading(false);
    }
  }

  function openVerificationDialog(user: AdminUser) {
    setSelectedUser(user);
    setVerificationIcon(user.verificationIcon ?? DEFAULT_VERIFICATION_ICON);
    setDialog('verification');
  }

  async function handleAdminDisableTotp(user: AdminUser) {
    if (!token || !currentUser?.isSuperAdmin) return;
    setActionLoading(true);
    try {
      const status = await fetchUserTotpStatus(user.id, token);
      if (!status.isEnabled) {
        showToast('У пользователя не включена двухфакторная аутентификация');
        return;
      }
      const confirmed = window.confirm(`Отключить 2FA для ${user.displayName}? Пользователю не потребуется код из приложения-аутентификатора.`);
      if (!confirmed) return;
      await adminDisableUserTotp(user.id, token);
      showToast('Двухфакторная аутентификация отключена');
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Не удалось отключить 2FA');
    } finally {
      setActionLoading(false);
    }
  }

  function renderRoles(user: AdminUser) {
    if (user.isBot) {
      return roleLabels.bot;
    }
    const userRoles = user.roles ?? [];
    const extraRoles = userRoles.filter((role) => role !== DEFAULT_USER_ROLE && role !== 'bot');
    const direct = user.directPermissions ?? [];
    const labels = user.isSuperAdmin
      ? ['Супер-админ', ...extraRoles.map((role) => roleLabels[role] ?? role)]
      : extraRoles.map((role) => roleLabels[role] ?? role);
    const directLabels = direct.map((slug) => permissionLabelBySlug[slug] ?? slug);
    const parts = [...labels, ...directLabels.map((label) => `+ ${label}`)];
    if (!parts.length) return roleLabels.user;
    return parts.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="flex items-center gap-2">
                      <span className="font-medium">{user.displayName}</span>
                      {user.isVerified ? <VerificationBadge verificationIcon={user.verificationIcon} size="xs" /> : null}
                    </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 && !user.isBot ? (
                        <Button
                          variant="secondary"
                          size="icon"
                          aria-label="Документы пользователя"
                          disabled={actionLoading}
                          onClick={() => setDocumentsUser(user)}
                        >
                          <FileText className="h-4 w-4" />
                        </Button>
                      ) : null}
                      {currentUser?.isSuperAdmin && !user.isBot ? (
                        <Button
                          variant="secondary"
                          size="icon"
                          aria-label="Отключить 2FA"
                          disabled={actionLoading}
                          onClick={() => void handleAdminDisableTotp(user)}
                        >
                          <ShieldOff className="h-4 w-4" />
                        </Button>
                      ) : null}
                      {currentUser?.canVerifyUsers ? (
                        <Button
                          variant={user.isVerified ? 'default' : 'secondary'}
                          size="icon"
                          aria-label="Верификация"
                          disabled={actionLoading}
                          onClick={() => openVerificationDialog(user)}
                        >
                          <BadgeCheck 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}{role === DEFAULT_USER_ROLE ? ' (стандартная)' : ''}</span>
                {role === DEFAULT_USER_ROLE ? (
                  <span className="text-xs text-[#667085]">Нельзя снять</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>
          <div className="mt-6 space-y-2 border-t border-[#eceef4] pt-4">
            <p className="text-sm font-medium">Прямые права</p>
            <p className="text-xs text-[#667085]">Дополнительные permissions без смены роли. Например, oauth.manage для одного пользователя.</p>
            {(selectedUser?.directPermissions ?? []).map((permissionSlug) => (
              <div key={permissionSlug} className="flex items-center justify-between rounded-xl bg-[#eef4ff] px-3 py-2">
                <span className="text-sm">{permissionLabelBySlug[permissionSlug] ?? permissionSlug}</span>
                <Button variant="ghost" size="sm" disabled={actionLoading} onClick={() => void handleRemovePermission(permissionSlug)}>
                  Снять
                </Button>
              </div>
            ))}
            {!(selectedUser?.directPermissions ?? []).length ? (
              <p className="text-sm text-[#667085]">Прямые права не назначены</p>
            ) : null}
            <div className="max-h-48 space-y-1 overflow-y-auto pt-2">
              {permissions
                .filter((permission) => !(selectedUser?.directPermissions ?? []).includes(permission.slug))
                .map((permission) => (
                  <Button
                    key={permission.id}
                    variant="secondary"
                    size="sm"
                    className="w-full justify-start"
                    disabled={actionLoading}
                    onClick={() => void handleAssignPermission(permission.slug)}
                  >
                    + {permission.name}
                  </Button>
                ))}
            </div>
          </div>
        </DialogContent>
      </Dialog>

      <Dialog open={dialog === 'verification'} onOpenChange={(open) => !open && setDialog(null)}>
        <DialogContent className="max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Верификация пользователя</DialogTitle>
          </DialogHeader>
          <p className="mb-4 text-sm text-[#667085]">{selectedUser?.displayName}</p>
          {selectedUser?.isVerified ? (
            <div className="mb-4 flex items-center gap-2 rounded-xl bg-[#eef4ff] px-3 py-2 text-sm">
              <VerificationBadge verificationIcon={selectedUser.verificationIcon} size="sm" />
              <span>Пользователь уже верифицирован</span>
            </div>
          ) : null}
          <div className="space-y-3">
            <p className="text-sm font-medium">Выберите значок</p>
            <div className="grid grid-cols-5 gap-2">
              {VERIFICATION_ICON_OPTIONS.map((option) => (
                <button
                  key={option.slug}
                  type="button"
                  className={`flex flex-col items-center gap-1 rounded-xl border px-2 py-3 text-xs transition ${
                    verificationIcon === option.slug ? 'border-[#3390ec] bg-[#eef4ff]' : 'border-[#eceef4] bg-[#fafbfd] hover:bg-[#f4f5f8]'
                  }`}
                  onClick={() => setVerificationIcon(option.slug)}
                >
                  <option.Icon className="h-5 w-5 text-[#3390ec]" />
                  <span className="text-center leading-tight">{option.name}</span>
                </button>
              ))}
            </div>
          </div>
          <div className="mt-4 flex flex-col gap-2">
            <Button className="w-full" disabled={actionLoading} onClick={() => void handleSaveVerification()}>
              {actionLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : selectedUser?.isVerified ? 'Обновить значок' : 'Верифицировать'}
            </Button>
            {selectedUser?.isVerified ? (
              <Button variant="secondary" className="w-full text-red-600" disabled={actionLoading} onClick={() => void handleRemoveVerification()}>
                Снять верификацию
              </Button>
            ) : null}
          </div>
        </DialogContent>
      </Dialog>

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