'use client';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * User detail drawer — opened from a Team members row. Five tabs:
 *
 *   Overview     — identity, role, status, lifecycle facts, content owned.
 *   Security     — MFA / password / lock state + admin security actions.
 *   Sessions     — active sessions with per-session + bulk revoke.
 *   Activity     — recent audit events where the user is actor or target.
 *   Permissions  — read-only effective role + permission scopes.
 *
 * Every mutating action is permission-checked and audited server-side. The
 * high-impact ones (MFA reset, Admin/Owner password reset) return a 401
 * "reauth required" which this component handles by prompting for the admin's
 * password and retrying with the `x-reauth-password` header.
 */
import * as Tabs from '@radix-ui/react-tabs';
import { ShieldCheck, ShieldAlert, KeyRound, Lock, Unlock, Ban, Monitor, LogOut, Activity as ActivityIcon, FileText, AlertTriangle, Check, } from 'lucide-react';
import { useCallback, useState } from 'react';
import { toast } from 'sonner';
import { cmsApi } from '../../lib/api.js';
import { useApiData } from '../../lib/useApiData.js';
import { Drawer } from '../../components/forms/Drawer.js';
import { Modal } from '../../components/ui/Modal.js';
import { Button } from '../../components/ui/Button.js';
import { Skeleton } from '../../components/ui/Skeleton.js';
import { EmptyState } from '../../components/ui/EmptyState.js';
import { ConfirmDialog } from '../../components/ui/ConfirmDialog.js';
// ---------------------------------------------------------------------------
// Formatting helpers
// ---------------------------------------------------------------------------
function relativeTime(iso) {
    if (!iso)
        return 'Never';
    const then = new Date(iso).getTime();
    if (Number.isNaN(then))
        return '—';
    const diffMs = Date.now() - then;
    const mins = Math.floor(diffMs / 60000);
    if (mins < 5)
        return 'Just now';
    if (mins < 60)
        return `${mins}m ago`;
    const hours = Math.floor(mins / 60);
    if (hours < 24)
        return `${hours}h ago`;
    const days = Math.floor(hours / 24);
    if (days === 1)
        return 'Yesterday';
    return `${days} days ago`;
}
function formatDate(iso) {
    if (!iso)
        return '—';
    const d = new Date(iso);
    if (Number.isNaN(d.getTime()))
        return '—';
    return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
}
function humanizeEvent(event) {
    return event.replace(/_/g, ' ').replace(/^\w/, (c) => c.toUpperCase());
}
const ROLE_PILL = {
    Owner: 'bg-brand/10 text-brand',
    Admin: 'bg-info/10 text-info',
    Editor: 'bg-accent text-accent-foreground',
    Viewer: 'bg-muted text-muted-foreground',
};
const STATUS_META = {
    active: { dot: 'bg-success', text: 'text-success', label: 'Active' },
    suspended: { dot: 'bg-muted-foreground', text: 'text-muted-foreground', label: 'Suspended' },
    locked: { dot: 'bg-destructive', text: 'text-destructive', label: 'Locked' },
    deactivated: {
        dot: 'bg-muted-foreground',
        text: 'text-muted-foreground',
        label: 'Deactivated',
    },
};
// ---------------------------------------------------------------------------
// Reauth dialog
// ---------------------------------------------------------------------------
function ReauthDialog({ open, onClose, onSubmit, }) {
    const [password, setPassword] = useState('');
    const [busy, setBusy] = useState(false);
    const submit = async () => {
        if (!password || busy)
            return;
        setBusy(true);
        try {
            await onSubmit(password);
            setPassword('');
        }
        finally {
            setBusy(false);
        }
    };
    return (_jsxs(Modal, { open: open, onClose: () => {
            setPassword('');
            onClose();
        }, title: "Confirm it's you", actions: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "ghost", onClick: () => {
                        setPassword('');
                        onClose();
                    }, children: "Cancel" }), _jsx(Button, { variant: "primary", loading: busy, disabled: !password || busy, onClick: submit, children: "Confirm" })] }), children: [_jsx("p", { className: "text-muted-foreground mb-3 text-sm", children: "This is a sensitive action. Re-enter your password to continue." }), _jsx("label", { htmlFor: "reauth-password", className: "text-card-foreground mb-1 block text-sm font-medium", children: "Your password" }), _jsx("input", { id: "reauth-password", type: "password", value: password, onChange: (e) => setPassword(e.target.value), onKeyDown: (e) => {
                    if (e.key === 'Enter')
                        submit();
                }, autoComplete: "current-password", className: "border-border bg-input-background text-foreground focus:ring-brand w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none" })] }));
}
function TransferContentModal({ open, onClose, fromUser, onTransferred, }) {
    // Only fetch the directory while the picker is open.
    const members = useApiData(open ? '/users' : null);
    const [toUserId, setToUserId] = useState('');
    const [busy, setBusy] = useState(false);
    const recipients = (members.data ?? []).filter((m) => m.id !== fromUser.id && m.status === 'active');
    const submit = async () => {
        if (!toUserId || busy)
            return;
        setBusy(true);
        try {
            const res = await cmsApi(`/users/${fromUser.id}/transfer-content`, {
                method: 'POST',
                body: JSON.stringify({ toUserId }),
            });
            if (res.error) {
                toast.error(res.error);
                return;
            }
            const c = res.data;
            toast.success(c && c.total > 0
                ? `Transferred ${c.total} item${c.total === 1 ? '' : 's'} (${c.documents} docs, ${c.media} media, ${c.templates} templates).`
                : 'Nothing to transfer.');
            setToUserId('');
            onClose();
            onTransferred();
        }
        finally {
            setBusy(false);
        }
    };
    return (_jsxs(Modal, { open: open, onClose: () => {
            setToUserId('');
            onClose();
        }, title: "Transfer content ownership", actions: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "ghost", onClick: () => {
                        setToUserId('');
                        onClose();
                    }, children: "Cancel" }), _jsx(Button, { variant: "primary", loading: busy, disabled: !toUserId || busy, onClick: submit, children: "Transfer" })] }), children: [_jsxs("p", { className: "text-muted-foreground mb-3 text-sm", children: ["Reassign ", fromUser.name, "'s authored documents, uploaded media, and templates to another active member. Version history and audit records are left unchanged."] }), _jsx("label", { htmlFor: "transfer-to", className: "text-card-foreground mb-1 block text-sm font-medium", children: "Transfer to" }), members.loading ? (_jsx(Skeleton, { variant: "table-row", lines: 1 })) : recipients.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-sm", children: "No other active members to receive the content." })) : (_jsxs("select", { id: "transfer-to", value: toUserId, onChange: (e) => setToUserId(e.target.value), className: "border-border bg-input-background text-foreground focus:ring-brand w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none", children: [_jsx("option", { value: "", children: "Select a member\u2026" }), recipients.map((m) => (_jsxs("option", { value: m.id, children: [m.name, " (", m.email, ")"] }, m.id)))] }))] }));
}
// ---------------------------------------------------------------------------
// Small presentational bits
// ---------------------------------------------------------------------------
function Fact({ label, value }) {
    return (_jsxs("div", { className: "min-w-0", children: [_jsx("dt", { className: "text-muted-foreground text-xs", children: label }), _jsx("dd", { className: "text-card-foreground mt-0.5 truncate text-sm", children: value })] }));
}
function SecurityRow({ icon, title, description, action, }) {
    return (_jsxs("div", { className: "border-border flex items-center justify-between gap-3 border-b py-3 last:border-b-0", children: [_jsxs("div", { className: "flex min-w-0 items-start gap-2.5", children: [_jsx("span", { className: "text-muted-foreground mt-0.5 shrink-0", children: icon }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-card-foreground text-sm font-medium", children: title }), _jsx("div", { className: "text-muted-foreground text-xs", children: description })] })] }), _jsx("div", { className: "shrink-0", children: action })] }));
}
// ---------------------------------------------------------------------------
// Drawer
// ---------------------------------------------------------------------------
const TABS = [
    { id: 'overview', label: 'Overview' },
    { id: 'security', label: 'Security' },
    { id: 'sessions', label: 'Sessions' },
    { id: 'activity', label: 'Activity' },
    { id: 'permissions', label: 'Permissions' },
];
export function UserDetailDrawer({ userId, open, onOpenChange, onChanged }) {
    const [tab, setTab] = useState('overview');
    const detailEp = open && userId ? `/users/${userId}` : null;
    const detail = useApiData(detailEp);
    const sessionsEp = open && userId && tab === 'sessions' ? `/users/${userId}/sessions` : null;
    const sessions = useApiData(sessionsEp);
    const activityEp = open && userId && tab === 'activity' ? `/users/${userId}/activity` : null;
    const activity = useApiData(activityEp);
    const permsEp = open && userId && tab === 'permissions' ? `/users/${userId}/permissions` : null;
    const perms = useApiData(permsEp);
    const [reauth, setReauth] = useState(null);
    const [confirm, setConfirm] = useState(null);
    const [pending, setPending] = useState(null);
    const [showTransfer, setShowTransfer] = useState(false);
    const refreshAfterChange = useCallback(() => {
        detail.refetch();
        onChanged?.();
    }, [detail, onChanged]);
    /**
     * Run a mutating action. If the server demands reauthentication (401), prompt
     * for the password and retry once with the `x-reauth-password` header.
     */
    const runAction = useCallback(async (key, path, options, { successMsg, after }) => {
        setPending(key);
        try {
            const res = await cmsApi(path, options);
            if (res.status === 401 && /re-?authenticat/i.test(res.error ?? '')) {
                setReauth({
                    run: async (password) => {
                        const retry = await cmsApi(path, {
                            ...options,
                            headers: { ...(options.headers ?? {}), 'x-reauth-password': password },
                        });
                        if (retry.error) {
                            toast.error(retry.error);
                            return;
                        }
                        toast.success(successMsg);
                        setReauth(null);
                        after?.();
                    },
                });
                return;
            }
            if (res.error) {
                toast.error(res.error);
                return;
            }
            toast.success(successMsg);
            after?.();
        }
        finally {
            setPending(null);
        }
    }, []);
    const u = detail.data;
    return (_jsx(_Fragment, { children: _jsxs(Drawer, { open: open, onOpenChange: onOpenChange, width: "max-w-xl", title: u ? u.name : detail.loading ? 'Loading…' : 'User', description: u?.email, headerExtra: u ? (_jsx("span", { className: `mr-1 inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${ROLE_PILL[u.roleName] ?? ROLE_PILL.Viewer}`, children: u.roleName })) : undefined, children: [detail.loading ? (_jsxs("div", { className: "space-y-3", children: [_jsx(Skeleton, { variant: "card" }), _jsx(Skeleton, { variant: "table-row", lines: 4 })] })) : detail.error || !u ? (_jsxs("div", { className: "flex items-center gap-3 py-6", children: [_jsx(AlertTriangle, { size: 18, className: "text-destructive shrink-0", "aria-hidden": true }), _jsx("span", { className: "text-destructive flex-1 text-sm", children: detail.error ?? 'User not found.' }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => detail.refetch(), children: "Retry" })] })) : (_jsxs(Tabs.Root, { value: tab, onValueChange: setTab, children: [_jsx(Tabs.List, { className: "border-border mb-4 flex gap-1 overflow-x-auto border-b", "aria-label": "User detail sections", children: TABS.map((t) => (_jsx(Tabs.Trigger, { value: t.id, className: "text-muted-foreground hover:text-foreground data-[state=active]:text-foreground data-[state=active]:border-brand focus-visible:ring-ring -mb-px shrink-0 border-b-2 border-transparent px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none", children: t.label }, t.id))) }), _jsxs(Tabs.Content, { value: "overview", tabIndex: -1, className: "focus:outline-none", children: [_jsxs("div", { className: "mb-4 flex items-center gap-2", children: [_jsxs("span", { className: `inline-flex items-center gap-1.5 text-sm ${STATUS_META[u.status].text}`, children: [_jsx("span", { className: `h-2 w-2 rounded-full ${STATUS_META[u.status].dot}`, "aria-hidden": true }), STATUS_META[u.status].label] }), u.isCurrentUser && (_jsx("span", { className: "bg-muted text-muted-foreground rounded px-1.5 py-0.5 text-xs", children: "You" })), u.externalDomain && (_jsx("span", { className: "bg-warning/10 text-warning rounded px-1.5 py-0.5 text-xs", children: "External domain" }))] }), _jsxs("dl", { className: "grid grid-cols-2 gap-x-4 gap-y-4", children: [_jsx(Fact, { label: "Role", value: u.roleName }), _jsx(Fact, { label: "Status", value: STATUS_META[u.status].label }), _jsx(Fact, { label: "Last active", value: relativeTime(u.lastActiveAt) }), _jsx(Fact, { label: "Last sign-in", value: relativeTime(u.lastLoginAt) }), _jsx(Fact, { label: "Created", value: formatDate(u.createdAt) }), _jsx(Fact, { label: "Accepted invite", value: formatDate(u.acceptedInviteAt) }), _jsx(Fact, { label: "Invited by", value: u.invitedBy ? (u.invitedBy.name) : (_jsx("span", { className: "text-muted-foreground", children: "\u2014" })) }), _jsx(Fact, { label: "Email domain", value: u.email.split('@')[1] ?? '—' }), _jsx(Fact, { label: "Content owned", value: `${u.contentOwnedCount} ${u.contentOwnedCount === 1 ? 'item' : 'items'}` }), _jsx(Fact, { label: "Email verified", value: u.emailVerified ? 'Yes' : _jsx("span", { className: "text-warning", children: "No" }) }), u.authProvider && _jsx(Fact, { label: "Auth provider", value: u.authProvider }), u.oauthProviders.length > 0 && (_jsx(Fact, { label: "Connected accounts", value: u.oauthProviders.join(', ') }))] }), u.contentOwnedCount > 0 && (_jsxs("div", { className: "border-info/30 bg-info/5 mt-4 flex items-start gap-2 rounded-md border p-3", children: [_jsx(FileText, { size: 14, className: "text-info mt-0.5 shrink-0", "aria-hidden": true }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("p", { className: "text-muted-foreground text-xs", children: ["This user owns ", u.contentOwnedCount, " content", ' ', u.contentOwnedCount === 1 ? 'item' : 'items', ". Revoking access suspends the account and preserves their content and authorship \u2014 or reassign it to another member first."] }), _jsx(Button, { size: "sm", variant: "outline", className: "mt-2", leftIcon: _jsx(FileText, { size: 14, "aria-hidden": true }), onClick: () => setShowTransfer(true), children: "Transfer content" })] })] }))] }), _jsxs(Tabs.Content, { value: "security", tabIndex: -1, className: "focus:outline-none", children: [_jsx(SecurityRow, { icon: u.mfaEnabled ? _jsx(ShieldCheck, { size: 16 }) : _jsx(ShieldAlert, { size: 16 }), title: "Multi-factor authentication", description: u.mfaEnabled
                                        ? 'Enabled for this account.'
                                        : u.mfaRequired
                                            ? 'Required but not yet enrolled.'
                                            : 'Not enabled.', action: _jsxs("div", { className: "flex items-center gap-2", children: [!u.mfaRequired && (_jsx(Button, { size: "sm", variant: "outline", loading: pending === 'require-mfa', onClick: () => runAction('require-mfa', `/users/${u.id}/require-mfa`, { method: 'POST', body: JSON.stringify({ required: true }) }, {
                                                    successMsg: 'MFA is now required for this user.',
                                                    after: refreshAfterChange,
                                                }), children: "Require MFA" })), _jsx(Button, { size: "sm", variant: "outline", disabled: !u.mfaEnabled, title: !u.mfaEnabled ? 'No MFA enrolment to reset' : undefined, loading: pending === 'mfa-reset', onClick: () => setConfirm({
                                                    title: 'Reset MFA enrolment',
                                                    description: `This clears ${u.name}'s authenticator and backup codes and signs them out everywhere. Resetting MFA temporarily lowers account protection until the user re-enrols. You'll be asked to confirm your password.`,
                                                    confirmLabel: 'Reset MFA',
                                                    destructive: true,
                                                    onConfirm: () => runAction('mfa-reset', `/users/${u.id}/mfa-reset`, { method: 'POST' }, { successMsg: 'MFA enrolment reset.', after: refreshAfterChange }),
                                                }), children: "Reset MFA" })] }) }), _jsx(SecurityRow, { icon: _jsx(KeyRound, { size: 16 }), title: "Password", description: u.ssoOnly
                                        ? 'Signs in via an external identity provider — no local password.'
                                        : u.forcePasswordReset
                                            ? 'Must set a new password on next sign-in.'
                                            : u.passwordSet
                                                ? 'A password is set.'
                                                : 'No password set yet.', action: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { size: "sm", variant: "outline", disabled: u.ssoOnly || !u.passwordSet, title: u.ssoOnly ? 'External identity provider — no password to reset' : undefined, loading: pending === 'password-reset', onClick: () => runAction('password-reset', `/users/${u.id}/password-reset`, { method: 'POST' }, { successMsg: `Password reset email sent to ${u.email}.` }), children: "Send reset" }), _jsx(Button, { size: "sm", variant: "outline", disabled: u.ssoOnly, loading: pending === 'force-reset', onClick: () => runAction('force-reset', `/users/${u.id}/force-password-reset`, {
                                                    method: 'POST',
                                                    body: JSON.stringify({ enabled: !u.forcePasswordReset }),
                                                }, {
                                                    successMsg: u.forcePasswordReset
                                                        ? 'Forced reset cleared.'
                                                        : 'User must reset password on next sign-in.',
                                                    after: refreshAfterChange,
                                                }), children: u.forcePasswordReset ? 'Clear forced reset' : 'Force reset' })] }) }), _jsx(SecurityRow, { icon: _jsx(ShieldAlert, { size: 16 }), title: "Failed sign-ins", description: `${u.failedLoginCount} failed ${u.failedLoginCount === 1 ? 'attempt' : 'attempts'} on record.`, action: null }), _jsx(SecurityRow, { icon: u.status === 'locked' ? _jsx(Lock, { size: 16 }) : _jsx(Unlock, { size: 16 }), title: "Account lock", description: u.status === 'locked' ? 'Locked by a security policy or an admin.' : 'Not locked.', action: u.status === 'locked' ? (_jsx(Button, { size: "sm", variant: "outline", loading: pending === 'unlock', onClick: () => runAction('unlock', `/users/${u.id}/unlock`, { method: 'POST' }, { successMsg: 'Account unlocked.', after: refreshAfterChange }), children: "Unlock" })) : (_jsx(Button, { size: "sm", variant: "outline", disabled: u.isCurrentUser, title: u.isCurrentUser ? 'You cannot lock your own account' : undefined, loading: pending === 'lock', onClick: () => setConfirm({
                                            title: 'Lock account',
                                            description: `${u.name} will be blocked from signing in and all their sessions will be revoked until you unlock the account.`,
                                            confirmLabel: 'Lock account',
                                            destructive: true,
                                            onConfirm: () => runAction('lock', `/users/${u.id}/lock`, { method: 'POST' }, { successMsg: 'Account locked.', after: refreshAfterChange }),
                                        }), children: "Lock" })) }), _jsx(SecurityRow, { icon: _jsx(Ban, { size: 16 }), title: "Account access", description: u.status === 'suspended'
                                        ? 'Suspended — cannot sign in, history preserved.'
                                        : 'Active — can sign in.', action: u.status === 'suspended' || u.status === 'deactivated' ? (_jsx(Button, { size: "sm", variant: "outline", loading: pending === 'reactivate', onClick: () => runAction('reactivate', `/users/${u.id}/reactivate`, { method: 'POST' }, { successMsg: 'Access restored.', after: refreshAfterChange }), children: "Reactivate" })) : (_jsx(Button, { size: "sm", variant: "outline", disabled: u.isCurrentUser, title: u.isCurrentUser ? 'You cannot suspend your own account' : undefined, loading: pending === 'suspend', onClick: () => setConfirm({
                                            title: 'Suspend user',
                                            description: `${u.name} will be blocked from signing in and signed out everywhere. Their content and history are preserved, and you can reactivate them later.`,
                                            confirmLabel: 'Suspend',
                                            destructive: true,
                                            onConfirm: () => runAction('suspend', `/users/${u.id}/suspend`, { method: 'POST' }, { successMsg: 'User suspended.', after: refreshAfterChange }),
                                        }), children: "Suspend" })) })] }), _jsx(Tabs.Content, { value: "sessions", tabIndex: -1, className: "focus:outline-none", children: sessions.loading ? (_jsx(Skeleton, { variant: "table-row", lines: 3 })) : sessions.error ? (_jsxs("div", { className: "flex items-center gap-3 py-4", children: [_jsx(AlertTriangle, { size: 16, className: "text-destructive shrink-0", "aria-hidden": true }), _jsx("span", { className: "text-destructive flex-1 text-sm", children: sessions.error }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => sessions.refetch(), children: "Retry" })] })) : (sessions.data?.filter((s) => s.active).length ?? 0) === 0 ? (_jsx(EmptyState, { icon: _jsx(Monitor, { size: 24, "aria-hidden": true }), title: "No active sessions", description: "This user isn't signed in on any device." })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "mb-3 flex justify-end", children: _jsx(Button, { size: "sm", variant: "outline", loading: pending === 'revoke-all', leftIcon: _jsx(LogOut, { size: 14, "aria-hidden": true }), onClick: () => setConfirm({
                                                title: 'Revoke all sessions',
                                                description: `${u.name} will be signed out of every device${u.isCurrentUser ? ' except this one' : ''}.`,
                                                confirmLabel: 'Revoke all',
                                                destructive: true,
                                                onConfirm: () => runAction('revoke-all', `/users/${u.id}/sessions/revoke-all`, { method: 'POST' }, { successMsg: 'Sessions revoked.', after: () => sessions.refetch() }),
                                            }), children: "Revoke all" }) }), _jsx("ul", { className: "space-y-2", children: sessions.data
                                            ?.filter((s) => s.active)
                                            .map((s) => (_jsxs("li", { className: "border-border flex items-center justify-between gap-3 rounded-md border p-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [_jsx(Monitor, { size: 16, className: "text-muted-foreground shrink-0", "aria-hidden": true }), _jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "text-card-foreground flex items-center gap-1.5 text-sm", children: [_jsx("span", { className: "truncate", children: s.deviceLabel }), s.current && (_jsx("span", { className: "bg-success/10 text-success rounded px-1 text-[10px]", children: "This device" }))] }), _jsxs("div", { className: "text-muted-foreground text-xs", children: ["Signed in ", relativeTime(s.createdAt), " \u00B7 expires", ' ', formatDate(s.expiresAt)] })] })] }), _jsx("button", { type: "button", disabled: pending === `revoke-${s.id}`, onClick: () => runAction(`revoke-${s.id}`, `/users/${u.id}/sessions/${s.id}`, { method: 'DELETE' }, { successMsg: 'Session revoked.', after: () => sessions.refetch() }), className: "text-muted-foreground hover:text-destructive shrink-0 text-xs font-medium transition-colors disabled:opacity-50", children: "Revoke" })] }, s.id))) })] })) }), _jsx(Tabs.Content, { value: "activity", tabIndex: -1, className: "focus:outline-none", children: activity.loading ? (_jsx(Skeleton, { variant: "table-row", lines: 4 })) : activity.error ? (_jsxs("div", { className: "flex items-center gap-3 py-4", children: [_jsx(AlertTriangle, { size: 16, className: "text-destructive shrink-0", "aria-hidden": true }), _jsx("span", { className: "text-destructive flex-1 text-sm", children: activity.error }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => activity.refetch(), children: "Retry" })] })) : (activity.data?.length ?? 0) === 0 ? (_jsx(EmptyState, { icon: _jsx(ActivityIcon, { size: 24, "aria-hidden": true }), title: "No recent activity", description: "Audit events for this user will appear here." })) : (_jsx("ul", { className: "space-y-1", children: activity.data?.map((e) => (_jsxs("li", { className: "hover:bg-accent/30 flex items-center justify-between gap-3 rounded-md px-2 py-2", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [_jsx(ActivityIcon, { size: 14, className: "text-muted-foreground shrink-0", "aria-hidden": true }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-card-foreground truncate text-sm", children: humanizeEvent(e.event) }), _jsxs("div", { className: "text-muted-foreground text-xs", children: [e.role === 'target' ? 'Affected this user' : 'Performed by this user', e.ipAddress ? ` · ${e.ipAddress}` : ''] })] })] }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: relativeTime(e.timestamp) })] }, e.id))) })) }), _jsx(Tabs.Content, { value: "permissions", tabIndex: -1, className: "focus:outline-none", children: perms.loading ? (_jsx(Skeleton, { variant: "table-row", lines: 4 })) : perms.error ? (_jsxs("div", { className: "flex items-center gap-3 py-4", children: [_jsx(AlertTriangle, { size: 16, className: "text-destructive shrink-0", "aria-hidden": true }), _jsx("span", { className: "text-destructive flex-1 text-sm", children: perms.error }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => perms.refetch(), children: "Retry" })] })) : perms.data ? (_jsxs(_Fragment, { children: [_jsxs("p", { className: "text-muted-foreground mb-3 text-sm", children: ["Effective role", ' ', _jsx("span", { className: "text-card-foreground font-medium", children: perms.data.roleName }), ' ', "grants ", perms.data.permissions.length, " permission", perms.data.permissions.length === 1 ? '' : 's', ". Permissions are derived from the role and managed in configuration."] }), _jsx("ul", { className: "flex flex-wrap gap-1.5", children: perms.data.permissions.map((p) => (_jsxs("li", { className: "border-border bg-muted/50 text-card-foreground inline-flex items-center gap-1 rounded-md border px-2 py-1 text-xs", children: [_jsx(Check, { size: 12, className: "text-success", "aria-hidden": true }), p] }, p))) })] })) : null })] })), confirm && (_jsx(ConfirmDialog, { open: !!confirm, onClose: () => setConfirm(null), onConfirm: confirm.onConfirm, title: confirm.title, description: confirm.description, confirmLabel: confirm.confirmLabel, destructive: confirm.destructive })), _jsx(ReauthDialog, { open: !!reauth, onClose: () => setReauth(null), onSubmit: async (password) => {
                        if (reauth)
                            await reauth.run(password);
                    } }), u && (_jsx(TransferContentModal, { open: showTransfer, onClose: () => setShowTransfer(false), fromUser: { id: u.id, name: u.name, contentOwnedCount: u.contentOwnedCount }, onTransferred: refreshAfterChange }))] }) }));
}
//# sourceMappingURL=UserDetailDrawer.js.map