'use client';

import { FormEvent, useEffect, useRef, useState } from 'react';
import { ChevronLeft, ChevronRight, Plus, RefreshCw, Search, Users } from 'lucide-react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { GeographyFields, GeographyFilterCards } from './GeographyFields';
import { BvasReportDetailsModal } from './BvasReportPresentation';
import { EMPTY_GEOGRAPHY, GEOGRAPHY_LEVELS, GeographySelection } from '@/lib/geography';
import {
  EMPTY_USER_FILTERS, FieldErrors, ManagedUser, USER_ROLES, ROLE_SCOPE, ROLE_PARENT_FIELD,
  USER_STATUSES, UserFilters, UserPage, UserPayload, isManagedUser, isRecord,
  isUserPage, userLabel, validateUserPayload, validateUserQuery,
} from '@/lib/users';

const inputStyle = 'w-full min-h-11 rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 focus:outline-none focus:ring-2 focus:ring-emerald-700 disabled:bg-slate-100';
const buttonStyle = 'inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-slate-300 px-4 py-2 text-sm font-semibold hover:bg-slate-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-emerald-700 disabled:cursor-not-allowed disabled:opacity-50';
const primaryStyle = `${buttonStyle} border-emerald-800 bg-emerald-800 text-white hover:bg-emerald-900`;
const EMPTY_FORM: UserPayload = {
  name: '', email: null, phone_number: '', password: '', role: 'PU_AGENT',
  status: 'ACTIVE',
};

class UsersRequestError extends Error {
  constructor(message: string, readonly fields: FieldErrors = {}) {
    super(message);
  }
}

async function requestUsers(url: string, options: RequestInit): Promise<unknown> {
  const response = await fetch(url, { ...options, cache: 'no-store' });
  if (response.status === 204) return null;
  let data: unknown;
  try {
    data = await response.json();
  } catch {
    throw new UsersRequestError('The users service returned an invalid response. Please try again.');
  }
  if (!response.ok) {
    if (response.status === 401) window.location.replace('/?screen=get_started');
    const fields: FieldErrors = {};
    if (isRecord(data) && isRecord(data.errors)) {
      for (const [key, messages] of Object.entries(data.errors)) {
        if (Array.isArray(messages) && messages.every((message) => typeof message === 'string')) fields[key] = messages;
      }
    }
    throw new UsersRequestError(
      isRecord(data) && typeof data.error === 'string' ? data.error : 'Unable to complete the request. Please try again.',
      fields
    );
  }
  return data;
}

function errorMessage(error: unknown) {
  return error instanceof Error ? error.message : 'Unable to reach the users service. Please try again.';
}

function FieldError({ name, errors }: { name: string; errors: FieldErrors }) {
  return errors[name]?.length
    ? <p id={`user-error-${name}`} className="mt-1 text-sm text-rose-700">{errors[name].join(' ')}</p>
    : null;
}

function UserStatus({ status }: { status: ManagedUser['status'] }) {
  const color = status === 'ACTIVE' ? 'bg-emerald-50 text-emerald-800'
    : status === 'SUSPENDED' ? 'bg-amber-50 text-amber-900' : 'bg-rose-50 text-rose-800';
  return <span className={`inline-block rounded-full px-2.5 py-1 text-xs font-semibold ${color}`}>{userLabel(status)}</span>;
}

type Editor = { mode: 'create' } | { mode: 'view' | 'edit'; id: ManagedUser['id'] };

function assignmentLabel(user: ManagedUser): string {
  const field = ROLE_PARENT_FIELD[user.role];
  return field ? String(user[field] ?? 'Not assigned') : 'National';
}

export function UserManagement() {
  const [client] = useState(() => new QueryClient());
  return <QueryClientProvider client={client}><UserManagementContent /></QueryClientProvider>;
}

