import { useEffect, useMemo, useState } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { KeyRound, MessageSquare, Pencil, Plus, RotateCcw, Search, Shield, Trash2, X } from 'lucide-react'
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
import { Modal } from '../components/Modal'
import { formatCellForDisplay, toE164CellNumber } from '../lib/cellNumber'
import type { RoleOption, UserListItem, UsersListResponse } from '../types/user'
import type { ListUsersParams } from '../services/userService'
import { ApiError, isAbortError } from '../lib/api'
import {
  assignBusinessAccess,
  listTeamRoles,
  type BusinessAccess,
} from '../services/teamService'
import {
  adminResetUserPassword,
  createUser,
  listUserRoles,
  listUsers,
  removeUser,
  sendUserMessage,
  updateUser,
  updateUserRole,
} from '../services/userService'
import { useToast } from '../context/ToastContext'
import { Pagination } from '@meshkee/dashboard-ui'
import pageStyles from '../components/PageContent.module.css'
import tableStyles from './BusinessesPage.module.css'
import styles from './UsersPage.module.css'

const PAGE_SIZE = 24

function formatDate(value: string) {
  const d = new Date(value)
  if (Number.isNaN(d.getTime())) return value
  return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: '2-digit' })
}

function displayName(user: UserListItem) {
  const name = [user.firstName, user.lastName].filter(Boolean).join(' ').trim()
  return name || '—'
}

const TEAM_ROLE_ORDER = ['admin', 'editor', 'viewer'] as const

const TEAM_ROLE_LABELS: Record<string, string> = {
  admin: 'Admin',
  editor: 'Editor',
  viewer: 'Observer',
}

function teamRoleLabel(slug: string | null | undefined, teamRoles: RoleOption[]) {
  if (!slug) return null
  return (
    TEAM_ROLE_LABELS[slug] ??
    teamRoles.find((role) => role.slug === slug)?.name ??
    slug
  )
}

function formatGlobalRoleLabel(user: UserListItem, teamRoles: RoleOption[]) {
  if (user.isBusinessOwner) return 'Business Owner'
  if (user.teamRole) {
    const teamName = teamRoleLabel(user.teamRole, teamRoles)
    return teamName ? `Manager · ${teamName}` : 'Manager'
  }
  if (user.roleSlug === 'business_staff' && user.teamRole) {
    const teamName = teamRoleLabel(user.teamRole, teamRoles)
    return teamName ? `Manager · ${teamName}` : 'Manager'
  }
  return user.roles
}

function formatBusinessUserRoleLabel(user: UserListItem, teamRoles: RoleOption[]) {
  if (user.isBusinessOwner) return 'Business Owner'
  if (user.businessMemberId && user.teamRole) {
    return teamRoleLabel(user.teamRole, teamRoles) ?? 'Manager'
  }
  if (user.businessMemberId) return 'Manager'
  return 'Customer'
}

