'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { useSearchParams } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { useRouter } from '@/i18n/navigation';
import {
  firstAccessibleDashboardPath,
  canEditStaff,
  canViewStaff,
} from '@/components/shared/permissions';
import { preserveHiddenTabPermissions } from '@/components/shared/hidden-tabs';
import {
  permissionNamesFromFeatureState,
  emptyFeaturePermissionState,
  featureStateFromPermissionNames,
  featureStateHasTreatmentEdit,
  resolveStaffFeatureLabel,
  formatAccessSummary,
  staffFeatureGroupsForOrgType,
  type FeaturePermState,
} from '@/components/staff/staff-permission-form';
import {
  StaffWorkingHoursStep,
  createDefaultWorkingHoursState,
  workingHoursPayloadFromState,
  workingHoursStateFromApi,
} from '@/components/ui/staff/StaffWorkingHoursStep';
import { validateEditorDays, type WorkingHoursEditorDay } from '@/components/staff/workingHours';
import { Pencil, Trash2, Copy, Check, X, UserX, UserCheck } from 'lucide-react';
import { DialogCloseButton } from '@/components/ui/shared/DialogCloseButton';
import { useAuth } from '@/lib/hooks/useAuth';
import { staffApi, type StaffMemberDto } from '@/lib/api/staff';
import { Button } from '@/components/ui/shared/Button';
import { Badge } from '@/components/ui/shared/Badge';
import { Input } from '@/components/ui/shared/Input';
import { Checkbox } from '@/components/ui/shared/Checkbox';
import { Table } from '@/components/ui/shared/Table';
import { getUserFacingError } from '@/components/shared/formatApiError';
import { StaffMembersMobileList } from '@/components/ui/staff/StaffMembersMobileList';
import { useToast } from '@/lib/hooks/useToast';
import {
  parseHighlightMembershipIds,
  STAFF_ROW_HIGHLIGHT_CLASS,
} from '@/components/staff/staffRowHighlight';
import { scrollWithinMainScrollContainer } from '@/components/shared/scrollWithinMain';

type StoredInviteLink = {
  membershipId: string;
  email: string;
  invitationUrl: string;
};

function inviteLinksStorageKey(orgId: string): string {
  return `staffInviteLinks:${orgId}`;
}

function readStoredInviteLinks(orgId: string): Record<string, StoredInviteLink> {
  if (typeof window === 'undefined') return {};
  try {
    const raw = window.localStorage.getItem(inviteLinksStorageKey(orgId));
    if (!raw) return {};
    const parsed = JSON.parse(raw) as Record<string, StoredInviteLink>;
    return parsed && typeof parsed === 'object' ? parsed : {};
  } catch {
    return {};
  }
}

function writeStoredInviteLinks(orgId: string, links: Record<string, StoredInviteLink>) {
  if (typeof window === 'undefined') return;
  window.localStorage.setItem(inviteLinksStorageKey(orgId), JSON.stringify(links));
}

function canShareStaffInviteLink(member: StaffMemberDto): boolean {
  return (
    !member.isOwner &&
    (member.invitationStatus === 'PENDING' || member.invitationStatus === 'EXPIRED')
  );
}

function canIssuePasswordSetup(member: StaffMemberDto, actorUserId?: string): boolean {
  return !member.isOwner && member.isActive && member.userId !== actorUserId;
}

function canDisableStaff(member: StaffMemberDto): boolean {
  return !member.isOwner && member.isActive;
}

function canEnableStaff(member: StaffMemberDto): boolean {
  return !member.isOwner && member.invitationStatus === 'DISABLED';
}

function PermissionGrid({
  state,
  onChange,
  disabled,
  organizationType,
}: {
  state: FeaturePermState;
  onChange: (next: FeaturePermState) => void;
  disabled?: boolean;
  organizationType?: 'CLINIC' | 'LAB';
}) {
  const t = useTranslations('staff');
  const tFeatures = useTranslations('staff.features');

  const setRead = (editKey: string, read: boolean) => {
    const cur = state[editKey] ?? { read: false, edit: false };
    onChange({
      ...state,
      [editKey]: { read, edit: read ? cur.edit : false },
    });
  };

  const setEdit = (editKey: string, edit: boolean) => {
    const cur = state[editKey] ?? { read: false, edit: false };
    onChange({
      ...state,
      [editKey]: { read: edit || cur.read, edit },
    });
  };

  return (
    <div className="grid gap-3 sm:grid-cols-2">
      {staffFeatureGroupsForOrgType(organizationType).map((g) => {
        const cell = state[g.edit] ?? { read: false, edit: false };
        return (
          <div
            key={g.edit}
            className="flex flex-col gap-3 rounded-[var(--radius-md)] border border-border/60 bg-background-card/50 px-3 py-3"
          >
            <span className="text-sm font-medium text-text-primary">
              {resolveStaffFeatureLabel(g, organizationType, tFeatures)}
            </span>
            <div className="flex flex-col gap-2.5 pl-0.5">
              <Checkbox
                checked={cell.read}
                disabled={disabled}
                label={t('permissionView')}
                onChange={(v) => setRead(g.edit, v)}
              />
              <Checkbox
                checked={cell.edit}
                disabled={disabled}
                label={t('permissionEdit')}
                onChange={(v) => setEdit(g.edit, v)}
              />
            </div>
          </div>
        );
      })}
    </div>
  );
}