function UserManagementContent() {
  const [draftFilters, setDraftFilters] = useState<UserFilters>({ ...EMPTY_USER_FILTERS });
  const [query, setQuery] = useState({ filters: { ...EMPTY_USER_FILTERS }, page: 1, revision: 0 });
  const [filterErrors, setFilterErrors] = useState<FieldErrors>({});
  const [result, setResult] = useState<UserPage | null>(null);
  const [loading, setLoading] = useState(true);
  const [listError, setListError] = useState<string | null>(null);
  const [notice, setNotice] = useState<string | null>(null);
  const [editor, setEditor] = useState<Editor | null>(null);
  const [form, setForm] = useState<UserPayload>({ ...EMPTY_FORM });
  const [detail, setDetail] = useState<ManagedUser | null>(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [editorError, setEditorError] = useState<string | null>(null);
  const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
  const [saving, setSaving] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<ManagedUser | null>(null);
  const [confirmation, setConfirmation] = useState('');
  const [deleting, setDeleting] = useState(false);
  const [deleteError, setDeleteError] = useState<string | null>(null);
  const deleteInFlight = useRef(false);
  const editorHeading = useRef<HTMLHeadingElement>(null);
  const saveInFlight = useRef(false);
  const [filterGeography, setFilterGeography] = useState<GeographySelection>({ ...EMPTY_GEOGRAPHY });
  const [assignment, setAssignment] = useState<GeographySelection>({ ...EMPTY_GEOGRAPHY });
  const [reassigning, setReassigning] = useState(true);
  const scope = ROLE_SCOPE[form.role];
  const assignmentField = ROLE_PARENT_FIELD[form.role];
  const assignmentLevel = ['ZONE', 'STATE', 'LGA', 'WARD', 'PU'].indexOf(scope);

  useEffect(() => {
    const controller = new AbortController();
    const params = new URLSearchParams({ page: String(query.page) });
    for (const [key, value] of Object.entries(query.filters)) if (value) params.set(key, value);
    setLoading(true);
    setResult(null);
    setListError(null);
    requestUsers(`/api/users?${params}`, { signal: controller.signal })
      .then((data) => {
        if (!isUserPage(data)) throw new UsersRequestError('The users service returned an invalid user list.');
        if (!controller.signal.aborted) setResult(data);
      })
      .catch((error: unknown) => { if (!controller.signal.aborted) setListError(errorMessage(error)); })
      .finally(() => { if (!controller.signal.aborted) setLoading(false); });
    return () => controller.abort();
  }, [query]);

  useEffect(() => {
    if (!editor) return;
    const controller = new AbortController();
    setEditorError(null);
    setFieldErrors({});
    setDetail(null);
    setForm({ ...EMPTY_FORM });
    setAssignment({ ...EMPTY_GEOGRAPHY });
    setReassigning(editor.mode === 'create');
    editorHeading.current?.focus();
    if (editor.mode === 'create') {
      setDetailLoading(false);
      return () => controller.abort();
    }
    setDetailLoading(true);
    requestUsers(`/api/users/${editor.id}`, { signal: controller.signal })
      .then((data) => {
        if (!isRecord(data) || !isManagedUser(data.data)) throw new UsersRequestError('The users service returned invalid user details.');
        if (controller.signal.aborted) return;
        const user = data.data;
        setDetail(user);
        setForm({
          name: user.name, email: user.email, phone_number: user.phone_number, password: '',
          role: user.role, status: user.status,
        });
      })
      .catch((error: unknown) => { if (!controller.signal.aborted) setEditorError(errorMessage(error)); })
      .finally(() => { if (!controller.signal.aborted) setDetailLoading(false); });
    return () => controller.abort();
  }, [editor]);

  const refresh = () => setQuery((previous) => ({ ...previous, revision: previous.revision + 1 }));

  const changeGeographyFilter = (next: GeographySelection) => {
    const filters = {
      geozone_id: next.geozone_id, state_id: next.state_id, lga_id: next.lga_id, ward_id: next.ward_id,
      pu_id: next.polling_unit_id,
    };
    setFilterGeography(next);
    setDraftFilters((previous) => ({ ...previous, ...filters }));
    setFilterErrors({});
    setQuery((previous) => ({ filters: { ...previous.filters, ...filters }, page: 1, revision: previous.revision + 1 }));
  };

  const applyFilters = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const params = new URLSearchParams();
    for (const [key, value] of Object.entries(draftFilters)) if (value) params.set(key, value);
    const errors = validateUserQuery(params);
    setFilterErrors(errors);
    if (Object.keys(errors).length) return;
    setQuery((previous) => ({ filters: { ...draftFilters }, page: 1, revision: previous.revision + 1 }));
  };

  const openEditor = (value: Editor) => {
    setNotice(null);
    setEditor(value);
  };

  const saveUser = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!editor || editor.mode === 'view' || saveInFlight.current) return;
    const payload: UserPayload = {
      ...form, name: form.name.trim(), email: form.email?.trim() || null,
      phone_number: form.phone_number.trim(),
    };
    if (assignmentField && reassigning) {
      payload[assignmentField] = assignment[GEOGRAPHY_LEVELS[assignmentLevel].field];
    }
    if (editor.mode === 'edit' && payload.password === '') delete payload.password;
    const errors = validateUserPayload(payload, editor.mode === 'edit' ? 'update' : 'create');
    if (scope !== 'NATIONAL' && reassigning &&
        GEOGRAPHY_LEVELS.slice(0, assignmentLevel + 1).some((level) => !assignment[level.field])) {
      errors[assignmentField || 'assignment'] = [`Select the complete geography chain through ${userLabel(scope)}.`];
    }
    setFieldErrors(errors);
    setEditorError(null);
    if (Object.keys(errors).length) {
      setEditorError('Check the highlighted fields.');
      return;
    }
    saveInFlight.current = true;
    setSaving(true);
    try {
      const url = editor.mode === 'create' ? '/api/users' : `/api/users/${editor.id}`;
      const data = await requestUsers(url, {
        method: editor.mode === 'create' ? 'POST' : 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (!isRecord(data) || !isManagedUser(data.data)) throw new UsersRequestError('The users service returned invalid user details.');
      setNotice(`${data.data.name} was ${editor.mode === 'create' ? 'created' : 'updated'} successfully. The list reflects your current filters.`);
      setEditor(null);
      setForm({ ...EMPTY_FORM });
      refresh();
    } catch (error: unknown) {
      setEditorError(errorMessage(error));
      if (error instanceof UsersRequestError) setFieldErrors(error.fields);
    } finally {
      saveInFlight.current = false;
      setSaving(false);
    }
  };

  const errorAttributes = (key: string) => ({
    'aria-invalid': Boolean(fieldErrors[key]),
    'aria-describedby': fieldErrors[key] ? `user-error-${key}` : undefined,
  });

  const deleteUser = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!deleteTarget || confirmation !== 'delete' || deleteInFlight.current) return;
    deleteInFlight.current = true;
    setDeleting(true);
    setDeleteError(null);
    try {
      await requestUsers(`/api/users/${deleteTarget.id}`, {
        method: 'DELETE',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ confirmation }),
      });
      setNotice(`${deleteTarget.name} was deleted successfully.`);
      setDeleteTarget(null);
      refresh();
    } catch (error: unknown) {
      setDeleteError(errorMessage(error));
    } finally {
      deleteInFlight.current = false;
      setDeleting(false);
    }
  };

  return (
    <section className="space-y-5 text-slate-900" aria-labelledby="users-heading">
      <GeographyFilterCards value={filterGeography} onChange={changeGeographyFilter} />
      <header className="flex flex-wrap items-start justify-between gap-3">
        <div>
          <h2 id="users-heading" className="flex items-center gap-2 text-xl font-bold"><Users className="h-5 w-5" />User management</h2>
          <p className="mt-1 text-sm text-slate-600">Manage accounts, roles, access scopes, and account status.</p>
        </div>
        <div className="flex flex-wrap gap-2">
          <button className={buttonStyle} onClick={refresh} disabled={loading || saving}><RefreshCw className="h-4 w-4" />Refresh</button>
          <button className={primaryStyle} onClick={() => openEditor({ mode: 'create' })} disabled={saving}><Plus className="h-4 w-4" />Create user</button>
        </div>
      </header>

      {notice && <p role="status" className="rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-sm text-emerald-900">{notice}</p>}

      {editor?.mode === 'view' && (
        <BvasReportDetailsModal title="User details" onClose={() => setEditor(null)}>
          {detailLoading && <p role="status" className="text-sm text-slate-600">Loading user details...</p>}
          {editorError && <div role="alert" className="space-y-2 text-sm text-rose-800">
            <p>{editorError}</p>
            <button className={buttonStyle} onClick={() => setEditor({ ...editor })}>Retry</button>
          </div>}
          {!detailLoading && detail && <>
            <dl className="grid gap-4 text-sm sm:grid-cols-2">
              {[
                ['Name', detail.name], ['Phone number', detail.phone_number], ['Email', detail.email || 'Not provided'],
                ['Role', userLabel(detail.role)], ['Assignment level', userLabel(ROLE_SCOPE[detail.role])],
                ['Assignment', assignmentLabel(detail)], ['Status', userLabel(detail.status)],
                ['Last updated', detail.updated_at ? new Date(detail.updated_at).toLocaleString() : 'Not available'],
              ].map(([label, value]) => <div key={label}><dt className="text-slate-600">{label}</dt><dd className="mt-1 break-words font-medium">{value}</dd></div>)}
            </dl>
            <button className={primaryStyle} onClick={() => setEditor({ mode: 'edit', id: detail.id })}>Edit user</button>
          </>}
        </BvasReportDetailsModal>
      )}

      {deleteTarget && (
        <BvasReportDetailsModal title="Delete user?" onClose={() => { if (!deleteInFlight.current) setDeleteTarget(null); }}>
          <form onSubmit={deleteUser} className="space-y-4">
            <p className="text-sm text-slate-600">Delete <strong className="break-words">{deleteTarget.name}</strong>? This removes the account from active users and revokes all its API tokens. Historical records are retained. You cannot delete your own account.</p>
            <label htmlFor="user-delete-confirmation" className="block text-sm font-medium">Type <strong>delete</strong> to confirm</label>
            <input id="user-delete-confirmation" className={inputStyle} value={confirmation}
              autoComplete="off" spellCheck={false} disabled={deleting} onChange={(event) => setConfirmation(event.target.value)} />
            {deleteError && <p role="alert" className="text-sm text-rose-800">{deleteError}</p>}
            <div className="flex gap-2">
              <button type="button" className={buttonStyle} disabled={deleting} onClick={() => setDeleteTarget(null)}>Cancel</button>
              <button type="submit" className={`${buttonStyle} border-rose-700 bg-rose-700 text-white hover:bg-rose-800`}
                disabled={deleting || confirmation !== 'delete'}>{deleting ? 'Deleting...' : 'Delete user'}</button>
            </div>
          </form>
        </BvasReportDetailsModal>
      )}

      {editor && editor.mode !== 'view' && (
        <section aria-labelledby="user-editor-heading" className="rounded-2xl border border-slate-200 bg-white p-4 sm:p-6">
          <div className="mb-4 flex flex-wrap items-center justify-between gap-3">
            <h3 ref={editorHeading} tabIndex={-1} id="user-editor-heading" className="text-lg font-bold focus:outline-none">
              {editor.mode === 'create' ? 'Create user' : 'Edit user'}
            </h3>
            <button className={buttonStyle} disabled={saving} onClick={() => { setEditor(null); setForm({ ...EMPTY_FORM }); }}>Close</button>
          </div>
          {detailLoading && <p role="status" className="py-6 text-sm text-slate-600">Loading user details...</p>}
          {editorError && (
            <div role="alert" className="mb-4 rounded-lg bg-rose-50 p-3 text-sm text-rose-800">
              <p>{editorError}</p>
              {Object.entries(fieldErrors).map(([field, messages]) => <p key={field}>{userLabel(field)}: {messages.join(' ')}</p>)}
              {editor.mode !== 'create' && !detail && <button className={`${buttonStyle} mt-2`} onClick={() => setEditor({ ...editor })}>Retry</button>}
            </div>
          )}
          {!detailLoading && (editor.mode === 'create' || (editor.mode === 'edit' && detail)) && (
            <form onSubmit={saveUser} className="space-y-5">
              <p className="text-sm text-slate-600">Name, phone, {editor.mode === 'create' ? 'password, ' : ''}and role are required. Select the geographical assignment required for the role.</p>
              <fieldset disabled={saving} className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
                <legend className="sr-only">User account details</legend>
                {([
                  ['name', 'Name', 'text', 255], ['email', 'Email (optional)', 'email', 255],
                  ['phone_number', 'Phone number', 'tel', 32], ['password', 'Password (12-255 characters)', 'password', 255],
                ] as const).map(([key, label, type, max]) => (
                  <div key={key}>
                    <label htmlFor={`user-${key}`} className="mb-1.5 block text-sm font-medium">{key === 'password' && editor.mode === 'edit' ? 'New password (optional, 12-255 characters)' : label}</label>
                    <input id={`user-${key}`} className={inputStyle} type={type} maxLength={max}
                      minLength={key === 'password' ? 12 : undefined} required={key !== 'email' && (key !== 'password' || editor.mode === 'create')}
                      autoComplete={key === 'password' ? 'new-password' : 'off'}
                      value={form[key] || ''} onChange={(event) => setForm({ ...form, [key]: event.target.value })}
                      {...errorAttributes(key)} />
                    <FieldError name={key} errors={fieldErrors} />
                  </div>
                ))}
                <div>
                  <label htmlFor="user-role" className="mb-1.5 block text-sm font-medium">Role</label>
                  <select id="user-role" className={inputStyle} value={form.role}
                    onChange={(event) => {
                      const role = USER_ROLES.find((value) => value === event.target.value);
                      if (role) {
                        setForm({ ...form, role });
                        setAssignment({ ...EMPTY_GEOGRAPHY });
                        setReassigning(true);
                      }
                    }} {...errorAttributes('role')}>
                    {USER_ROLES.map((role) => <option key={role} value={role}>{userLabel(role)}</option>)}
                  </select>
                  <FieldError name="role" errors={fieldErrors} />
                </div>
                <div>
                  <label htmlFor="user-status" className="mb-1.5 block text-sm font-medium">Status</label>
                  <select id="user-status" className={inputStyle} value={form.status}
                    onChange={(event) => {
                      const status = USER_STATUSES.find((value) => value === event.target.value);
                      if (status) setForm({ ...form, status });
                    }} {...errorAttributes('status')}>
                    {USER_STATUSES.map((status) => <option key={status} value={status}>{userLabel(status)}</option>)}
                  </select>
                  <FieldError name="status" errors={fieldErrors} />
                </div>
              </fieldset>
              <section className="space-y-3 rounded-xl border border-slate-200 p-4" aria-labelledby="assignment-heading">
                <h4 id="assignment-heading" className="text-sm font-semibold">{userLabel(scope)} assignment</h4>
                {scope === 'NATIONAL' ? <p className="text-sm text-slate-600">National access (ALL). No geographical selection is required.</p>
                  : !reassigning && detail ? <div className="space-y-2">
                    <p className="text-sm text-slate-600">Current {userLabel(ROLE_SCOPE[detail.role])} assignment: {assignmentLabel(detail)}. Leave this unchanged or select a new assignment.</p>
                    <button type="button" className={buttonStyle} disabled={saving} onClick={() => {
                      setReassigning(true); setAssignment({ ...EMPTY_GEOGRAPHY });
                    }}>Change assignment</button>
                  </div> : <GeographyFields value={assignment} maxLevel={assignmentLevel} required disabled={saving}
                    onChange={(next) => {
                      setAssignment(next);
                    }} />}
                <FieldError name={assignmentField || 'assignment'} errors={fieldErrors} />
              </section>
              {editor.mode === 'edit' && <p className="text-sm text-slate-600">Leave the password blank to keep the existing password. Enter a new password only to change it.</p>}
              <div className="flex flex-wrap gap-2">
                <button className={primaryStyle} type="submit" disabled={saving}>{saving ? 'Saving...' : editor.mode === 'create' ? 'Create account' : 'Save changes'}</button>
                <button className={buttonStyle} type="button" disabled={saving} onClick={() => { setEditor(null); setForm({ ...EMPTY_FORM }); }}>Cancel</button>
              </div>
            </form>
          )}
        </section>
      )}

      <form onSubmit={applyFilters} className="space-y-4 rounded-2xl border border-slate-200 bg-white p-4 sm:p-5" aria-label="Filter users">
        <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
          <div className="sm:col-span-2">
            <label htmlFor="users-search" className="mb-1.5 block text-sm font-medium">Search users</label>
            <input id="users-search" type="search" className={inputStyle} maxLength={255}
              placeholder="Search by name, phone, or email" value={draftFilters.search}
              onChange={(event) => setDraftFilters({ ...draftFilters, search: event.target.value })} />
          </div>
          <div>
            <label htmlFor="users-role-filter" className="mb-1.5 block text-sm font-medium">Role filter</label>
            <select id="users-role-filter" className={inputStyle} value={draftFilters.role} onChange={(event) => setDraftFilters({ ...draftFilters, role: event.target.value })}>
              <option value="">All roles</option>
              {USER_ROLES.map((role) => <option key={role} value={role}>{userLabel(role)}</option>)}
            </select>
          </div>
          <div>
            <label htmlFor="users-status-filter" className="mb-1.5 block text-sm font-medium">Status filter</label>
            <select id="users-status-filter" className={inputStyle} value={draftFilters.status} onChange={(event) => setDraftFilters({ ...draftFilters, status: event.target.value })}>
              <option value="">All statuses</option>
              {USER_STATUSES.map((status) => <option key={status} value={status}>{userLabel(status)}</option>)}
            </select>
          </div>
        </div>
        {Object.keys(filterErrors).length > 0 && <div role="alert" className="text-sm text-rose-700">
          {Object.entries(filterErrors).map(([field, messages]) => <p key={field}>{userLabel(field)}: {messages.join(' ')}</p>)}
        </div>}
        <div className="flex flex-wrap items-end justify-between gap-3">
          <div className="flex flex-wrap gap-2">
            <button className={primaryStyle} type="submit"><Search className="h-4 w-4" />Apply filters</button>
            <button className={buttonStyle} type="button" onClick={() => {
              setDraftFilters({ ...EMPTY_USER_FILTERS }); setFilterErrors({});
              setFilterGeography({ ...EMPTY_GEOGRAPHY });
              setQuery((previous) => ({ filters: { ...EMPTY_USER_FILTERS }, page: 1, revision: previous.revision + 1 }));
            }}>Clear filters</button>
          </div>
          <div>
            <label htmlFor="users-page-size" className="mb-1.5 block text-sm font-medium">Users per page</label>
            <select id="users-page-size" className={inputStyle} value={draftFilters.per_page}
              onChange={(event) => {
                const value = event.target.value;
                setDraftFilters((previous) => ({ ...previous, per_page: value }));
                setQuery((previous) => ({ ...previous, page: 1, filters: { ...previous.filters, per_page: value } }));
              }}>
              {[10, 25, 50, 100].map((size) => <option key={size} value={size}>{size}</option>)}
            </select>
          </div>
        </div>
      </form>

      <div className="overflow-hidden rounded-2xl border border-slate-200 bg-white" aria-busy={loading}>
        {loading && <p role="status" className="p-8 text-center text-sm text-slate-600">Loading users...</p>}
        {listError && <div role="alert" className="space-y-3 p-6 text-sm text-rose-800">
          <p>{listError}</p><button className={buttonStyle} onClick={refresh}>Retry loading users</button>
        </div>}
        {!loading && result && (
          <>
            {result.data.length === 0 ? <div className="p-8 text-center">
              <h3 className="font-semibold">No users found</h3>
              <p className="mt-1 text-sm text-slate-600">Try clearing filters or create an account.</p>
            </div> : <div className="overflow-x-auto">
              <table className="w-full min-w-[760px] text-left text-sm">
                <caption className="sr-only">Users matching the applied filters</caption>
                <thead className="border-b border-slate-200 bg-slate-50 text-slate-600"><tr>
                  {['User', 'Role', 'Scope', 'Status', 'Actions'].map((heading) => <th key={heading} scope="col" className="px-4 py-3 font-semibold">{heading}</th>)}
                </tr></thead>
                <tbody className="divide-y divide-slate-100">
                  {result.data.map((user) => <tr key={user.id} className="hover:bg-slate-50">
                    <td className="px-4 py-4"><p className="font-semibold">{user.name}</p><p className="mt-1 text-slate-600">{user.phone_number}</p>{user.email && <p className="mt-1 break-all text-slate-600">{user.email}</p>}</td>
                    <td className="px-4 py-4">{userLabel(user.role)}</td>
                    <td className="px-4 py-4"><p>{userLabel(ROLE_SCOPE[user.role])}</p><p className="mt-1 font-mono text-xs text-slate-600">{assignmentLabel(user)}</p></td>
                    <td className="px-4 py-4"><UserStatus status={user.status} /></td>
                    <td className="px-4 py-4"><div className="flex flex-wrap gap-2">
                      <button className={buttonStyle} aria-label={`View ${user.name}`} disabled={saving} onClick={() => openEditor({ mode: 'view', id: user.id })}>View</button>
                      <button className={buttonStyle} aria-label={`Edit ${user.name}`} disabled={saving} onClick={() => openEditor({ mode: 'edit', id: user.id })}>Edit</button>
                      <button className={`${buttonStyle} text-rose-700`} aria-label={`Delete ${user.name}`} disabled={saving || deleting}
                        onClick={() => { setEditor(null); setNotice(null); setConfirmation(''); setDeleteError(null); setDeleteTarget(user); }}>Delete</button>
                    </div></td>
                  </tr>)}
                </tbody>
              </table>
            </div>}
            <footer className="flex flex-wrap items-center justify-between gap-3 border-t border-slate-200 p-4">
              <p role="status" className="text-sm text-slate-600">{result.meta.from ?? 0}-{result.meta.to ?? 0} of {result.meta.total} users</p>
              <nav aria-label="User list pagination" className="flex flex-wrap items-center gap-2">
                <button className={buttonStyle} disabled={loading || result.meta.current_page <= 1} onClick={() => setQuery((previous) => ({ ...previous, page: result.meta.current_page - 1 }))}>
                  <ChevronLeft className="h-4 w-4" />Previous
                </button>
                <span className="px-2 text-sm">Page {result.meta.current_page} of {result.meta.last_page}</span>
                <button className={buttonStyle} disabled={loading || result.meta.current_page >= result.meta.last_page} onClick={() => setQuery((previous) => ({ ...previous, page: result.meta.current_page + 1 }))}>
                  Next<ChevronRight className="h-4 w-4" />
                </button>
              </nav>
            </footer>
          </>
        )}
      </div>
    </section>
  );
}