export function UsersPage() {
  const { showToast } = useToast()
  const navigate = useNavigate()
  const [searchParams] = useSearchParams()
  const [data, setData] = useState<UsersListResponse | null>(null)
  const [roles, setRoles] = useState<RoleOption[]>([])
  const [teamRoles, setTeamRoles] = useState<RoleOption[]>([])
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')

  const [appliedFilters, setAppliedFilters] = useState<Omit<ListUsersParams, 'page' | 'pageSize'>>({})
  const [page, setPage] = useState(1)

  const [draftName, setDraftName] = useState('')
  const [draftCell, setDraftCell] = useState('')
  const [draftRole, setDraftRole] = useState('')

  const [editOpen, setEditOpen] = useState(false)
  const [editUser, setEditUser] = useState<UserListItem | null>(null)
  const [editFirstName, setEditFirstName] = useState('')
  const [editLastName, setEditLastName] = useState('')
  const [editEmail, setEditEmail] = useState('')
  const [editCell, setEditCell] = useState('')
  const [editSubmitting, setEditSubmitting] = useState(false)
  const [editError, setEditError] = useState('')

  const [resetOpen, setResetOpen] = useState(false)
  const [resetUser, setResetUser] = useState<UserListItem | null>(null)
  const [resetPassword, setResetPassword] = useState('')
  const [resetConfirm, setResetConfirm] = useState('')
  const [resetSubmitting, setResetSubmitting] = useState(false)
  const [resetError, setResetError] = useState('')

  const [messageOpen, setMessageOpen] = useState(false)
  const [messageUser, setMessageUser] = useState<UserListItem | null>(null)
  const [messageText, setMessageText] = useState('')
  const [messageSubmitting, setMessageSubmitting] = useState(false)
  const [messageError, setMessageError] = useState('')

  const [removeTarget, setRemoveTarget] = useState<UserListItem | null>(null)

  const [roleOpen, setRoleOpen] = useState(false)
  const [roleUser, setRoleUser] = useState<UserListItem | null>(null)
  const [selectedRoleSlug, setSelectedRoleSlug] = useState('')
  const [businessAccess, setBusinessAccess] = useState<BusinessAccess>('customer')
  const [selectedTeamRoleSlug, setSelectedTeamRoleSlug] = useState('admin')
  const [roleSubmitting, setRoleSubmitting] = useState(false)
  const [roleError, setRoleError] = useState('')

  const [createOpen, setCreateOpen] = useState(false)
  const [createFirstName, setCreateFirstName] = useState('')
  const [createLastName, setCreateLastName] = useState('')
  const [createCell, setCreateCell] = useState('')
  const [createPassword, setCreatePassword] = useState('')
  const [createEmail, setCreateEmail] = useState('')
  const [createSubmitting, setCreateSubmitting] = useState(false)
  const [createError, setCreateError] = useState('')
  const [listVersion, setListVersion] = useState(0)

  const businessFilter = useMemo(() => {
    const businessIdRaw = searchParams.get('businessId')
    const membershipRaw = searchParams.get('membership')
    if (!businessIdRaw || (membershipRaw !== 'staff' && membershipRaw !== 'all')) {
      return null
    }
    const businessId = Number(businessIdRaw)
    if (!Number.isFinite(businessId)) return null
    return {
      businessId,
      membership: membershipRaw as 'staff' | 'all',
      businessName: searchParams.get('businessName') ?? 'Business',
    }
  }, [searchParams])

  useEffect(() => {
    const controller = new AbortController()

    async function load() {
      setLoading(true)
      setError('')
      try {
        const [result, roleResult, teamRoleResult] = await Promise.all([
          listUsers(
            {
              page,
              pageSize: PAGE_SIZE,
              ...appliedFilters,
              ...(businessFilter
                ? { businessId: businessFilter.businessId, membership: businessFilter.membership }
                : {}),
            },
            controller.signal,
          ),
          listUserRoles(controller.signal),
          listTeamRoles(controller.signal),
        ])
        if (controller.signal.aborted) return
        setData(result)
        setRoles(roleResult.items)
        setTeamRoles(teamRoleResult.items)
      } catch (err) {
        if (isAbortError(err) || controller.signal.aborted) return
        setError(err instanceof ApiError ? err.message : 'Unable to load users.')
      } finally {
        if (!controller.signal.aborted) setLoading(false)
      }
    }

    void load()

    return () => {
      controller.abort()
    }
  }, [
    page,
    appliedFilters.name,
    appliedFilters.cellNumber,
    appliedFilters.role,
    businessFilter?.businessId,
    businessFilter?.membership,
    listVersion,
  ])

  useEffect(() => {
    setPage(1)
  }, [businessFilter?.businessId, businessFilter?.membership])

  const totalPages = useMemo(() => {
    const total = data?.total ?? 0
    return Math.max(1, Math.ceil(total / PAGE_SIZE))
  }, [data?.total])

  const showingFrom = useMemo(() => {
    if (!data) return 0
    return (page - 1) * PAGE_SIZE + 1
  }, [data, page])

  const showingTo = useMemo(() => {
    if (!data) return 0
    return Math.min(data.total, page * PAGE_SIZE)
  }, [data, page])

  function applyFilters() {
    setPage(1)
    setAppliedFilters({
      ...(draftName.trim() ? { name: draftName.trim() } : {}),
      ...(draftCell.trim() ? { cellNumber: draftCell.trim() } : {}),
      ...(draftRole ? { role: draftRole } : {}),
    })
  }

  function clearFilters() {
    setDraftName('')
    setDraftCell('')
    setDraftRole('')
    setPage(1)
    setAppliedFilters({})
  }

  function clearBusinessFilter() {
    setPage(1)
    navigate('/users')
  }

  function resetCreateForm() {
    setCreateFirstName('')
    setCreateLastName('')
    setCreateCell('')
    setCreatePassword('')
    setCreateEmail('')
    setCreateError('')
  }

  function openCreate() {
    resetCreateForm()
    setCreateOpen(true)
  }

  async function submitCreate() {
    if (!businessFilter || businessFilter.membership !== 'all') return
    const cellNumber = toE164CellNumber(createCell.trim())
    if (!cellNumber) return

    setCreateSubmitting(true)
    setCreateError('')
    try {
      await createUser({
        businessId: businessFilter.businessId,
        cellNumber,
        firstName: createFirstName.trim(),
        lastName: createLastName.trim(),
        ...(createPassword.trim() ? { password: createPassword.trim() } : {}),
        ...(createEmail.trim() ? { email: createEmail.trim() } : {}),
      })
      showToast('User added to business.', 'success')
      setCreateOpen(false)
      resetCreateForm()
      setPage(1)
      setListVersion((v) => v + 1)
    } catch (err) {
      setCreateError(err instanceof ApiError ? err.message : 'Unable to add user.')
    } finally {
      setCreateSubmitting(false)
    }
  }

  const canCreateUser =
    createFirstName.trim().length >= 2 &&
    createLastName.trim().length >= 2 &&
    toE164CellNumber(createCell.trim()).length > 0

  const orderedTeamRoles = useMemo(() => {
    const bySlug = new Map(teamRoles.map((role) => [role.slug, role]))
    const ordered = TEAM_ROLE_ORDER.map((slug) => bySlug.get(slug)).filter(
      (role): role is RoleOption => Boolean(role),
    )
    const extras = teamRoles.filter(
      (role) => !TEAM_ROLE_ORDER.includes(role.slug as (typeof TEAM_ROLE_ORDER)[number]),
    )
    return [...ordered, ...extras]
  }, [teamRoles])

  function openRoleChange(user: UserListItem) {
    if (businessFilter && user.isBusinessOwner) return

    setRoleUser(user)
    setSelectedRoleSlug(user.roleSlug ?? '')
    if (businessFilter) {
      const isStaff = Boolean(user.businessMemberId) && !user.isBusinessOwner
      setBusinessAccess(isStaff ? 'staff' : 'customer')
      setSelectedTeamRoleSlug(
        (isStaff && user.teamRole) || orderedTeamRoles[0]?.slug || 'admin',
      )
    } else {
      setBusinessAccess('customer')
      setSelectedTeamRoleSlug(orderedTeamRoles[0]?.slug || 'admin')
    }
    setRoleError('')
    setRoleOpen(true)
  }

  const canSaveRole = businessFilter
    ? !roleUser?.isBusinessOwner &&
      (businessAccess === 'customer' || Boolean(selectedTeamRoleSlug))
    : Boolean(selectedRoleSlug)

  async function submitRoleChange() {
    if (!roleUser || !canSaveRole) return
    setRoleSubmitting(true)
    setRoleError('')
    try {
      if (businessFilter) {
        const result = await assignBusinessAccess(businessFilter.businessId, {
          userId: roleUser.id,
          access: businessAccess,
          roleSlug: businessAccess === 'staff' ? selectedTeamRoleSlug : undefined,
        })

        const accessLabel =
          businessAccess === 'staff'
            ? teamRoleLabel(selectedTeamRoleSlug, teamRoles) ?? 'Manager'
            : 'Customer'

        showToast(`Access updated to ${accessLabel}.`, 'success')

        setData((prev) => {
          if (!prev) return prev
          return {
            ...prev,
            items: prev.items.map((item) =>
              item.id === roleUser.id
                ? {
                    ...item,
                    roleSlug: businessAccess === 'staff' ? 'business_staff' : 'customer',
                    roles: accessLabel,
                    teamRole: businessAccess === 'staff' ? selectedTeamRoleSlug : null,
                    businessMemberId:
                      businessAccess === 'staff'
                        ? result.member?.id != null
                          ? Number(result.member.id)
                          : item.businessMemberId
                        : null,
                    isBusinessOwner: false,
                  }
                : item,
            ),
          }
        })
      } else {
        await updateUserRole(roleUser.id, selectedRoleSlug)

        const roleName =
          roles.find((role) => role.slug === selectedRoleSlug)?.name ?? selectedRoleSlug

        showToast(`Role updated to ${roleName}.`, 'success')

        setData((prev) => {
          if (!prev) return prev
          return {
            ...prev,
            items: prev.items.map((item) =>
              item.id === roleUser.id
                ? {
                    ...item,
                    roleSlug: selectedRoleSlug,
                    roles: roleName,
                  }
                : item,
            ),
          }
        })
      }

      setRoleOpen(false)
      setRoleUser(null)
      setSelectedTeamRoleSlug('admin')
    } catch (err) {
      setRoleError(err instanceof ApiError ? err.message : 'Unable to update role.')
    } finally {
      setRoleSubmitting(false)
    }
  }

  function openEdit(user: UserListItem) {
    setEditUser(user)
    setEditFirstName(user.firstName ?? '')
    setEditLastName(user.lastName ?? '')
    setEditEmail('')
    setEditCell(user.cellNumber)
    setEditError('')
    setEditOpen(true)
  }

  async function submitEdit() {
    if (!editUser) return
    setEditSubmitting(true)
    setEditError('')
    try {
      await updateUser(editUser.id, {
        firstName: editFirstName.trim(),
        lastName: editLastName.trim(),
        cellNumber: editCell.trim(),
        ...(editEmail.trim() ? { email: editEmail.trim() } : {}),
      })
      setEditOpen(false)
      setEditUser(null)
      showToast(`"${displayName(editUser)}" has been updated.`, 'success')
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === editUser.id
              ? {
                  ...item,
                  firstName: editFirstName.trim(),
                  lastName: editLastName.trim(),
                  cellNumber: editCell.trim(),
                }
              : item,
          ),
        }
      })
    } catch (err) {
      setEditError(err instanceof ApiError ? err.message : 'Unable to update user.')
    } finally {
      setEditSubmitting(false)
    }
  }

  function openResetPassword(user: UserListItem) {
    setResetUser(user)
    setResetPassword('')
    setResetConfirm('')
    setResetError('')
    setResetOpen(true)
  }

  async function submitResetPassword() {
    if (!resetUser) return
    if (resetPassword !== resetConfirm) {
      setResetError('Passwords do not match.')
      return
    }
    setResetSubmitting(true)
    setResetError('')
    try {
      await adminResetUserPassword(resetUser.id, resetPassword)
      setResetOpen(false)
      setResetUser(null)
      showToast(`Password reset for "${displayName(resetUser)}".`, 'success')
    } catch (err) {
      setResetError(err instanceof ApiError ? err.message : 'Unable to reset password.')
    } finally {
      setResetSubmitting(false)
    }
  }

  function openSendMessage(user: UserListItem) {
    setMessageUser(user)
    setMessageText('')
    setMessageError('')
    setMessageOpen(true)
  }

  async function submitSendMessage() {
    if (!messageUser) return
    setMessageSubmitting(true)
    setMessageError('')
    try {
      const result = await sendUserMessage(messageUser.id, messageText.trim())
      setMessageOpen(false)
      setMessageUser(null)
      showToast(result.message, result.enabled ? 'success' : 'info')
    } catch (err) {
      setMessageError(err instanceof ApiError ? err.message : 'Unable to send message.')
    } finally {
      setMessageSubmitting(false)
    }
  }

  async function confirmRemove() {
    if (!removeTarget) return
    setError('')
    try {
      await removeUser(removeTarget.id)
      setRemoveTarget(null)
      showToast(`"${displayName(removeTarget)}" has been removed.`, 'success')
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === removeTarget.id ? { ...item, isActive: false } : item,
          ),
        }
      })
    } catch (err) {
      setError(err instanceof ApiError ? err.message : 'Unable to remove user.')
    }
  }

  const canResetPassword =
    resetPassword.length >= 8 && resetConfirm.length >= 8 && resetPassword === resetConfirm

  return (
    <main className={pageStyles.content}>
      <div className={pageStyles.pageHeader}>
        <div>
          <h2 className={pageStyles.pageTitle}>Users</h2>
          <p className={pageStyles.pageSubtitle}>
            View and manage all platform users and their access levels.
          </p>
        </div>
      </div>

      {businessFilter && (
        <div className={styles.businessBanner}>
          <span>
            Showing {businessFilter.membership === 'staff' ? 'staff' : 'all users'} for{' '}
            <strong>{businessFilter.businessName}</strong>
          </span>
          <button
            type="button"
            className={styles.businessBannerClear}
            onClick={clearBusinessFilter}
            aria-label="Clear business filter"
            title="Clear business filter"
          >
            <X size={16} />
          </button>
        </div>
      )}

      <div className={tableStyles.filtersPanel}>
        <div className={tableStyles.filtersTitle}>Filters</div>
        <form className={tableStyles.filtersGrid} onSubmit={(e) => { e.preventDefault(); applyFilters() }}>
          <div className={tableStyles.filtersInputs}>
            <div className={`${tableStyles.field} ${tableStyles.fieldCol3}`}>
              <label htmlFor="filter-user-name">Name</label>
              <input
                id="filter-user-name"
                value={draftName}
                onChange={(e) => setDraftName(e.target.value)}
                placeholder="Search by name"
              />
            </div>
            <div className={`${tableStyles.field} ${tableStyles.fieldCol3}`}>
              <label htmlFor="filter-user-cell">Cell number</label>
              <input
                id="filter-user-cell"
                value={draftCell}
                onChange={(e) => setDraftCell(e.target.value)}
                placeholder="0912..."
                autoComplete="off"
              />
            </div>
            <div className={`${tableStyles.field} ${tableStyles.fieldCol3}`}>
              <label htmlFor="filter-user-role">Role</label>
              <select
                id="filter-user-role"
                value={draftRole}
                onChange={(e) => setDraftRole(e.target.value)}
              >
                <option value="">All roles</option>
                {roles.map((role) => (
                  <option key={role.slug} value={role.slug}>
                    {role.name}
                  </option>
                ))}
              </select>
            </div>
          </div>
          <div className={tableStyles.filterActions}>
            <button
              type="submit"
              className={`${tableStyles.iconActionBtn} ${tableStyles.iconActionBtnPrimary}`}
              disabled={loading}
              aria-label="Search"
              title="Search"
            >
              <Search size={18} />
            </button>
            <button
              type="button"
              className={`${tableStyles.iconActionBtn} ${tableStyles.iconActionBtnGhost}`}
              onClick={clearFilters}
              disabled={loading}
              aria-label="Clear filters"
              title="Clear filters"
            >
              <RotateCcw size={18} />
            </button>
          </div>
        </form>
      </div>

      <div className={tableStyles.tablePanel}>
        <div className={tableStyles.tableWrap}>
          <div className={tableStyles.tableHeader}>
            <div className={tableStyles.tableHeaderTitle}>User list</div>
            <div className={tableStyles.meta}>
              {data ? (
                <>
                  Showing {showingFrom} - {showingTo} of {data.total}
                </>
              ) : (
                ' '
              )}
            </div>
          </div>

          {error && (
            <div style={{ padding: 16 }}>
              <div className={tableStyles.meta} style={{ color: '#b91c1c' }}>
                {error}
              </div>
            </div>
          )}

          <div style={{ overflowX: 'auto' }}>
            <table className={tableStyles.table}>
              <thead>
                <tr>
                  <th className={tableStyles.th}>Name</th>
                  <th className={tableStyles.th}>Cell number</th>
                  <th className={tableStyles.th}>Role</th>
                  <th className={tableStyles.th}>Business</th>
                  <th className={tableStyles.th}>Date joined</th>
                  <th className={`${tableStyles.th} ${tableStyles.thActions}`}>Actions</th>
                </tr>
              </thead>
              <tbody>
                {loading && (
                  <tr>
                    <td className={tableStyles.td} colSpan={6}>
                      Loading...
                    </td>
                  </tr>
                )}

                {!loading && data?.items?.length === 0 && (
                  <tr>
                    <td className={tableStyles.td} colSpan={6}>
                      No results found.
                    </td>
                  </tr>
                )}

                {!loading &&
                  data?.items?.map((user) => (
                    <tr key={user.id} className={!user.isActive ? styles.inactiveRow : undefined}>
                      <td className={tableStyles.td}>
                        <div>{displayName(user)}</div>
                        {!user.isActive && <div className={styles.statusInactive}>Inactive</div>}
                      </td>
                      <td className={tableStyles.td}>{formatCellForDisplay(user.cellNumber)}</td>
                      <td className={tableStyles.td}>
                        {(() => {
                          const label = businessFilter
                            ? formatBusinessUserRoleLabel(user, teamRoles)
                            : formatGlobalRoleLabel(user, teamRoles)
                          return label ? (
                            <span className={styles.roleBadge}>{label}</span>
                          ) : (
                            <span className={tableStyles.subText}>—</span>
                          )
                        })()}
                      </td>
                      <td className={tableStyles.td}>
                        {user.businesses ?? <span className={tableStyles.subText}>—</span>}
                      </td>
                      <td className={tableStyles.td}>{formatDate(user.createdAt)}</td>
                      <td className={`${tableStyles.td} ${tableStyles.tdActions}`}>
                        <div className={tableStyles.rowActions}>
                          <button
                            type="button"
                            className={tableStyles.controlBtn}
                            onClick={() => openRoleChange(user)}
                            title={
                              businessFilter && user.isBusinessOwner
                                ? 'Business owner cannot be changed'
                                : 'Change role'
                            }
                            aria-label={
                              businessFilter && user.isBusinessOwner
                                ? 'Business owner cannot be changed'
                                : 'Change role'
                            }
                            disabled={!user.isActive || Boolean(businessFilter && user.isBusinessOwner)}
                          >
                            <Shield size={16} />
                          </button>
                          <button
                            type="button"
                            className={tableStyles.controlBtn}
                            onClick={() => openResetPassword(user)}
                            title="Reset password"
                            aria-label="Reset password"
                            disabled={!user.isActive}
                          >
                            <KeyRound size={16} />
                          </button>
                          <button
                            type="button"
                            className={tableStyles.controlBtn}
                            onClick={() => openEdit(user)}
                            title="Edit"
                            aria-label="Edit"
                            disabled={!user.isActive}
                          >
                            <Pencil size={16} />
                          </button>
                          <button
                            type="button"
                            className={tableStyles.controlBtn}
                            onClick={() => openSendMessage(user)}
                            title="Send message"
                            aria-label="Send message"
                            disabled={!user.isActive}
                          >
                            <MessageSquare size={16} />
                          </button>
                          <button
                            type="button"
                            className={`${tableStyles.controlBtn} ${tableStyles.controlBtnDanger}`}
                            onClick={() => setRemoveTarget(user)}
                            title="Remove"
                            aria-label="Remove"
                            disabled={!user.isActive}
                          >
                            <Trash2 size={16} />
                          </button>
                        </div>
                      </td>
                    </tr>
                  ))}
              </tbody>
            </table>
          </div>

          <div className={tableStyles.pagination}>
            <div>
              Page {page} / {totalPages} · {PAGE_SIZE} per page · {data?.total ?? 0} total
            </div>
            <Pagination
              currentPage={page}
              totalPages={totalPages}
              onPageChange={setPage}
              disabled={loading}
              variant="inline"
            />
          </div>
        </div>
      </div>

      <Modal
        open={editOpen}
        title="Edit user"
        onClose={() => {
          setEditOpen(false)
          setEditUser(null)
          setEditError('')
        }}
      >
        {editError ? (
          <p className={tableStyles.alertError} role="alert">
            {editError}
          </p>
        ) : null}
        <div className={tableStyles.formGrid}>
          <div className={tableStyles.field}>
            <label htmlFor="edit-first-name">First name</label>
            <input
              id="edit-first-name"
              value={editFirstName}
              onChange={(e) => setEditFirstName(e.target.value)}
              disabled={editSubmitting}
            />
          </div>
          <div className={tableStyles.field}>
            <label htmlFor="edit-last-name">Last name</label>
            <input
              id="edit-last-name"
              value={editLastName}
              onChange={(e) => setEditLastName(e.target.value)}
              disabled={editSubmitting}
            />
          </div>
          <div className={`${tableStyles.field} ${tableStyles.formFull}`}>
            <label htmlFor="edit-cell">Cell number</label>
            <input
              id="edit-cell"
              value={editCell}
              onChange={(e) => setEditCell(e.target.value)}
              autoComplete="off"
              disabled={editSubmitting}
            />
          </div>
          <div className={`${tableStyles.field} ${tableStyles.formFull}`}>
            <label htmlFor="edit-email">Email (optional)</label>
            <input
              id="edit-email"
              type="email"
              value={editEmail}
              onChange={(e) => setEditEmail(e.target.value)}
              disabled={editSubmitting}
            />
          </div>
        </div>
        <div style={{ height: 12 }} />
        <div className={tableStyles.actionsRow}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={() => setEditOpen(false)}
            disabled={editSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
            onClick={() => void submitEdit()}
            disabled={
              editSubmitting ||
              !editFirstName.trim() ||
              !editLastName.trim() ||
              !editCell.trim()
            }
          >
            Save
          </button>
        </div>
      </Modal>

      <Modal
        open={resetOpen}
        title="Reset password"
        onClose={() => {
          setResetOpen(false)
          setResetUser(null)
          setResetError('')
        }}
      >
        {resetError ? (
          <p className={tableStyles.alertError} role="alert">
            {resetError}
          </p>
        ) : null}
        <p className={tableStyles.meta} style={{ marginBottom: 12 }}>
          Set a new password for {resetUser ? displayName(resetUser) : 'user'}.
        </p>
        <div className={tableStyles.field}>
          <label htmlFor="reset-password">New password</label>
          <input
            id="reset-password"
            type="password"
            autoComplete="new-password"
            value={resetPassword}
            onChange={(e) => setResetPassword(e.target.value)}
            disabled={resetSubmitting}
          />
        </div>
        <div style={{ height: 10 }} />
        <div className={tableStyles.field}>
          <label htmlFor="reset-confirm">Confirm password</label>
          <input
            id="reset-confirm"
            type="password"
            autoComplete="new-password"
            value={resetConfirm}
            onChange={(e) => setResetConfirm(e.target.value)}
            disabled={resetSubmitting}
          />
        </div>
        <div style={{ height: 12 }} />
        <div className={tableStyles.actionsRow}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={() => setResetOpen(false)}
            disabled={resetSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
            onClick={() => void submitResetPassword()}
            disabled={resetSubmitting || !canResetPassword}
          >
            Reset
          </button>
        </div>
      </Modal>

      <Modal
        open={messageOpen}
        title="Send SMS message"
        onClose={() => {
          setMessageOpen(false)
          setMessageUser(null)
          setMessageError('')
        }}
      >
        {messageError ? (
          <p className={tableStyles.alertError} role="alert">
            {messageError}
          </p>
        ) : null}
        <p className={tableStyles.meta} style={{ marginBottom: 12 }}>
          Send an SMS to {messageUser ? formatCellForDisplay(messageUser.cellNumber) : 'user'}.
        </p>
        <div className={tableStyles.field}>
          <label htmlFor="sms-message">Message</label>
          <textarea
            id="sms-message"
            value={messageText}
            onChange={(e) => setMessageText(e.target.value)}
            disabled={messageSubmitting}
            rows={4}
          />
        </div>
        <div style={{ height: 12 }} />
        <div className={tableStyles.actionsRow}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={() => setMessageOpen(false)}
            disabled={messageSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
            onClick={() => void submitSendMessage()}
            disabled={messageSubmitting || !messageText.trim()}
          >
            Send
          </button>
        </div>
      </Modal>

      <Modal
        open={roleOpen}
        title="Change role"
        onClose={() => {
          setRoleOpen(false)
          setRoleUser(null)
          setSelectedTeamRoleSlug('admin')
          setRoleError('')
        }}
      >
        {roleError ? (
          <p className={tableStyles.alertError} role="alert">
            {roleError}
          </p>
        ) : null}
        <p className={tableStyles.meta} style={{ marginBottom: 12 }}>
          {businessFilter
            ? `Choose customer or manager access for ${roleUser ? displayName(roleUser) : 'user'} on ${businessFilter.businessName}.`
            : `Select a role for ${roleUser ? displayName(roleUser) : 'user'}.`}
        </p>

        {businessFilter ? (
          <>
            <div className={styles.roleList}>
              <label className={styles.roleOption}>
                <input
                  type="radio"
                  name="business-access"
                  value="customer"
                  checked={businessAccess === 'customer'}
                  onChange={() => setBusinessAccess('customer')}
                  disabled={roleSubmitting}
                />
                <span className={styles.roleOptionLabel}>Customer</span>
              </label>
              <label className={styles.roleOption}>
                <input
                  type="radio"
                  name="business-access"
                  value="staff"
                  checked={businessAccess === 'staff'}
                  onChange={() => {
                    setBusinessAccess('staff')
                    if (!selectedTeamRoleSlug) {
                      setSelectedTeamRoleSlug(orderedTeamRoles[0]?.slug || 'admin')
                    }
                  }}
                  disabled={roleSubmitting}
                />
                <span className={styles.roleOptionLabel}>Manager</span>
              </label>
            </div>

            {businessAccess === 'staff' ? (
              <>
                <p className={styles.roleHint}>
                  Only a super admin can assign Admin. Admins can assign Editor or Observer.
                </p>
                <div className={`${styles.roleList} ${styles.roleListNested}`}>
                  {orderedTeamRoles.map((role) => (
                    <label key={role.slug} className={styles.roleOption}>
                      <input
                        type="radio"
                        name="team-role"
                        value={role.slug}
                        checked={selectedTeamRoleSlug === role.slug}
                        onChange={() => setSelectedTeamRoleSlug(role.slug)}
                        disabled={roleSubmitting}
                      />
                      <span className={styles.roleOptionLabel}>
                        {teamRoleLabel(role.slug, teamRoles) ?? role.name}
                      </span>
                    </label>
                  ))}
                </div>
              </>
            ) : null}
          </>
        ) : (
          <div className={styles.roleList}>
            {roles.map((role) => (
              <label key={role.slug} className={styles.roleOption}>
                <input
                  type="radio"
                  name="user-role"
                  value={role.slug}
                  checked={selectedRoleSlug === role.slug}
                  onChange={() => setSelectedRoleSlug(role.slug)}
                  disabled={roleSubmitting}
                />
                <span className={styles.roleOptionLabel}>{role.name}</span>
              </label>
            ))}
          </div>
        )}

        <div style={{ height: 12 }} />
        <div className={tableStyles.actionsRow}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={() => setRoleOpen(false)}
            disabled={roleSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
            onClick={() => void submitRoleChange()}
            disabled={roleSubmitting || !canSaveRole}
          >
            Save
          </button>
        </div>
      </Modal>

      <ConfirmDeleteModal
        open={removeTarget !== null}
        title="Remove user?"
        message={
          removeTarget
            ? `Are you sure you want to remove "${displayName(removeTarget)}"? They will no longer be able to sign in.`
            : ''
        }
        onCancel={() => setRemoveTarget(null)}
        onConfirm={() => void confirmRemove()}
      />

      {businessFilter?.membership === 'all' && (
        <button
          type="button"
          className={tableStyles.fab}
          onClick={openCreate}
          aria-label="Add user to business"
          title="Add user to business"
        >
          <Plus size={24} />
        </button>
      )}

      <Modal
        open={createOpen}
        title={`Add user to ${businessFilter?.businessName ?? 'business'}`}
        onClose={() => {
          setCreateOpen(false)
          resetCreateForm()
        }}
      >
        {createError ? (
          <p className={tableStyles.alertError} role="alert">
            {createError}
          </p>
        ) : null}
        <p className={tableStyles.meta} style={{ marginBottom: 12 }}>
          Creates a new account or links an existing user as a customer of this business.
          Password is required only for new accounts.
        </p>
        <div className={tableStyles.formGrid}>
          <div className={tableStyles.field}>
            <label htmlFor="create-user-first-name">First name</label>
            <input
              id="create-user-first-name"
              value={createFirstName}
              onChange={(e) => setCreateFirstName(e.target.value)}
              disabled={createSubmitting}
            />
          </div>
          <div className={tableStyles.field}>
            <label htmlFor="create-user-last-name">Last name</label>
            <input
              id="create-user-last-name"
              value={createLastName}
              onChange={(e) => setCreateLastName(e.target.value)}
              disabled={createSubmitting}
            />
          </div>
          <div className={`${tableStyles.field} ${tableStyles.formFull}`}>
            <label htmlFor="create-user-cell">Cell number</label>
            <input
              id="create-user-cell"
              value={createCell}
              onChange={(e) => setCreateCell(e.target.value)}
              placeholder="0912..."
              autoComplete="off"
              disabled={createSubmitting}
            />
          </div>
          <div className={`${tableStyles.field} ${tableStyles.formFull}`}>
            <label htmlFor="create-user-password">Password (new users)</label>
            <input
              id="create-user-password"
              type="password"
              autoComplete="new-password"
              value={createPassword}
              onChange={(e) => setCreatePassword(e.target.value)}
              placeholder="Min. 8 characters"
              disabled={createSubmitting}
            />
          </div>
          <div className={`${tableStyles.field} ${tableStyles.formFull}`}>
            <label htmlFor="create-user-email">Email (optional)</label>
            <input
              id="create-user-email"
              type="email"
              value={createEmail}
              onChange={(e) => setCreateEmail(e.target.value)}
              disabled={createSubmitting}
            />
          </div>
        </div>
        <div style={{ height: 12 }} />
        <div className={tableStyles.actionsRow}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={() => setCreateOpen(false)}
            disabled={createSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
            onClick={() => void submitCreate()}
            disabled={createSubmitting || !canCreateUser}
          >
            Add user
          </button>
        </div>
      </Modal>
    </main>
  )
}
