import type { FormEvent } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { ArrowDown, ArrowUp, ArrowUpDown, Loader2, Pencil, Search, Trash2, UserPlus, Users, X } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { ModuleHeader } from '@/components/ui/module-header';
import { NativeSelect } from '@/components/ui/native-select';
import { PageSkeleton } from '@/components/ui/page-skeleton';
import { TenantParentPicker } from '@/components/tenant-create/TenantParentPicker';
import { ImageUpload } from '@/components/common/ImageUpload';
import { useScopeContext } from '@/contexts/scope-context';
import { useAuth } from '@/contexts/useAuth';
import { useTenantChildren } from '@/business/scope/queries';
import { getAuthRoleLabel } from '@/business/auth/selectors';
import { useIamCapabilities } from '@/business/iam-capabilities/hooks';
import { usePermissions } from '@/hooks/usePermissions';
import {
  getRoleTenantInput,
  type RoleTenantInput,
} from '@/business/user-admin/selectors';
import {
  createOwnerWithOrganization,
  createUser,
  deleteUser,
  fileDownloadUrl,
  linkGuardianStudent,
  listPermissions,
  listRoles,
  listUsers,
  updateUser,
  type AdminUserRow,
  type RoleRow,
  type SaveUserData,
} from '@/business/user-admin/api';
import { USER_NAME_PREFIX_OPTIONS } from '@/shared/constants/users';
import { getErrorMessage } from '@/shared/errors/errorMessages';
import type { UserRole } from '@/shared/types/app';
import type { ParentLevel } from '@/business/tenant-create/selectors';
import { cn } from '@/lib/utils';

const USER_LIST_PAGE_SIZE = 10;
const USER_LIST_FETCH_LIMIT = 1000;

interface StatusMessage {
  readonly type: 'success' | 'error';
  readonly text: string;
}

type UserListSortField =
  | 'name'
  | 'email'
  | 'phoneNumber'
  | 'organization'
  | 'school'
  | 'campus'
  | 'role';

type UserListSortDirection = 'asc' | 'desc';

const TENANT_INPUT_TARGET: Record<Exclude<RoleTenantInput, 'none' | 'guardian'>, ParentLevel> = {
  org: 'organization',
  school: 'school',
  campus: 'campus',
  class: 'campus',
};

function userName(row: AdminUserRow): string {
  return [row.firstName, row.lastName].filter(Boolean).join(' ').trim() || row.email;
}

function locationName(value?: { name?: string | null } | null): string {
  return value?.name?.trim() || '—';
}

function sortText(value: string | null | undefined): string {
  return value?.trim().toLocaleLowerCase() || '';
}

function permissionLabel(name: string | null | undefined, id: string): string {
  return (name?.trim() || id).replace(/_/g, ' ');
}