export function StaffPage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const t = useTranslations('staff');
  const tErrors = useTranslations('errors');
  const tCommon = useTranslations('common');
  const tFeatures = useTranslations('staff.features');
  const tWorkingHours = useTranslations('staff.workingHours');
  const { currentOrganization, user } = useAuth();
  const [members, setMembers] = useState<StaffMemberDto[]>([]);
  const [seats, setSeats] = useState<{
    used: number;
    limit: number | null;
    unlimited: boolean;
  } | null>(null);
  const [loading, setLoading] = useState(true);
  const toast = useToast();

  const [inviteOpen, setInviteOpen] = useState(false);
  const [inviteStep, setInviteStep] = useState<1 | 2>(1);
  const [inviteEmail, setInviteEmail] = useState('');
  const [inviteName, setInviteName] = useState('');
  const [invitePerms, setInvitePerms] = useState(() => emptyFeaturePermissionState());
  const [inviteWorkingHoursDays, setInviteWorkingHoursDays] = useState<WorkingHoursEditorDay[]>(
    () => createDefaultWorkingHoursState().days,
  );
  const [inviteAutoRepeatWeekly, setInviteAutoRepeatWeekly] = useState(true);
  const [inviteHoursValidationError, setInviteHoursValidationError] = useState<string | null>(null);
  const [inviteLoading, setInviteLoading] = useState(false);
  const [copiedInviteMembershipId, setCopiedInviteMembershipId] = useState<string | null>(null);
  const [copyingInviteMembershipId, setCopyingInviteMembershipId] = useState<string | null>(null);
  const [lastInviteInfo, setLastInviteInfo] = useState<{
    membershipId: string;
    name: string;
    email: string;
    invitationUrl: string | null;
    invitationStatus: 'PENDING' | 'ACCEPTED';
  } | null>(null);
  const [pendingInviteLinks, setPendingInviteLinks] = useState<Record<string, StoredInviteLink>>({});
  const [lastPasswordSetupInfo, setLastPasswordSetupInfo] = useState<{
    membershipId: string;
    name: string;
    email: string;
    invitationUrl: string;
  } | null>(null);

  const [editing, setEditing] = useState<StaffMemberDto | null>(null);
  const [editStep, setEditStep] = useState<1 | 2>(1);
  const [editName, setEditName] = useState('');
  const [editPerms, setEditPerms] = useState(() => emptyFeaturePermissionState());
  const [editWorkingHoursDays, setEditWorkingHoursDays] = useState<WorkingHoursEditorDay[]>(
    () => createDefaultWorkingHoursState().days,
  );
  const [editAutoRepeatWeekly, setEditAutoRepeatWeekly] = useState(true);
  const [editHoursValidationError, setEditHoursValidationError] = useState<string | null>(null);
  const [editLoadingWorkingHours, setEditLoadingWorkingHours] = useState(false);
  const [editLoading, setEditLoading] = useState(false);
  const [disableTarget, setDisableTarget] = useState<StaffMemberDto | null>(null);
  const [disablingMembershipId, setDisablingMembershipId] = useState<string | null>(null);
  const [enableTarget, setEnableTarget] = useState<StaffMemberDto | null>(null);
  const [enablingMembershipId, setEnablingMembershipId] = useState<string | null>(null);
  const [clearPasswordTarget, setClearPasswordTarget] = useState<StaffMemberDto | null>(null);
  const [clearingMembershipId, setClearingMembershipId] = useState<string | null>(null);

  const canEdit = useMemo(() => canEditStaff(currentOrganization), [currentOrganization]);
  const highlightMembershipIds = useMemo(
    () => parseHighlightMembershipIds(searchParams),
    [searchParams],
  );
  const inviteHasTreatmentEdit = useMemo(
    () =>
      currentOrganization?.type === 'CLINIC' && featureStateHasTreatmentEdit(invitePerms),
    [currentOrganization?.type, invitePerms],
  );
  const editHasTreatmentEdit = useMemo(
    () => currentOrganization?.type === 'CLINIC' && featureStateHasTreatmentEdit(editPerms),
    [currentOrganization?.type, editPerms],
  );
  const hasActivePlan = Boolean(currentOrganization?.plan);
  const atSeatLimit = useMemo(() => {
    if (!seats || seats.unlimited) return false;
    if (seats.limit == null) return false;
    return seats.used >= seats.limit;
  }, [seats]);

  const hasAvailableSeat = useMemo(() => {
    if (!seats || seats.unlimited) return true;
    if (seats.limit == null) return true;
    return seats.used < seats.limit;
  }, [seats]);

  const load = useCallback(async () => {
    toast.setError('');
    setLoading(true);
    try {
      const res = await staffApi.list();
      setMembers(res.data.members);
      setSeats(res.data.seats);
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorLoadStaff')));
    } finally {
      setLoading(false);
    }
  }, [t]);

  useEffect(() => {
    if (!currentOrganization?.id) return;
    setPendingInviteLinks(readStoredInviteLinks(currentOrganization.id));
  }, [currentOrganization?.id]);

  useEffect(() => {
    if (!currentOrganization?.id || loading) return;

    const activeMemberIds = new Set(
      members
        .filter((m) => m.isOwner || m.invitationStatus === 'ACTIVE')
        .map((m) => m.id),
    );

    let changed = false;
    const nextLinks: Record<string, StoredInviteLink> = { ...pendingInviteLinks };
    for (const memberId of Object.keys(nextLinks)) {
      if (activeMemberIds.has(memberId)) {
        delete nextLinks[memberId];
        changed = true;
      }
    }
    if (!changed) return;

    setPendingInviteLinks(nextLinks);
    writeStoredInviteLinks(currentOrganization.id, nextLinks);
  }, [currentOrganization?.id, loading, members, pendingInviteLinks]);

  useEffect(() => {
    void load();
  }, [load]);

  useEffect(() => {
    if (loading || highlightMembershipIds.size === 0) return;
    const firstMatch = members.find((member) => highlightMembershipIds.has(member.id));
    if (!firstMatch) return;
    const frame = requestAnimationFrame(() => {
      scrollWithinMainScrollContainer(
        document.getElementById(`staff-row-${firstMatch.id}`),
      );
    });
    return () => cancelAnimationFrame(frame);
  }, [loading, members, highlightMembershipIds]);

  useEffect(() => {
    if (!currentOrganization) return;
    if (!canViewStaff(currentOrganization)) {
      router.replace(firstAccessibleDashboardPath(currentOrganization));
    }
  }, [currentOrganization, router]);

  async function copyStaffInviteLink(member: StaffMemberDto) {
    if (!canShareStaffInviteLink(member)) return;

    setCopyingInviteMembershipId(member.id);
    toast.setError('');
    try {
      let invitationUrl = pendingInviteLinks[member.id]?.invitationUrl;
      if (!invitationUrl || member.invitationStatus === 'EXPIRED') {
        const res = await staffApi.getInvitationLink(member.id);
        invitationUrl = res.data.invitationUrl;
        if (currentOrganization?.id) {
          const nextLinks = {
            ...pendingInviteLinks,
            [member.id]: {
              membershipId: member.id,
              email: member.email,
              invitationUrl,
            },
          };
          setPendingInviteLinks(nextLinks);
          writeStoredInviteLinks(currentOrganization.id, nextLinks);
        }
      }
      await navigator.clipboard.writeText(invitationUrl);
      setCopiedInviteMembershipId(member.id);
      setTimeout(() => setCopiedInviteMembershipId(null), 1500);
      if (member.invitationStatus === 'EXPIRED') {
        await load();
      }
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorCopyInvite')));
    } finally {
      setCopyingInviteMembershipId(null);
    }
  }

  function resetInviteForm() {
    setInviteStep(1);
    setInviteEmail('');
    setInviteName('');
    setInvitePerms(emptyFeaturePermissionState(currentOrganization?.type));
    const defaults = createDefaultWorkingHoursState();
    setInviteWorkingHoursDays(defaults.days);
    setInviteAutoRepeatWeekly(defaults.autoRepeatWeekly);
    setInviteHoursValidationError(null);
  }

  async function saveInviteWorkingHours(membershipId: string, includeHours: boolean) {
    if (!includeHours || !inviteHasTreatmentEdit) {
      return;
    }
    const validationError = validateEditorDays(inviteWorkingHoursDays, tWorkingHours);
    if (validationError) {
      throw new Error(validationError);
    }
    await staffApi.upsertWorkingHours(
      membershipId,
      workingHoursPayloadFromState({
        days: inviteWorkingHoursDays,
        autoRepeatWeekly: inviteAutoRepeatWeekly,
      }),
    );
  }

  async function submitInvite(includeWorkingHours: boolean) {
    setInviteLoading(true);
    toast.setError('');
    setLastInviteInfo(null);
    const displayName = inviteName.trim();
    const displayEmail = inviteEmail.trim();
    try {
      if (includeWorkingHours && inviteHasTreatmentEdit) {
        const validationError = validateEditorDays(inviteWorkingHoursDays, tWorkingHours);
        if (validationError) {
          toast.showError(validationError);
          return;
        }
      }

      const permissionNames = permissionNamesFromFeatureState(invitePerms);
      const res = await staffApi.invite({
        email: displayEmail,
        name: displayName,
        permissionNames,
      });

      if (includeWorkingHours) {
        await saveInviteWorkingHours(res.data.membershipId, true);
      }

      setLastInviteInfo({
        membershipId: res.data.membershipId,
        name: displayName,
        email: res.data.email,
        invitationUrl: res.data.invitationUrl,
        invitationStatus: res.data.invitationStatus,
      });
      if (currentOrganization?.id && res.data.invitationUrl) {
        const nextLinks = {
          ...pendingInviteLinks,
          [res.data.membershipId]: {
            membershipId: res.data.membershipId,
            email: res.data.email,
            invitationUrl: res.data.invitationUrl,
          },
        };
        setPendingInviteLinks(nextLinks);
        writeStoredInviteLinks(currentOrganization.id, nextLinks);
      }
      setInviteOpen(false);
      resetInviteForm();
      await load();
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorSendInvite')));
    } finally {
      setInviteLoading(false);
    }
  }

  async function openEdit(m: StaffMemberDto) {
    if (m.isOwner) return;
    setEditing(m);
    setEditStep(1);
    setEditName(m.name);
    setEditPerms(featureStateFromPermissionNames(m.permissions ?? [], currentOrganization?.type));
    setEditHoursValidationError(null);
    const defaults = createDefaultWorkingHoursState();
    setEditWorkingHoursDays(defaults.days);
    setEditAutoRepeatWeekly(defaults.autoRepeatWeekly);
    setEditLoadingWorkingHours(true);
    try {
      const res = await staffApi.getWorkingHours(m.id);
      const state = workingHoursStateFromApi(res.data);
      setEditWorkingHoursDays(state.days);
      setEditAutoRepeatWeekly(state.autoRepeatWeekly);
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorLoadWorkingHours')));
    } finally {
      setEditLoadingWorkingHours(false);
    }
  }

  async function submitEdit() {
    if (!editing) return;
    if (editHasTreatmentEdit) {
      const validationError = validateEditorDays(editWorkingHoursDays, tWorkingHours);
      if (validationError) {
        toast.showError(validationError);
        return;
      }
    }

    setEditLoading(true);
    toast.setError('');
    try {
      if (editHasTreatmentEdit) {
        await staffApi.upsertWorkingHours(
          editing.id,
          workingHoursPayloadFromState({
            days: editWorkingHoursDays,
            autoRepeatWeekly: editAutoRepeatWeekly,
          }),
        );
      }

      await staffApi.updateMember(editing.id, {
        name: editName.trim(),
        permissionNames: preserveHiddenTabPermissions(
          permissionNamesFromFeatureState(editPerms),
          editing.permissions,
        ),
      });

      toast.showSuccess(t('successMemberUpdated'));
      setEditing(null);
      setEditStep(1);
      await load();
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorUpdateMember')));
    } finally {
      setEditLoading(false);
    }
  }

  function handleDeleteMember() {
    toast.showError(t('errorDeleteNotImplemented'));
  }

  async function confirmDisableMember() {
    if (!disableTarget || !canDisableStaff(disableTarget)) return;

    setDisablingMembershipId(disableTarget.id);
    toast.setError('');
    try {
      await staffApi.disableMember(disableTarget.id);
      toast.showSuccess(t('successMemberDisabled', { name: disableTarget.name }));
      setDisableTarget(null);
      await load();
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorDisableMember')));
    } finally {
      setDisablingMembershipId(null);
    }
  }

  async function confirmEnableMember() {
    if (!enableTarget || !canEnableStaff(enableTarget) || !hasAvailableSeat) return;

    setEnablingMembershipId(enableTarget.id);
    toast.setError('');
    try {
      await staffApi.enableMember(enableTarget.id);
      toast.showSuccess(t('successMemberEnabled', { name: enableTarget.name }));
      setEnableTarget(null);
      await load();
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorEnableMember')));
    } finally {
      setEnablingMembershipId(null);
    }
  }

  async function issuePasswordSetupLink(member: StaffMemberDto, copyToClipboard: boolean) {
    setClearingMembershipId(member.id);
    toast.setError('');
    try {
      const res = await staffApi.clearPassword(member.id);
      setLastPasswordSetupInfo({
        membershipId: member.id,
        name: member.name,
        email: member.email,
        invitationUrl: res.data.invitationUrl,
      });
      setClearPasswordTarget(null);
      setEditing(null);
      setEditStep(1);
      await load();
      toast.showSuccess(t('successPasswordCleared', { name: member.name }));
      if (copyToClipboard) {
        try {
          await navigator.clipboard.writeText(res.data.invitationUrl);
          setCopiedInviteMembershipId(member.id);
          setTimeout(() => setCopiedInviteMembershipId(null), 1500);
        } catch {
          /* banner still shows the URL */
        }
      }
    } catch (e) {
      toast.showError(getUserFacingError(e, tErrors, t('errorClearPassword')));
    } finally {
      setClearingMembershipId(null);
    }
  }

  async function confirmClearPassword() {
    if (!clearPasswordTarget || !canIssuePasswordSetup(clearPasswordTarget, user?.id)) {
      return;
    }
    await issuePasswordSetupLink(clearPasswordTarget, true);
  }

  if (!currentOrganization || !canViewStaff(currentOrganization)) {
    return (
      <p className="text-sm text-text-secondary">{t('redirecting')}</p>
    );
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
        <div>
          <h1 className="text-xl sm:text-2xl font-semibold text-text-primary">{t('title')}</h1>
          <p className="text-sm text-text-secondary mt-1">{t('subtitle')}</p>
        </div>
        <Button
          size="sm"
          onClick={() => {
            if (!canEdit || atSeatLimit) return;
            resetInviteForm();
            setInviteOpen(true);
            setLastInviteInfo(null);
          }}
          disabled={!canEdit || atSeatLimit}
          className="shrink-0"
          title={!canEdit ? tCommon('readOnlyAccess') : undefined}
        >
          {t('inviteMember')}
        </Button>
      </div>

      {seats && (
        <p className="text-sm text-text-secondary">
          {t('seatsLabel')}{' '}
          <span className="text-text-primary font-medium">
            {seats.used}
            {seats.unlimited ? ` ${t('unlimitedPlan')}` : ` / ${seats.limit}`}
          </span>
          {!seats.unlimited && atSeatLimit && (
            <span className="text-amber-600 dark:text-amber-400 ml-2">
              {hasActivePlan ? t('seatLimitReached') : t('noActivePlan')}
            </span>
          )}
        </p>
      )}

      {lastInviteInfo && (
        <div className="relative rounded-[var(--radius-md)] border border-border-strong bg-background-secondary/90 px-4 py-3 pr-12 shadow-[inset_0_1px_0_rgba(255,255,255,0.04)] space-y-3">
          <button
            type="button"
            className="absolute right-2 top-2 p-1.5 rounded-[var(--radius-sm)] text-text-muted hover:text-text-primary hover:bg-background-card/80"
            aria-label={tCommon('dismiss')}
            onClick={() => {
              setLastInviteInfo(null);
            }}
          >
            <X className="w-4 h-4" />
          </button>
          <p className="text-sm text-text-primary pr-6">
            {t('successInvited', { name: lastInviteInfo.name, email: lastInviteInfo.email })}
            {lastInviteInfo.invitationStatus === 'PENDING'
              ? ` ${t('invitedPending')}`
              : ` ${t('invitedAccepted')}`}
          </p>
          {lastInviteInfo.invitationStatus === 'PENDING' && (
            <div className="space-y-2 pt-1 border-t border-border/60">
              <p className="text-xs font-medium text-text-secondary uppercase tracking-wide">
                {t('inviteLinkHeading')}
              </p>
              {lastInviteInfo.invitationUrl && (
                <code className="block text-sm px-2 py-1.5 rounded-[var(--radius-sm)] bg-background-card border border-border font-mono break-all">
                  {lastInviteInfo.invitationUrl}
                </code>
              )}
              <Button
                type="button"
                variant="outline"
                size="sm"
                isLoading={copyingInviteMembershipId === lastInviteInfo.membershipId}
                onClick={async () => {
                  const member = members.find((item) => item.id === lastInviteInfo.membershipId);
                  if (member) {
                    await copyStaffInviteLink(member);
                    return;
                  }
                  setCopyingInviteMembershipId(lastInviteInfo.membershipId);
                  toast.setError('');
                  try {
                    const res = await staffApi.getInvitationLink(lastInviteInfo.membershipId);
                    if (currentOrganization?.id) {
                      const nextLinks = {
                        ...pendingInviteLinks,
                        [lastInviteInfo.membershipId]: {
                          membershipId: lastInviteInfo.membershipId,
                          email: lastInviteInfo.email,
                          invitationUrl: res.data.invitationUrl,
                        },
                      };
                      setPendingInviteLinks(nextLinks);
                      writeStoredInviteLinks(currentOrganization.id, nextLinks);
                    }
                    setLastInviteInfo({ ...lastInviteInfo, invitationUrl: res.data.invitationUrl });
                    await navigator.clipboard.writeText(res.data.invitationUrl);
                    setCopiedInviteMembershipId(lastInviteInfo.membershipId);
                    setTimeout(() => setCopiedInviteMembershipId(null), 1500);
                  } catch (e) {
                    toast.showError(getUserFacingError(e, tErrors, t('errorCopyInvite')));
                  } finally {
                    setCopyingInviteMembershipId(null);
                  }
                }}
              >
                {copiedInviteMembershipId === lastInviteInfo.membershipId
                  ? tCommon('copied')
                  : tCommon('copyLink')}
              </Button>
              <p className="text-xs text-text-muted">{t('shareLinkHint')}</p>
            </div>
          )}
        </div>
      )}

      {lastPasswordSetupInfo && (
        <div className="relative rounded-[var(--radius-md)] border border-border-strong bg-background-secondary/90 px-4 py-3 pr-12 shadow-[inset_0_1px_0_rgba(255,255,255,0.04)] space-y-3">
          <button
            type="button"
            className="absolute right-2 top-2 p-1.5 rounded-[var(--radius-sm)] text-text-muted hover:text-text-primary hover:bg-background-card/80"
            aria-label={tCommon('dismiss')}
            onClick={() => setLastPasswordSetupInfo(null)}
          >
            <X className="w-4 h-4" />
          </button>
          <p className="text-sm text-text-primary pr-6">
            {t('successPasswordCleared', { name: lastPasswordSetupInfo.name })}
          </p>
          <div className="space-y-2 pt-1 border-t border-border/60">
            <p className="text-xs font-medium text-text-secondary uppercase tracking-wide">
              {t('passwordSetupLinkHeading')}
            </p>
            <code className="block text-sm px-2 py-1.5 rounded-[var(--radius-sm)] bg-background-card border border-border font-mono break-all">
              {lastPasswordSetupInfo.invitationUrl}
            </code>
            <Button
              type="button"
              variant="outline"
              size="sm"
              isLoading={clearingMembershipId === lastPasswordSetupInfo.membershipId}
              onClick={async () => {
                setClearingMembershipId(lastPasswordSetupInfo.membershipId);
                toast.setError('');
                try {
                  await navigator.clipboard.writeText(lastPasswordSetupInfo.invitationUrl);
                  setCopiedInviteMembershipId(lastPasswordSetupInfo.membershipId);
                  setTimeout(() => setCopiedInviteMembershipId(null), 1500);
                } catch (e) {
                  toast.showError(getUserFacingError(e, tErrors, t('errorClearPassword')));
                } finally {
                  setClearingMembershipId(null);
                }
              }}
            >
              {copiedInviteMembershipId === lastPasswordSetupInfo.membershipId
                ? tCommon('copied')
                : tCommon('copyLink')}
            </Button>
            <p className="text-xs text-text-muted">{t('passwordSetupShareHint')}</p>
          </div>
        </div>
      )}

      {loading ? (
        <p className="text-sm text-text-secondary">{t('loadingTeam')}</p>
      ) : (
        <>
          <StaffMembersMobileList
            members={members}
            canEdit={canEdit}
            organizationType={currentOrganization?.type}
            highlightMembershipIds={highlightMembershipIds}
            copiedInviteMembershipId={copiedInviteMembershipId}
            copyingInviteMembershipId={copyingInviteMembershipId}
            enablingMembershipId={enablingMembershipId}
            disablingMembershipId={disablingMembershipId}
            formatAccessSummary={(member) =>
              formatAccessSummary(member.permissions, currentOrganization?.type, tFeatures)
            }
            canShareInviteLink={canShareStaffInviteLink}
            canEnable={canEnableStaff}
            canDisable={canDisableStaff}
            onCopyInviteLink={(member) => copyStaffInviteLink(member)}
            onEnable={setEnableTarget}
            onDisable={setDisableTarget}
            onEdit={openEdit}
            onDelete={() => handleDeleteMember()}
            labels={{
              roleOwner: t('roleOwner'),
              roleStaff: t('roleStaff'),
              statusActive: t('statusActive'),
              statusPending: t('statusPending'),
              statusDisabled: t('statusDisabled'),
              statusExpired: t('statusExpired'),
              allFeatures: t('allFeatures'),
              copyInviteLink: t('copyInviteLinkTitle'),
              enableMemberTitle: t('enableMemberTitle'),
              disableMemberTitle: t('disableMemberTitle'),
              editMemberAria: t('editMemberAria'),
              deleteMemberAria: t('deleteMemberAria'),
            }}
          />
          <div className="hidden lg:block">
        <Table
          headers={
            <tr>
              <th className="text-xs font-medium text-text-muted uppercase tracking-wider">{t('tableName')}</th>
              <th className="text-xs font-medium text-text-muted uppercase tracking-wider">{t('tableEmail')}</th>
              <th className="text-xs font-medium text-text-muted uppercase tracking-wider">{t('tableRole')}</th>
              <th className="text-center text-xs font-medium text-text-muted uppercase tracking-wider">{t('tableStatus')}</th>
              <th className="text-xs font-medium text-text-muted uppercase tracking-wider">{t('tableAccess')}</th>
              <th className="text-center text-xs font-medium text-text-muted uppercase tracking-wider w-36">
                {t('tableAction')}
              </th>
            </tr>
          }
          body={
            <>
              {members.map((m) => {
                const highlighted = highlightMembershipIds.has(m.id);
                return (
                <tr
                  key={m.id}
                  id={`staff-row-${m.id}`}
                  className={[
                    'hover:bg-background-secondary/45',
                    highlighted ? STAFF_ROW_HIGHLIGHT_CLASS : undefined,
                  ]
                    .filter(Boolean)
                    .join(' ')}
                >
                  <td className="text-sm text-text-primary">{m.name}</td>
                  <td className="text-sm text-text-secondary">{m.email}</td>
                  <td className="text-sm">
                    {m.isOwner ? (
                      <span className="text-primary font-medium">{t('roleOwner')}</span>
                    ) : (
                      <span className="text-text-secondary">{t('roleStaff')}</span>
                    )}
                  </td>
                  <td className="align-middle text-center">
                    {m.isOwner || m.invitationStatus === 'ACTIVE' ? (
                      <Badge variant="success">{t('statusActive')}</Badge>
                    ) : m.invitationStatus === 'PENDING' ? (
                      <Badge variant="warning">{t('statusPending')}</Badge>
                    ) : m.invitationStatus === 'DISABLED' ? (
                      <Badge variant="default">{t('statusDisabled')}</Badge>
                    ) : (
                      <Badge variant="danger">{t('statusExpired')}</Badge>
                    )}
                  </td>
                  <td className="text-sm text-text-secondary max-w-md">
                    {m.isOwner ? (
                      <span className="text-text-muted">{t('allFeatures')}</span>
                    ) : (
                      <span className="line-clamp-3 text-sm leading-relaxed">
                        {formatAccessSummary(m.permissions, currentOrganization?.type, tFeatures)}
                      </span>
                    )}
                  </td>
                  <td className="align-middle text-center">
                    {!m.isOwner && (
                      <div className="flex min-h-[36px] items-center justify-center gap-1 mx-auto w-fit">
                        {canShareStaffInviteLink(m) && (
                          <button
                            type="button"
                            className="p-2 rounded-md text-text-secondary hover:bg-background-card/80 hover:text-text-primary disabled:opacity-50"
                            disabled={copyingInviteMembershipId === m.id}
                            onClick={() => copyStaffInviteLink(m)}
                            aria-label={t('copyInviteLink')}
                            title={t('copyInviteLinkTitle')}
                          >
                            {copiedInviteMembershipId === m.id ? (
                              <Check className="w-4 h-4" />
                            ) : (
                              <Copy className="w-4 h-4" />
                            )}
                          </button>
                        )}
                        {canEnableStaff(m) && (
                          <button
                            type="button"
                            className={`p-2 rounded-md ${
                              canEdit
                                ? 'text-text-secondary hover:bg-background-card/80 hover:text-primary'
                                : 'text-text-muted opacity-50 cursor-not-allowed'
                            }`}
                            aria-label={t('enableMemberAria')}
                            disabled={!canEdit || enablingMembershipId === m.id}
                            title={t('enableMemberTitle')}
                            onClick={() => {
                              if (!canEdit) return;
                              setEnableTarget(m);
                            }}
                          >
                            <UserCheck className="w-4 h-4" />
                          </button>
                        )}
                        {canDisableStaff(m) && (
                          <button
                            type="button"
                            className={`p-2 rounded-md ${
                              canEdit
                                ? 'text-text-secondary hover:bg-background-card/80 hover:text-amber-600'
                                : 'text-text-muted opacity-50 cursor-not-allowed'
                            }`}
                            aria-label={t('disableMemberAria')}
                            disabled={!canEdit || disablingMembershipId === m.id}
                            title={t('disableMemberTitle')}
                            onClick={() => {
                              if (!canEdit) return;
                              setDisableTarget(m);
                            }}
                          >
                            <UserX className="w-4 h-4" />
                          </button>
                        )}
                        <button
                          type="button"
                          className={`p-2 rounded-md ${
                            canEdit
                              ? 'text-text-secondary hover:bg-background-card/80 hover:text-text-primary'
                              : 'text-text-muted opacity-50 cursor-not-allowed'
                          }`}
                          aria-label={t('editMemberAria')}
                          disabled={!canEdit}
                          onClick={() => {
                            if (!canEdit) return;
                            openEdit(m);
                          }}
                        >
                          <Pencil className="w-4 h-4" />
                        </button>
                        <button
                          type="button"
                          className={`p-2 rounded-md ${
                            canEdit
                              ? 'text-text-secondary hover:bg-red-500/15 hover:text-red-600'
                              : 'text-text-muted opacity-50 cursor-not-allowed'
                          }`}
                          aria-label={t('deleteMemberAria')}
                          disabled={!canEdit}
                          title={t('deleteMemberTitle')}
                          onClick={() => {
                            if (!canEdit) return;
                            handleDeleteMember();
                          }}
                        >
                          <Trash2 className="w-4 h-4" />
                        </button>
                      </div>
                    )}
                  </td>
                </tr>
                );
              })}
            </>
          }
        />
          </div>
        </>
      )}

      {inviteOpen && (
        <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-0 sm:p-4 bg-black/50">
          <div
            className="w-full sm:max-w-lg max-h-[90dvh] overflow-y-auto rounded-t-[var(--radius-lg)] sm:rounded-[var(--radius-md)] border border-border bg-background-secondary p-4 sm:p-6 shadow-xl space-y-4"
            role="dialog"
            aria-modal="true"
            aria-labelledby="invite-staff-title"
          >
            <div className="flex items-start justify-between gap-3">
              <div>
                <h2 id="invite-staff-title" className="text-lg font-semibold text-text-primary pr-2">
                  {t('inviteModalTitle')}
                </h2>
                {inviteHasTreatmentEdit && (
                  <p className="text-xs text-text-muted mt-1">{t('stepOf', { step: inviteStep })}</p>
                )}
              </div>
              <DialogCloseButton
                onClick={() => {
                  setInviteOpen(false);
                  resetInviteForm();
                }}
              />
            </div>

            {inviteStep === 1 ? (
              <>
                <Input
                  label={t('labelEmail')}
                  type="email"
                  value={inviteEmail}
                  onChange={(e) => setInviteEmail(e.target.value)}
                  autoComplete="off"
                />
                <Input
                  label={t('labelDisplayName')}
                  value={inviteName}
                  onChange={(e) => setInviteName(e.target.value)}
                />
                <div>
                  <p className="text-sm font-medium text-text-secondary mb-2">{t('tabAccess')}</p>
                  <PermissionGrid
                    state={invitePerms}
                    onChange={setInvitePerms}
                    organizationType={currentOrganization?.type}
                  />
                </div>
              </>
            ) : (
              <StaffWorkingHoursStep
                days={inviteWorkingHoursDays}
                autoRepeatWeekly={inviteAutoRepeatWeekly}
                onDaysChange={setInviteWorkingHoursDays}
                onAutoRepeatWeeklyChange={setInviteAutoRepeatWeekly}
                onValidationChange={setInviteHoursValidationError}
                disabled={inviteLoading}
              />
            )}

            <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-2">
              <Button
                variant="outline"
                type="button"
                onClick={() => {
                  if (inviteStep === 2) {
                    setInviteStep(1);
                    return;
                  }
                  setInviteOpen(false);
                  resetInviteForm();
                }}
              >
                {inviteStep === 2 ? tCommon('back') : tCommon('cancel')}
              </Button>
              {inviteStep === 1 ? (
                inviteHasTreatmentEdit ? (
                  <Button
                    type="button"
                    disabled={!inviteEmail.trim() || !inviteName.trim()}
                    onClick={() => setInviteStep(2)}
                  >
                    {tCommon('next')}
                  </Button>
                ) : (
                  <Button
                    type="button"
                    isLoading={inviteLoading}
                    disabled={!inviteEmail.trim() || !inviteName.trim()}
                    onClick={() => submitInvite(false)}
                  >
                    {t('sendInvite')}
                  </Button>
                )
              ) : (
                <>
                  <Button
                    type="button"
                    variant="outline"
                    isLoading={inviteLoading}
                    onClick={() => submitInvite(false)}
                  >
                    {t('skipForNow')}
                  </Button>
                  <Button
                    type="button"
                    isLoading={inviteLoading}
                    disabled={Boolean(inviteHoursValidationError)}
                    onClick={() => submitInvite(true)}
                  >
                    {t('sendInvite')}
                  </Button>
                </>
              )}
            </div>
          </div>
        </div>
      )}

      {enableTarget && (
        <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-0 sm:p-4 bg-black/55">
          <div
            className="surface-card w-full sm:max-w-md max-h-[90dvh] overflow-y-auto p-4 sm:p-5 space-y-4 shadow-xl rounded-t-[var(--radius-lg)] sm:rounded-[var(--radius-lg)]"
            role="dialog"
            aria-modal="true"
            aria-labelledby="enable-staff-title"
          >
            <div className="flex items-start justify-between gap-2">
              <h2 id="enable-staff-title" className="text-lg font-semibold text-text-primary pr-2">
                {t('enableModalTitle')}
              </h2>
              <DialogCloseButton
                onClick={() => {
                  if (enablingMembershipId) return;
                  setEnableTarget(null);
                }}
              />
            </div>
            <p className="text-sm text-text-secondary">
              {t('enableConfirm', { name: enableTarget.name, email: enableTarget.email })}
            </p>
            <ul className="text-sm text-text-secondary space-y-2 list-disc pl-5">
              <li>{t('enableBullet1')}</li>
              <li>{t('enableBullet2')}</li>
              <li>{t('enableBullet3')}</li>
            </ul>
            {!hasAvailableSeat && (
              <p className="text-sm text-amber-600 dark:text-amber-400">{t('noSeatsAvailable')}</p>
            )}
            <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-1">
              <Button
                type="button"
                variant="outline"
                disabled={Boolean(enablingMembershipId)}
                onClick={() => setEnableTarget(null)}
              >
                {tCommon('cancel')}
              </Button>
              <Button
                type="button"
                variant="primary"
                isLoading={enablingMembershipId === enableTarget.id}
                disabled={Boolean(enablingMembershipId) || !hasAvailableSeat}
                onClick={() => confirmEnableMember()}
              >
                {t('enableMemberButton')}
              </Button>
            </div>
          </div>
        </div>
      )}

      {disableTarget && (
        <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-0 sm:p-4 bg-black/55">
          <div
            className="surface-card w-full sm:max-w-md max-h-[90dvh] overflow-y-auto p-4 sm:p-5 space-y-4 shadow-xl rounded-t-[var(--radius-lg)] sm:rounded-[var(--radius-lg)]"
            role="dialog"
            aria-modal="true"
            aria-labelledby="disable-staff-title"
          >
            <div className="flex items-start justify-between gap-2">
              <h2 id="disable-staff-title" className="text-lg font-semibold text-text-primary pr-2">
                {t('disableModalTitle')}
              </h2>
              <DialogCloseButton
                onClick={() => {
                  if (disablingMembershipId) return;
                  setDisableTarget(null);
                }}
              />
            </div>
            <p className="text-sm text-text-secondary">
              {t('disableConfirm', { name: disableTarget.name, email: disableTarget.email })}
            </p>
            <ul className="text-sm text-text-secondary space-y-2 list-disc pl-5">
              <li>{t('disableBullet1')}</li>
              <li>{t('disableBullet2')}</li>
              <li>{t('disableBullet3')}</li>
            </ul>
            <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-1">
              <Button
                type="button"
                variant="outline"
                disabled={Boolean(disablingMembershipId)}
                onClick={() => setDisableTarget(null)}
              >
                {tCommon('cancel')}
              </Button>
              <Button
                type="button"
                variant="danger"
                isLoading={disablingMembershipId === disableTarget.id}
                disabled={Boolean(disablingMembershipId)}
                onClick={() => confirmDisableMember()}
              >
                {t('disableMemberButton')}
              </Button>
            </div>
          </div>
        </div>
      )}

      {clearPasswordTarget && (
        <div className="fixed inset-0 z-[60] flex items-end sm:items-center justify-center p-0 sm:p-4 bg-black/55">
          <div
            className="surface-card w-full sm:max-w-md max-h-[90dvh] overflow-y-auto p-4 sm:p-5 space-y-4 shadow-xl rounded-t-[var(--radius-lg)] sm:rounded-[var(--radius-lg)]"
            role="dialog"
            aria-modal="true"
            aria-labelledby="clear-password-title"
          >
            <div className="flex items-start justify-between gap-2">
              <h2 id="clear-password-title" className="text-lg font-semibold text-text-primary pr-2">
                {t('removePasswordModalTitle')}
              </h2>
              <DialogCloseButton
                onClick={() => {
                  if (clearingMembershipId) return;
                  setClearPasswordTarget(null);
                }}
              />
            </div>
            <p className="text-sm text-text-secondary">
              {t('removePasswordConfirm', {
                name: clearPasswordTarget.name,
                email: clearPasswordTarget.email,
              })}
            </p>
            <ul className="text-sm text-text-secondary space-y-2 list-disc ps-5">
              <li>{t('removePasswordBullet1')}</li>
              <li>{t('removePasswordBullet2')}</li>
              <li>{t('removePasswordBullet3')}</li>
            </ul>
            <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-1">
              <Button
                type="button"
                variant="outline"
                disabled={Boolean(clearingMembershipId)}
                onClick={() => setClearPasswordTarget(null)}
              >
                {tCommon('cancel')}
              </Button>
              <Button
                type="button"
                variant="danger"
                isLoading={clearingMembershipId === clearPasswordTarget.id}
                disabled={Boolean(clearingMembershipId)}
                onClick={() => confirmClearPassword()}
              >
                {t('removePasswordButton')}
              </Button>
            </div>
          </div>
        </div>
      )}

      {editing && (
        <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-0 sm:p-4 bg-black/50">
          <div
            className="w-full sm:max-w-lg max-h-[90dvh] overflow-y-auto rounded-t-[var(--radius-lg)] sm:rounded-[var(--radius-md)] border border-border bg-background-secondary p-4 sm:p-6 shadow-xl space-y-4"
            role="dialog"
            aria-modal="true"
          >
            <div className="flex items-start justify-between gap-3">
              <div>
                <h2 className="text-lg font-semibold text-text-primary pr-2">{t('editModalTitle')}</h2>
                {editHasTreatmentEdit && (
                  <p className="text-xs text-text-muted mt-1">{t('stepOf', { step: editStep })}</p>
                )}
              </div>
              <DialogCloseButton
                onClick={() => {
                  setEditing(null);
                  setEditStep(1);
                }}
              />
            </div>
            <p className="text-xs text-text-muted">{editing.email}</p>

            {editStep === 1 ? (
              <>
                <Input
                  label={t('labelDisplayName')}
                  value={editName}
                  onChange={(e) => setEditName(e.target.value)}
                />
                <div>
                  <p className="text-sm font-medium text-text-secondary mb-2">{t('tabAccess')}</p>
                  <PermissionGrid
                    state={editPerms}
                    onChange={setEditPerms}
                    organizationType={currentOrganization?.type}
                  />
                </div>
                {canEdit && canIssuePasswordSetup(editing, user?.id) && (
                  <div className="pt-3 border-t border-border/60">
                    {editing.hasPassword ? (
                      <Button
                        type="button"
                        variant="danger"
                        size="sm"
                        disabled={Boolean(clearingMembershipId)}
                        onClick={() => setClearPasswordTarget(editing)}
                      >
                        {t('removePassword')}
                      </Button>
                    ) : (
                      <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        isLoading={clearingMembershipId === editing.id}
                        onClick={() => void issuePasswordSetupLink(editing, true)}
                      >
                        {t('copyPasswordSetupLink')}
                      </Button>
                    )}
                  </div>
                )}
              </>
            ) : editLoadingWorkingHours ? (
              <p className="text-sm text-text-secondary">{t('loadingWorkingHours')}</p>
            ) : (
              <StaffWorkingHoursStep
                days={editWorkingHoursDays}
                autoRepeatWeekly={editAutoRepeatWeekly}
                onDaysChange={setEditWorkingHoursDays}
                onAutoRepeatWeeklyChange={setEditAutoRepeatWeekly}
                onValidationChange={setEditHoursValidationError}
                disabled={editLoading}
              />
            )}

            <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2 pt-2">
              <Button
                variant="outline"
                type="button"
                onClick={() => {
                  if (editStep === 2) {
                    setEditStep(1);
                    return;
                  }
                  setEditing(null);
                  setEditStep(1);
                }}
              >
                {editStep === 2 ? tCommon('back') : tCommon('cancel')}
              </Button>
              {editStep === 1 ? (
                editHasTreatmentEdit ? (
                  <Button type="button" onClick={() => setEditStep(2)}>
                    {tCommon('next')}
                  </Button>
                ) : (
                  <Button type="button" isLoading={editLoading} onClick={() => submitEdit()}>
                    {tCommon('save')}
                  </Button>
                )
              ) : (
                <Button
                  type="button"
                  isLoading={editLoading}
                  disabled={Boolean(editHoursValidationError)}
                  onClick={() => submitEdit()}
                >
                  {tCommon('save')}
                </Button>
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