export default function UserAdminPage() {
  const { tier, ownTenant } = useScopeContext();
  const { user } = useAuth();
  const queryClient = useQueryClient();
  const permissions = usePermissions();
  const capabilitiesQuery = useIamCapabilities();
  const rolesQuery = useQuery({ queryKey: ['roles'], queryFn: listRoles });
  const permissionsQuery = useQuery({ queryKey: ['permissions'], queryFn: listPermissions });
  const [usersPage, setUsersPage] = useState(0);
  const [usersSearchDraft, setUsersSearchDraft] = useState('');
  const [usersSearch, setUsersSearch] = useState('');
  const [usersSortField, setUsersSortField] = useState<UserListSortField>('name');
  const [usersSortDirection, setUsersSortDirection] = useState<UserListSortDirection>('asc');
  const usersQuery = useQuery({
    queryKey: ['admin-users', usersSearch],
    queryFn: () =>
      listUsers({
        query: usersSearch || undefined,
        limit: USER_LIST_FETCH_LIMIT,
        page: 0,
      }),
  });

  const manageableRoles = useMemo(
    () => capabilitiesQuery.data?.manageableRoleNames ?? [],
    [capabilitiesQuery.data],
  );
  const createRoleOptions = useMemo(
    () => manageableRoles.filter((item) => item !== 'super_admin'),
    [manageableRoles],
  );
  const currentRoleName = user?.app_role?.name ?? null;
  const canCreateUsers = permissions.has('CREATE_USERS');
  const canUpdateUsers = permissions.has('UPDATE_USERS');
  const canDeleteUsers = permissions.has('DELETE_USERS');
  const canEditPermissions = canCreateUsers || canUpdateUsers;


  // role name → id (for create/update payloads + student lookup).
  const roleIdByName = useMemo(() => {
    const map = new Map<string, string>();
    for (const r of rolesQuery.data?.rows ?? []) {
      if (r.name) map.set(r.name, r.id);
    }
    return map;
  }, [rolesQuery.data]);
  const roleById = useMemo(() => {
    const map = new Map<string, RoleRow>();
    for (const roleItem of rolesQuery.data?.rows ?? []) {
      map.set(roleItem.id, roleItem);
    }
    return map;
  }, [rolesQuery.data]);
  const allPermissions = useMemo(
    () =>
      [...(permissionsQuery.data?.rows ?? [])].sort((a, b) =>
        permissionLabel(a.name, a.id).localeCompare(permissionLabel(b.name, b.id)),
      ),
    [permissionsQuery.data],
  );

  const [editingId, setEditingId] = useState<string | null>(null);
  const [namePrefix, setNamePrefix] = useState('');
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [phoneNumber, setPhoneNumber] = useState('');
  const [email, setEmail] = useState('');
  const [avatar, setAvatar] = useState<string | null>(null);
  const [role, setRole] = useState<UserRole | ''>('');
  const [pickedTenantId, setPickedTenantId] = useState<string | null>(null);
  const [classId, setClassId] = useState('');
  const [studentIds, setStudentIds] = useState<string[]>([]);
  const [grantPerms, setGrantPerms] = useState<string[]>([]);
  const [excludePerms, setExcludePerms] = useState<string[]>([]);
  const [saving, setSaving] = useState(false);
  const [status, setStatus] = useState<StatusMessage | null>(null);

  const editingSuperAdmin = editingId !== null && role === 'super_admin';
  const roleOptions = editingSuperAdmin ? ['super_admin' as UserRole] : createRoleOptions;
  const selectedRole = editingSuperAdmin ? ('super_admin' as UserRole) : (role || roleOptions[0] || '');
  const selectedRoleId = selectedRole ? (roleIdByName.get(selectedRole) ?? null) : null;
  const selectedRoleRecord = selectedRoleId ? roleById.get(selectedRoleId) ?? null : null;
  const rolePermissionIds = useMemo(
    () => new Set((selectedRoleRecord?.permissions ?? []).map((item) => item.id)),
    [selectedRoleRecord],
  );
  const effectivePermissionIds = useMemo(() => {
    const ids = new Set(rolePermissionIds);
    for (const id of grantPerms) ids.add(id);
    for (const id of excludePerms) ids.delete(id);
    return ids;
  }, [excludePerms, grantPerms, rolePermissionIds]);
  const addablePermissions = useMemo(
    () => allPermissions.filter((permission) => !effectivePermissionIds.has(permission.id)),
    [allPermissions, effectivePermissionIds],
  );
  const excludablePermissions = useMemo(
    () => allPermissions.filter((permission) => effectivePermissionIds.has(permission.id)),
    [allPermissions, effectivePermissionIds],
  );
  const tenantInput = selectedRole ? getRoleTenantInput(selectedRole) : 'none';
  const canAutoCreateOwnerOrganization =
    selectedRole === 'owner' && capabilitiesQuery.data?.canCreateOwnerWithOrganization === true;
  const targetLevel =
    tenantInput === 'none' || tenantInput === 'guardian'
      ? null
      : TENANT_INPUT_TARGET[tenantInput];
  // Picker is only needed when the creator's own tier is above the target level.
  const needsPicker =
    targetLevel !== null && tier !== targetLevel && !canAutoCreateOwnerOrganization;
  const resolvedTenantId = needsPicker ? pickedTenantId : (ownTenant?.id ?? null);

  // Class options = children of the chosen/own campus.
  const campusForClass =
    tenantInput === 'class' ? (needsPicker ? pickedTenantId : ownTenant?.id ?? null) : null;
  const classQuery = useTenantChildren(
    campusForClass ? { level: 'campus', id: campusForClass } : null,
    { enabled: Boolean(campusForClass) },
  );

  // Students for guardian linking (role 'student' in the actor's scope).
  const studentRoleId = roleIdByName.get('student');
  const studentsQuery = useQuery({
    queryKey: ['admin-users', 'students', studentRoleId],
    queryFn: () => listUsers({ app_role: studentRoleId }),
    enabled: tenantInput === 'guardian' && Boolean(studentRoleId),
  });

  const handlePickerChange = useCallback((id: string | null) => {
    setPickedTenantId(id);
    setClassId('');
  }, []);

  const handleUsersSearchSubmit = useCallback((event: FormEvent) => {
    event.preventDefault();
    setUsersPage(0);
    setUsersSearch(usersSearchDraft.trim());
  }, [usersSearchDraft]);

  const clearUsersSearch = useCallback(() => {
    setUsersSearchDraft('');
    setUsersSearch('');
    setUsersPage(0);
  }, []);

  const toggleUsersSort = useCallback((field: UserListSortField) => {
    setUsersPage(0);
    if (field === usersSortField) {
      setUsersSortDirection((current) => (current === 'asc' ? 'desc' : 'asc'));
      return;
    }
    setUsersSortField(field);
    setUsersSortDirection('asc');
  }, [usersSortField]);

  const includePermission = useCallback((permissionId: string) => {
    setExcludePerms((current) => current.filter((id) => id !== permissionId));
    if (!rolePermissionIds.has(permissionId)) {
      setGrantPerms((current) =>
        current.includes(permissionId) ? current : [...current, permissionId],
      );
      return;
    }
    setGrantPerms((current) => current.filter((id) => id !== permissionId));
  }, [rolePermissionIds]);

  const excludePermission = useCallback((permissionId: string) => {
    if (rolePermissionIds.has(permissionId)) {
      setExcludePerms((current) =>
        current.includes(permissionId) ? current : [...current, permissionId],
      );
    } else {
      setGrantPerms((current) => current.filter((id) => id !== permissionId));
      setExcludePerms((current) => current.filter((id) => id !== permissionId));
    }
  }, [rolePermissionIds]);

  const fetchedRows = usersQuery.data?.rows;
  const sortedRows = useMemo(() => {
    const collator = new Intl.Collator(undefined, {
      numeric: true,
      sensitivity: 'base',
    });

    const valueForField = (row: AdminUserRow, field: UserListSortField): string => {
      switch (field) {
        case 'name':
          return sortText(userName(row));
        case 'email':
          return sortText(row.email);
        case 'phoneNumber':
          return sortText(row.phoneNumber);
        case 'organization':
          return sortText(locationName(row.organizations));
        case 'school':
          return sortText(locationName(row.school));
        case 'campus':
          return sortText(locationName(row.campus));
        case 'role':
          return sortText(
            row.app_role?.name ? getAuthRoleLabel(row.app_role.name as UserRole) : '—',
          );
      }
    };

    return [...(fetchedRows ?? [])].sort((left, right) => {
      const result = collator.compare(
        valueForField(left, usersSortField),
        valueForField(right, usersSortField),
      );

      if (result !== 0) {
        return usersSortDirection === 'asc' ? result : -result;
      }

      return collator.compare(sortText(userName(left)), sortText(userName(right)));
    });
  }, [fetchedRows, usersSortDirection, usersSortField]);
  const usersTotal = usersQuery.data?.count ?? sortedRows.length;
  const rows = useMemo(() => {
    const start = usersPage * USER_LIST_PAGE_SIZE;
    return sortedRows.slice(start, start + USER_LIST_PAGE_SIZE);
  }, [sortedRows, usersPage]);

  function resetForm() {
    setEditingId(null);
    setNamePrefix('');
    setFirstName('');
    setLastName('');
    setPhoneNumber('');
    setEmail('');
    setAvatar(null);
    setRole('');
    setPickedTenantId(null);
    setClassId('');
    setStudentIds([]);
    setGrantPerms([]);
    setExcludePerms([]);
  }

  function startEdit(row: AdminUserRow) {
    setEditingId(row.id);
    setNamePrefix(row.name_prefix ?? '');
    setFirstName(row.firstName ?? '');
    setLastName(row.lastName ?? '');
    setPhoneNumber(row.phoneNumber ?? '');
    setEmail(row.email);
    setAvatar(row.avatar?.[0]?.privateUrl ?? null);
    const roleName = row.app_role?.name;
    setRole(
      roleName === 'super_admin' || (roleName && manageableRoles.includes(roleName as UserRole))
        ? (roleName as UserRole)
        : '',
    );
    setPickedTenantId(null);
    setClassId('');
    setStudentIds([]);
    setGrantPerms((row.custom_permissions ?? []).map((p) => p.id));
    setExcludePerms((row.custom_permissions_filter ?? []).map((p) => p.id));
    setStatus(null);
  }

  function buildTenantPayload(): SaveUserData {
    if (tenantInput === 'org' && resolvedTenantId) return { organizations: resolvedTenantId };
    if (tenantInput === 'school' && resolvedTenantId) return { schoolId: resolvedTenantId };
    if (tenantInput === 'campus' && resolvedTenantId) return { campusId: resolvedTenantId };
    if (tenantInput === 'class') {
      return {
        ...(resolvedTenantId ? { campusId: resolvedTenantId } : {}),
        ...(classId ? { classId } : {}),
      };
    }
    return {};
  }

  async function handleSubmit(event: FormEvent) {
    event.preventDefault();
    setStatus(null);
    if (!selectedRole) return;

    if (needsPicker && !resolvedTenantId) {
      setStatus({ type: 'error', text: 'Please choose a tenant for this user.' });
      return;
    }
    if (tenantInput === 'class' && !classId) {
      setStatus({ type: 'error', text: 'Please choose a class.' });
      return;
    }

    const roleId = roleIdByName.get(selectedRole);

    const data: SaveUserData = {
      name_prefix: namePrefix === '' ? null : namePrefix,
      firstName: firstName.trim(),
      lastName: lastName.trim(),
      phoneNumber: phoneNumber.trim() || null,
      email: email.trim(),
      avatar,
      app_role: roleId ?? null,
      custom_permissions: grantPerms,
      custom_permissions_filter: excludePerms,
      ...buildTenantPayload(),
    };

    setSaving(true);
    try {
      if (editingId) {
        await updateUser(editingId, data);
      } else {
        const { id } = selectedRole === 'owner' && !data.organizations
          ? await createOwnerWithOrganization(data)
          : await createUser(data);
        if (tenantInput === 'guardian' && id && studentIds.length > 0) {
          await Promise.all(studentIds.map((sid) => linkGuardianStudent(id, sid)));
        }
      }
      await queryClient.invalidateQueries({ queryKey: ['admin-users'] });
      setUsersPage(0);
      setStatus({ type: 'success', text: editingId ? 'User updated.' : 'User created (invite sent).' });
      resetForm();
    } catch (error) {
      setStatus({ type: 'error', text: getErrorMessage(error, 'Could not save user') });
    } finally {
      setSaving(false);
    }
  }

  async function handleDelete(row: AdminUserRow) {
    setStatus(null);
    try {
      await deleteUser(row.id);
      await queryClient.invalidateQueries({ queryKey: ['admin-users'] });
      if (editingId === row.id) resetForm();
      if (rows.length === 1 && usersPage > 0) setUsersPage((page) => page - 1);
    } catch (error) {
      setStatus({ type: 'error', text: getErrorMessage(error, 'Could not delete user') });
    }
  }

  if (rolesQuery.isLoading || usersQuery.isLoading || capabilitiesQuery.isLoading) {
    return <PageSkeleton />;
  }
  const usersPageCount = Math.max(1, Math.ceil(usersTotal / USER_LIST_PAGE_SIZE));
  const usersStart = usersTotal === 0 ? 0 : usersPage * USER_LIST_PAGE_SIZE + 1;
  const usersEnd = Math.min(usersStart + rows.length - 1, usersTotal);
  const formControlClassName =
    'border-slate-600 bg-slate-950/80 text-slate-100 placeholder:text-slate-500 focus-visible:ring-sky-400 focus-visible:ring-offset-slate-950';
  const hasUsersSearch = usersSearch.length > 0;

  function renderSortIcon(field: UserListSortField) {
    if (usersSortField !== field) {
      return <ArrowUpDown className="h-3.5 w-3.5 text-slate-500" />;
    }
    if (usersSortDirection === 'asc') {
      return <ArrowUp className="h-3.5 w-3.5 text-sky-300" />;
    }
    return <ArrowDown className="h-3.5 w-3.5 text-sky-300" />;
  }

  return (
    <div className="space-y-6 px-3 py-4 md:px-4 md:py-5">
      <ModuleHeader
        title="Users"
        description="Create and manage users within your scope."
        icon={Users}
        iconClassName="bg-gradient-to-br from-sky-500 to-sky-700"
      />

      {(canCreateUsers || editingId) && (
      <Card className="border-slate-600/70 bg-slate-900/80 shadow-lg shadow-black/20">
        <CardHeader className="border-b border-slate-700/70 px-4 py-4 md:px-5">
          <CardTitle className="flex items-center gap-2 text-base text-slate-50">
            {editingId ? <Pencil size={16} /> : <UserPlus size={16} />}
            {editingId ? 'Edit user' : 'New user'}
            {editingId && (
              <Button
                type="button"
                variant="ghost"
                onClick={resetForm}
                className="ml-auto h-auto px-2 py-1 text-xs text-slate-400"
              >
                Cancel edit
              </Button>
            )}
          </CardTitle>
        </CardHeader>
        <CardContent className="px-4 pb-4 md:px-5">
          <form className="space-y-5 pt-6" onSubmit={handleSubmit}>
            <div className="rounded-lg border border-slate-600/80 bg-slate-950/45 p-4 space-y-4">
              <div>
                <p className="text-sm font-semibold text-slate-100">User details</p>
                <p className="mt-1 text-xs text-slate-300">
                  Basic identity fields used for login, invitations, and profile display.
                </p>
              </div>
              <div className="grid gap-4 sm:grid-cols-[auto_1fr]">
                <ImageUpload
                  value={avatar}
                  onChange={setAvatar}
                  table="users"
                  field="avatar"
                  label="Avatar"
                  shape="circle"
                />
                <div className="grid gap-4 sm:grid-cols-4">
                <div className="space-y-1.5">
                  <Label htmlFor="prefix" className="text-slate-100">Title</Label>
                  <NativeSelect
                    id="prefix"
                    value={namePrefix}
                    className={formControlClassName}
                    onChange={(e) => setNamePrefix(e.target.value)}
                  >
                    <option value="">None</option>
                    {USER_NAME_PREFIX_OPTIONS.map((o) => (
                      <option key={o.value} value={o.value}>{o.label}</option>
                    ))}
                  </NativeSelect>
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="firstName" className="text-slate-100">First name</Label>
                  <Input
                    id="firstName"
                    value={firstName}
                    className={formControlClassName}
                    onChange={(e) => setFirstName(e.target.value)}
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="lastName" className="text-slate-100">Last name</Label>
                  <Input
                    id="lastName"
                    value={lastName}
                    className={formControlClassName}
                    onChange={(e) => setLastName(e.target.value)}
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="email" className="text-slate-100">Email</Label>
                  <Input
                    id="email"
                    type="email"
                    value={email}
                    className={formControlClassName}
                    onChange={(e) => setEmail(e.target.value)}
                    required
                  />
                </div>
                <div className="space-y-1.5 sm:col-span-2">
                  <Label htmlFor="phoneNumber" className="text-slate-100">Phone number</Label>
                  <Input
                    id="phoneNumber"
                    type="tel"
                    value={phoneNumber}
                    className={formControlClassName}
                    onChange={(e) => setPhoneNumber(e.target.value)}
                  />
                </div>
                </div>
              </div>
            </div>

            <div className="rounded-lg border border-sky-400/50 bg-sky-950/35 p-4 space-y-4">
              <div>
                <p className="text-sm font-semibold text-slate-100">Access</p>
                <p className="mt-1 text-xs text-sky-100/85">
                  Choose the user's role and the organization or location where this account should work.
                </p>
              </div>

              <div className="space-y-1.5">
                <Label htmlFor="role" className="text-slate-100">Role</Label>
                <NativeSelect
                  id="role"
                  value={selectedRole}
                  disabled={editingSuperAdmin}
                  className={formControlClassName}
                  onChange={(e) => {
                    setRole(e.target.value as UserRole);
                    setPickedTenantId(null);
                    setClassId('');
                    setStudentIds([]);
                    setStatus(null);
                  }}
                >
                  {roleOptions.length === 0 ? (
                    <option value="">No available roles</option>
                  ) : (
                    roleOptions.map((r) => (
                      <option key={r} value={r}>{getAuthRoleLabel(r)}</option>
                    ))
                  )}
                </NativeSelect>
                {editingSuperAdmin && (
                  <p className="text-xs text-slate-300">
                    The platform has one Super Admin. This account can be updated, but its role cannot be reassigned.
                  </p>
                )}
              </div>

              {needsPicker && targetLevel && (
                <TenantParentPicker ownTier={tier} targetLevel={targetLevel} onChange={handlePickerChange} />
              )}

              {tenantInput === 'class' && (
                <div className="space-y-1.5">
                  <Label htmlFor="class" className="text-slate-100">Class</Label>
                  <NativeSelect
                    id="class"
                    value={classId}
                    disabled={!campusForClass}
                    className={formControlClassName}
                    onChange={(e) => setClassId(e.target.value)}
                  >
                    <option value="">Select class...</option>
                    {(classQuery.data?.rows ?? []).map((row) => (
                      <option key={row.id} value={row.id}>{row.name ?? row.id}</option>
                    ))}
                  </NativeSelect>
                </div>
              )}

              {tenantInput === 'guardian' && !editingId && (
                <div className="space-y-1.5">
                  <Label className="text-slate-100">Students</Label>
                  <div className="max-h-40 space-y-1 overflow-y-auto rounded-lg border border-slate-600 bg-slate-950/60 p-2">
                    {(studentsQuery.data?.rows ?? []).length === 0 ? (
                      <p className="text-xs text-slate-300">No students found in your scope.</p>
                    ) : (
                      (studentsQuery.data?.rows ?? []).map((s) => (
                        <label key={s.id} className="flex items-center gap-2 text-sm text-slate-100">
                          <input
                            type="checkbox"
                            checked={studentIds.includes(s.id)}
                            onChange={(e) =>
                              setStudentIds((prev) =>
                                e.target.checked ? [...prev, s.id] : prev.filter((x) => x !== s.id),
                              )
                            }
                          />
                          {userName(s)}
                        </label>
                      ))
                    )}
                  </div>
                </div>
              )}
            </div>

            {canEditPermissions && selectedRole !== 'super_admin' && (
            <details className="rounded-lg border border-slate-600/80 bg-slate-950/45 p-4">
              <summary className="cursor-pointer text-sm font-semibold text-slate-100">
                Advanced permissions (optional)
              </summary>
              <p className="mt-2 mb-3 text-xs text-slate-300">
                Add permissions on top of the role, or exclude permissions the role would grant. The role's
                base permissions apply automatically.
              </p>
              <div className="grid gap-4 sm:grid-cols-2">
                <div className="space-y-1.5">
                  <Label htmlFor="grant-perms" className="text-slate-100">Add permissions</Label>
                  <div
                    id="grant-perms"
                    className="max-h-[26rem] min-h-[8rem] space-y-1 overflow-y-auto rounded-md border border-slate-600 bg-slate-950/80 p-2"
                  >
                    {addablePermissions.length === 0 ? (
                      <p className="px-2 py-1 text-xs text-slate-400">No additional permissions available.</p>
                    ) : (
                      addablePermissions.map((permission) => (
                        <button
                          key={permission.id}
                          type="button"
                          onClick={() => includePermission(permission.id)}
                          className={cn(
                            'flex w-full items-center justify-between rounded-md px-2 py-1.5 text-left text-sm text-slate-200 transition',
                            'hover:bg-emerald-500/15 hover:text-emerald-100',
                          )}
                        >
                          <span className="truncate">{permissionLabel(permission.name, permission.id)}</span>
                          <span className="ml-3 shrink-0 text-xs text-emerald-300">Add</span>
                        </button>
                      ))
                    )}
                  </div>
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="exclude-perms" className="text-slate-100">Exclude permissions</Label>
                  <div
                    id="exclude-perms"
                    className="max-h-[26rem] min-h-[8rem] space-y-1 overflow-y-auto rounded-md border border-slate-600 bg-slate-950/80 p-2"
                  >
                    {excludablePermissions.length === 0 ? (
                      <p className="px-2 py-1 text-xs text-slate-400">No effective permissions to exclude.</p>
                    ) : (
                      excludablePermissions.map((permission) => (
                        <button
                          key={permission.id}
                          type="button"
                          onClick={() => excludePermission(permission.id)}
                          className={cn(
                            'flex w-full items-center justify-between rounded-md px-2 py-1.5 text-left text-sm text-slate-100 transition',
                            'hover:bg-amber-500/15 hover:text-amber-100',
                          )}
                        >
                          <span className="truncate">{permissionLabel(permission.name, permission.id)}</span>
                          <span className="ml-3 shrink-0 text-xs text-amber-300">Exclude</span>
                        </button>
                      ))
                    )}
                  </div>
                </div>
              </div>
            </details>
            )}

            {status && (
              <div
                className={`rounded-lg border px-3 py-2 text-sm ${
                  status.type === 'success'
                    ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-200'
                    : 'border-red-500/30 bg-red-500/10 text-red-200'
                }`}
              >
                {status.text}
              </div>
            )}

            <div className="flex justify-end">
              <Button
                type="submit"
                disabled={saving || (editingId ? !canUpdateUsers : !canCreateUsers)}
              >
                {saving && <Loader2 size={16} className="mr-2 animate-spin" />}
                {editingId ? 'Save changes' : 'Create user'}
              </Button>
            </div>
          </form>
        </CardContent>
      </Card>
      )}

      <Card>
        <CardHeader className="px-4 py-4 md:px-5">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <CardTitle className="text-base">Users ({usersTotal})</CardTitle>
            {usersTotal > 0 && (
              <p className="text-xs text-slate-400">
                Showing {usersStart}-{usersEnd} of {usersTotal}
              </p>
            )}
          </div>
        </CardHeader>
        <CardContent className="space-y-4 px-4 pb-4 md:px-5">
          <form
            className="flex flex-col gap-3 rounded-lg border border-slate-700/60 bg-slate-950/35 p-3 md:flex-row md:items-center"
            onSubmit={handleUsersSearchSubmit}
          >
            <div className="relative flex-1">
              <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-500" />
              <Input
                value={usersSearchDraft}
                onChange={(event) => setUsersSearchDraft(event.target.value)}
                placeholder="Search by name, email, phone, organization, school, campus, or role"
                className="pl-9"
              />
            </div>
            <div className="flex items-center gap-2">
              <Button type="submit" variant="outline" disabled={usersQuery.isFetching}>
                Search
              </Button>
              <Button
                type="button"
                variant="ghost"
                disabled={!hasUsersSearch && usersSearchDraft.length === 0}
                onClick={clearUsersSearch}
              >
                <X className="mr-2 h-4 w-4" />
                Clear
              </Button>
            </div>
          </form>

          {rows.length === 0 ? (
            <p className="text-sm text-slate-400">
              {hasUsersSearch ? 'No users match the current search.' : 'No users yet.'}
            </p>
          ) : (
            <div className="overflow-x-auto rounded-lg border border-slate-700/60">
              <table className="min-w-full divide-y divide-slate-700/60 text-sm">
                <thead className="bg-slate-950/60 text-left text-xs uppercase tracking-wide text-slate-400">
                  <tr>
                    {([
                      ['name', 'User'],
                      ['email', 'Email'],
                      ['phoneNumber', 'Phone'],
                      ['organization', 'Organization'],
                      ['school', 'School'],
                      ['campus', 'Campus'],
                      ['role', 'Role'],
                    ] as const).map(([field, label]) => (
                      <th key={field} className="px-3 py-3 font-medium">
                        <button
                          type="button"
                          onClick={() => toggleUsersSort(field)}
                          className="inline-flex items-center gap-1.5 text-left text-slate-300 transition hover:text-white"
                        >
                          <span>{label}</span>
                          {renderSortIcon(field)}
                        </button>
                      </th>
                    ))}
                    <th className="w-[88px] px-3 py-3 text-right font-medium text-slate-300">Actions</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-slate-700/50 bg-slate-950/20">
                  {rows.map((row) => {
                    const roleName = row.app_role?.name;
                    const isSuperAdminRow = roleName === 'super_admin';
                    const manageable = roleName ? manageableRoles.includes(roleName as UserRole) : true;
                    const canEditRow =
                      canUpdateUsers
                      && (manageable || (isSuperAdminRow && currentRoleName === 'super_admin'));
                    const canDeleteRow = canDeleteUsers && manageable && !isSuperAdminRow;

                    return (
                      <tr key={row.id} className="align-middle">
                        <td className="px-3 py-2.5">
                          <div className="flex min-w-[180px] items-center gap-3">
                            <div className="flex h-9 w-9 shrink-0 items-center justify-center overflow-hidden rounded-full border border-slate-700 bg-slate-800 text-[11px] font-semibold text-slate-300">
                              {row.avatar?.[0]?.privateUrl ? (
                                <img
                                  src={fileDownloadUrl(row.avatar[0].privateUrl)}
                                  alt=""
                                  className="h-full w-full object-cover"
                                />
                              ) : (
                                userName(row).slice(0, 2).toUpperCase()
                              )}
                            </div>
                            <div className="min-w-0">
                              <p className="truncate font-medium text-slate-100">{userName(row)}</p>
                            </div>
                          </div>
                        </td>
                        <td className="px-3 py-2.5 text-slate-300 break-all">{row.email || '—'}</td>
                        <td className="px-3 py-2.5 text-slate-300">{row.phoneNumber || '—'}</td>
                        <td className="px-3 py-2.5 text-slate-300">{locationName(row.organizations)}</td>
                        <td className="px-3 py-2.5 text-slate-300">{locationName(row.school)}</td>
                        <td className="px-3 py-2.5 text-slate-300">{locationName(row.campus)}</td>
                        <td className="px-3 py-2.5 text-slate-300">
                          {roleName ? getAuthRoleLabel(roleName as UserRole) : '—'}
                        </td>
                        <td className="px-3 py-2.5">
                          <div className="flex items-center justify-end gap-1">
                            <Button
                              type="button"
                              variant="ghost"
                              disabled={!canEditRow}
                              onClick={() => startEdit(row)}
                              className="h-8 w-8 px-0"
                              title="Edit"
                              aria-label={`Edit ${userName(row)}`}
                            >
                              <Pencil className="h-3.5 w-3.5" />
                            </Button>
                            <Button
                              type="button"
                              variant="ghost"
                              disabled={!canDeleteRow}
                              onClick={() => handleDelete(row)}
                              className="h-8 w-8 px-0 text-red-400 hover:bg-red-500/10"
                              title="Delete"
                              aria-label={`Delete ${userName(row)}`}
                            >
                              <Trash2 className="h-3.5 w-3.5" />
                            </Button>
                          </div>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}
          {usersPageCount > 1 && (
            <div className="mt-4 flex flex-wrap items-center justify-between gap-3 border-t border-slate-700/50 pt-4">
              <p className="text-xs text-slate-400">
                Page {usersPage + 1} of {usersPageCount}
              </p>
              <div className="flex items-center gap-2">
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  disabled={usersPage === 0 || usersQuery.isFetching}
                  onClick={() => setUsersPage((page) => Math.max(0, page - 1))}
                >
                  Previous
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  disabled={usersPage >= usersPageCount - 1 || usersQuery.isFetching}
                  onClick={() => setUsersPage((page) => Math.min(usersPageCount - 1, page + 1))}
                >
                  Next
                </Button>
              </div>
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
