import React, { useState, useEffect, useMemo } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import {
  MagnifyingGlassIcon, PlusIcon, EllipsisVerticalIcon,
  EyeIcon, PencilIcon, TrashIcon, ArrowPathIcon,
  UserGroupIcon, CheckCircleIcon, XCircleIcon,
  ShieldCheckIcon, HeartIcon, UserIcon, FunnelIcon,
} from '@heroicons/react/24/outline';
import { toast } from 'sonner';
import { api } from '../lib/api';
import type { ApiResponse, PaginatedResponse } from '../lib/api';
import { formatDate, formatNumber, maskMobile } from '../lib/utils';
import ConfirmDialog from '../components/ui/ConfirmDialog';
import Pagination from '../components/ui/Pagination';

// ── Types ─────────────────────────────────────────────────────────────────

interface AdminUser {
  uuid: string;
  id: number;
  mobile_number: string;
  name: string | null;
  email: string | null;
  roles: string[];
  is_active: boolean;
  status: number;
  created_at: string;
}

interface UserStats {
  total: number;
  active: number;
  inactive: number;
  admins: number;
  doctors: number;
  patients: number;
}

// ── Role helpers ──────────────────────────────────────────────────────────

const ROLE_META: Record<string, { label: string; cls: string; dot: string }> = {
  admin:     { label: 'ادمین',  cls: 'bg-violet-100 dark:bg-violet-400/10 text-violet-700 dark:text-violet-300',    dot: '#8b5cf6' },
  doctor:    { label: 'پزشک',   cls: 'bg-blue-100 dark:bg-blue-400/10 text-blue-700 dark:text-blue-300',            dot: '#3b82f6' },
  secretary: { label: 'منشی',   cls: 'bg-orange-100 dark:bg-orange-400/10 text-orange-700 dark:text-orange-300',    dot: '#f97316' },
  clinic:    { label: 'کلینیک', cls: 'bg-emerald-100 dark:bg-emerald-400/10 text-emerald-700 dark:text-emerald-300', dot: '#10b981' },
  patient:   { label: 'بیمار',  cls: 'bg-slate-100 dark:bg-slate-400/10 text-slate-600 dark:text-slate-400',        dot: '#94a3b8' },
};

function getPrimaryRole(roles: string[]): string {
  if (roles.includes('ROLE_ADMIN'))     return 'admin';
  if (roles.includes('ROLE_DOCTOR'))    return 'doctor';
  if (roles.includes('ROLE_SECRETARY')) return 'secretary';
  if (roles.includes('ROLE_CLINIC'))    return 'clinic';
  return 'patient';
}

// ── Sub-components ────────────────────────────────────────────────────────

const AVATAR_COLORS = [
  'bg-violet-100 text-violet-700 dark:bg-violet-400/20 dark:text-violet-300',
  'bg-blue-100 text-blue-700 dark:bg-blue-400/20 dark:text-blue-300',
  'bg-emerald-100 text-emerald-700 dark:bg-emerald-400/20 dark:text-emerald-300',
  'bg-pink-100 text-pink-700 dark:bg-pink-400/20 dark:text-pink-300',
  'bg-amber-100 text-amber-700 dark:bg-amber-400/20 dark:text-amber-300',
];

function Avatar({ name, id }: { name: string | null; id: number }) {
  const initials = name
    ? name.split(' ').filter(Boolean).map(w => w[0]).join('').toUpperCase().slice(0, 2)
    : '؟';
  return (
    <div className={`w-8 h-8 rounded-full ${AVATAR_COLORS[id % AVATAR_COLORS.length]} flex items-center justify-center text-xs font-bold shrink-0`}>
      {initials}
    </div>
  );
}

function RoleBadge({ roles }: { roles: string[] }) {
  const key  = getPrimaryRole(roles);
  const meta = ROLE_META[key];
  return (
    <span className={`inline-flex items-center gap-1 text-[11px] font-medium px-2 py-0.5 rounded-full ${meta.cls}`}>
      <span className="w-1.5 h-1.5 rounded-full shrink-0" style={{ backgroundColor: meta.dot }} />
      {meta.label}
    </span>
  );
}

function ActiveBadge({ active }: { active: boolean }) {
  return active ? (
    <span className="inline-flex items-center gap-1 text-[11px] font-medium px-2 py-0.5 rounded-full bg-green-100 dark:bg-green-400/10 text-green-700 dark:text-green-300">
      <span className="w-1.5 h-1.5 rounded-full bg-green-500 shrink-0" />
      فعال
    </span>
  ) : (
    <span className="inline-flex items-center gap-1 text-[11px] font-medium px-2 py-0.5 rounded-full bg-slate-100 dark:bg-slate-400/10 text-slate-500 dark:text-slate-400">
      <span className="w-1.5 h-1.5 rounded-full bg-slate-400 shrink-0" />
      غیرفعال
    </span>
  );
}

function highlight(text: string | null | undefined, query: string): React.ReactNode {
  if (!text || !query.trim()) return text ?? '—';
  const idx = text.toLowerCase().indexOf(query.toLowerCase());
  if (idx === -1) return text;
  return (
    <>
      {text.slice(0, idx)}
      <mark className="bg-yellow-100 dark:bg-yellow-400/20 text-yellow-800 dark:text-yellow-200 rounded px-0.5 not-italic">
        {text.slice(idx, idx + query.length)}
      </mark>
      {text.slice(idx + query.length)}
    </>
  );
}

// ── KPI Card ──────────────────────────────────────────────────────────────

function KpiCard({ label, value, icon: Icon, iconBg, iconColor }: {
  label: string; value: number | undefined;
  icon: React.ElementType; iconBg: string; iconColor: string;
}) {
  return (
    <div className="cp-card p-4 flex items-center gap-3">
      <div className={`cp-stat-icon ${iconBg} shrink-0`}>
        <Icon className={`w-5 h-5 ${iconColor}`} />
      </div>
      <div className="min-w-0 flex-1">
        <p className="text-xs text-slate-500 dark:text-slate-400 mb-0.5 truncate">{label}</p>
        {value === undefined
          ? <div className="h-5 w-16 rounded skeleton" />
          : <p className="text-lg font-bold text-slate-900 dark:text-slate-50 leading-none">{formatNumber(value)}</p>
        }
      </div>
    </div>
  );
}

// ── Role Change Modal ─────────────────────────────────────────────────────

function ChangeRoleModal({ user, onClose, onSave, loading }: {
  user: AdminUser; onClose: () => void;
  onSave: (role: string) => void; loading: boolean;
}) {
  const [selected, setSelected] = useState(getPrimaryRole(user.roles));
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-sm animate-fade-in">
      <div className="cp-card w-full max-w-sm p-6 animate-scale-in shadow-2xl">
        <h3 className="text-base font-bold text-slate-900 dark:text-slate-50 mb-1">تغییر نقش</h3>
        <p className="text-sm text-slate-500 dark:text-slate-400 mb-5">{user.name || user.mobile_number}</p>
        <div className="space-y-2 mb-6">
          {Object.entries(ROLE_META).map(([key, meta]) => (
            <label
              key={key}
              className={`flex items-center gap-3 p-3 rounded-xl cursor-pointer border-2 transition-all ${
                selected === key
                  ? 'border-primary-500 bg-primary-50 dark:bg-primary-500/10'
                  : 'border-transparent hover:bg-slate-50 dark:hover:bg-gray-800 border border-slate-200 dark:border-gray-700'
              }`}
            >
              <input type="radio" name="role" value={key} checked={selected === key}
                onChange={() => setSelected(key)} className="sr-only" />
              <span className="w-2.5 h-2.5 rounded-full shrink-0" style={{ backgroundColor: meta.dot }} />
              <span className="text-sm font-medium text-slate-800 dark:text-slate-200 flex-1">{meta.label}</span>
              {selected === key && <CheckCircleIcon className="w-4 h-4 text-primary-600 dark:text-primary-400" />}
            </label>
          ))}
        </div>
        <div className="flex gap-2">
          <button onClick={() => onSave(selected)} disabled={loading} className="cp-btn-primary flex-1">
            {loading ? 'در حال ذخیره...' : 'ذخیره'}
          </button>
          <button onClick={onClose} disabled={loading} className="cp-btn-secondary px-5">لغو</button>
        </div>
      </div>
    </div>
  );
}

// ── Constants ─────────────────────────────────────────────────────────────

const ROLE_TABS = [
  { key: '',          label: 'همه',    dot: '' },
  { key: 'admin',     label: 'ادمین',  dot: '#8b5cf6' },
  { key: 'doctor',    label: 'پزشک',   dot: '#3b82f6' },
  { key: 'secretary', label: 'منشی',   dot: '#f97316' },
  { key: 'clinic',    label: 'کلینیک', dot: '#10b981' },
  { key: 'patient',   label: 'بیمار',  dot: '#94a3b8' },
];

const LIMIT_OPTIONS = [10, 25, 50, 100];

// ── Main Page ─────────────────────────────────────────────────────────────

export default function UsersPage() {
  const navigate = useNavigate();
  const qc = useQueryClient();

  const [page, setPage]               = useState(1);
  const [limit, setLimit]             = useState(25);
  const [searchInput, setSearchInput] = useState('');
  const [search, setSearch]           = useState('');
  const [role, setRole]               = useState('');
  const [status, setStatus]           = useState('');
  const [sort, setSort]               = useState('newest');
  const [selected, setSelected]       = useState<string[]>([]);
  const [activeMenu, setActiveMenu]   = useState<string | null>(null);
  const [deleteTarget, setDeleteTarget]       = useState<AdminUser | null>(null);
  const [roleTarget, setRoleTarget]           = useState<AdminUser | null>(null);
  const [confirmBulkDel, setConfirmBulkDel]   = useState(false);
  const [bulkDeleting, setBulkDeleting]       = useState(false);

  // Debounce search
  useEffect(() => {
    const t = setTimeout(() => { setSearch(searchInput); setPage(1); }, 350);
    return () => clearTimeout(t);
  }, [searchInput]);

  // Reset page + selection when filters change
  useEffect(() => { setPage(1); setSelected([]); }, [role, status, sort, limit]);

  // Close action dropdown on outside click
  useEffect(() => {
    if (!activeMenu) return;
    const close = (e: MouseEvent) => {
      if ((e.target as HTMLElement).closest('[data-menu]') === null) setActiveMenu(null);
    };
    document.addEventListener('mousedown', close);
    return () => document.removeEventListener('mousedown', close);
  }, [activeMenu]);

  // ── Queries ──

  const statsQ = useQuery({
    queryKey: ['users-stats'],
    queryFn: () => api.get<ApiResponse<UserStats>>('/api/v1/admin/users/stats'),
    staleTime: 30_000,
  });

  const usersQ = useQuery({
    queryKey: ['users', page, limit, search, role, status, sort],
    queryFn: () => {
      const p = new URLSearchParams({ page: String(page), limit: String(limit), sort });
      if (search) p.set('search', search);
      if (role)   p.set('role', role);
      if (status) p.set('status', status);
      return api.get<PaginatedResponse<AdminUser>>(`/api/v1/admin/users?${p}`);
    },
  });

  const stats = useMemo<UserStats | undefined>(
    () => (statsQ.data?.data as any)?.data ?? statsQ.data?.data, [statsQ.data]
  );
  const items = usersQ.data?.data ?? [];
  const total = usersQ.data?.meta?.totalRecords ?? 0;

  // ── Mutations ──

  const deleteMut = useMutation({
    mutationFn: (uuid: string) => api.delete<ApiResponse<null>>(`/api/v1/admin/users/${uuid}`),
    onSuccess: () => {
      toast.success('کاربر حذف شد');
      setDeleteTarget(null);
      qc.invalidateQueries({ queryKey: ['users'] });
      qc.invalidateQueries({ queryKey: ['users-stats'] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const toggleStatusMut = useMutation({
    mutationFn: (uuid: string) => api.post<ApiResponse<{ is_active: boolean }>>(`/api/v1/admin/users/${uuid}/status`, {}),
    onSuccess: () => {
      toast.success('وضعیت کاربر تغییر کرد');
      qc.invalidateQueries({ queryKey: ['users'] });
      qc.invalidateQueries({ queryKey: ['users-stats'] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const updateRoleMut = useMutation({
    mutationFn: ({ uuid, role: r }: { uuid: string; role: string }) =>
      api.put<ApiResponse<null>>(`/api/v1/admin/users/${uuid}/role`, { role: r }),
    onSuccess: () => {
      toast.success('نقش کاربر بروزرسانی شد');
      setRoleTarget(null);
      qc.invalidateQueries({ queryKey: ['users'] });
      qc.invalidateQueries({ queryKey: ['users-stats'] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  // ── Bulk actions ──

  const allSelected = items.length > 0 && items.every(u => selected.includes(u.uuid));
  const toggleAll   = () => setSelected(allSelected ? [] : items.map(u => u.uuid));
  const toggleOne   = (uuid: string) =>
    setSelected(prev => prev.includes(uuid) ? prev.filter(id => id !== uuid) : [...prev, uuid]);

  const handleBulkDelete = async () => {
    setBulkDeleting(true);
    let count = 0;
    for (const uuid of selected) {
      try { await api.delete(`/api/v1/admin/users/${uuid}`); count++; } catch {}
    }
    setBulkDeleting(false);
    setConfirmBulkDel(false);
    setSelected([]);
    toast.success(`${formatNumber(count)} کاربر حذف شد`);
    qc.invalidateQueries({ queryKey: ['users'] });
    qc.invalidateQueries({ queryKey: ['users-stats'] });
  };

  // ── KPI cards ──

  const kpiCards = [
    { label: 'کل کاربران', value: stats?.total,    icon: UserGroupIcon,   iconBg: 'bg-slate-100 dark:bg-slate-400/10',   iconColor: 'text-slate-600 dark:text-slate-400' },
    { label: 'فعال',       value: stats?.active,   icon: CheckCircleIcon, iconBg: 'bg-green-100 dark:bg-green-400/10',   iconColor: 'text-green-600 dark:text-green-400' },
    { label: 'غیرفعال',    value: stats?.inactive, icon: XCircleIcon,     iconBg: 'bg-slate-100 dark:bg-slate-400/10',   iconColor: 'text-slate-500 dark:text-slate-400' },
    { label: 'ادمین‌ها',   value: stats?.admins,   icon: ShieldCheckIcon, iconBg: 'bg-violet-100 dark:bg-violet-400/10', iconColor: 'text-violet-600 dark:text-violet-400' },
    { label: 'پزشکان',     value: stats?.doctors,  icon: HeartIcon,       iconBg: 'bg-blue-100 dark:bg-blue-400/10',     iconColor: 'text-blue-600 dark:text-blue-400' },
    { label: 'بیماران',    value: stats?.patients, icon: UserIcon,        iconBg: 'bg-orange-100 dark:bg-orange-400/10', iconColor: 'text-orange-600 dark:text-orange-400' },
  ];

  const hasFilters = !!(search || role || status);

  return (
    <div className="animate-slide-up space-y-5">

      {/* ── Header ─────────────────────────────────────────────── */}
      <div className="flex items-start justify-between gap-4">
        <div>
          <h1 className="text-xl font-bold text-slate-900 dark:text-slate-50">کاربران</h1>
          <p className="text-sm text-slate-500 dark:text-slate-400 mt-0.5">مدیریت کاربران، نقش‌ها و سطح دسترسی سیستم</p>
        </div>
        <button className="cp-btn-primary shrink-0">
          <PlusIcon className="w-4 h-4" />
          افزودن کاربر
        </button>
      </div>

      {/* ── KPI Cards ──────────────────────────────────────────── */}
      <div className="grid grid-cols-2 sm:grid-cols-3 xl:grid-cols-6 gap-3">
        {kpiCards.map((c) => <KpiCard key={c.label} {...c} />)}
      </div>

      {/* ── Main Card ──────────────────────────────────────────── */}
      <div className="cp-card overflow-hidden">

        {/* Toolbar */}
        <div className="p-4 border-b border-slate-200 dark:border-gray-700/50 space-y-3">

          {/* Row 1: Search + Status + Sort + Limit + Refresh */}
          <div className="flex items-center gap-2 flex-wrap">
            <div className="relative flex-1 min-w-52">
              <MagnifyingGlassIcon className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400 pointer-events-none" />
              <input
                type="text"
                value={searchInput}
                onChange={(e) => setSearchInput(e.target.value)}
                placeholder="نام، موبایل یا ایمیل..."
                className="cp-input pr-9"
              />
              {searchInput && (
                <button
                  onClick={() => { setSearchInput(''); setSearch(''); }}
                  className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600 dark:hover:text-slate-300 text-lg leading-none"
                >×</button>
              )}
            </div>

            <select value={status} onChange={(e) => setStatus(e.target.value)} className="cp-select h-10 w-auto min-w-36 text-sm">
              <option value="">همه وضعیت‌ها</option>
              <option value="1">فعال</option>
              <option value="0">غیرفعال</option>
            </select>

            <select value={sort} onChange={(e) => setSort(e.target.value)} className="cp-select h-10 w-auto min-w-32 text-sm">
              <option value="newest">جدیدترین</option>
              <option value="oldest">قدیمی‌ترین</option>
            </select>

            <select value={limit} onChange={(e) => setLimit(Number(e.target.value))} className="cp-select h-10 w-auto min-w-24 text-sm">
              {LIMIT_OPTIONS.map(l => <option key={l} value={l}>{formatNumber(l)} عدد</option>)}
            </select>

            <button
              onClick={() => usersQ.refetch()}
              disabled={usersQ.isFetching}
              className="cp-btn-secondary h-10 px-3"
              title="به‌روزرسانی"
            >
              <ArrowPathIcon className={`w-4 h-4 ${usersQ.isFetching ? 'animate-spin' : ''}`} />
            </button>
          </div>

          {/* Row 2: Role filter pills */}
          <div className="flex items-center gap-1.5 flex-wrap">
            <span className="flex items-center gap-1 text-xs text-slate-500 dark:text-slate-400 shrink-0">
              <FunnelIcon className="w-3.5 h-3.5" />نقش:
            </span>
            {ROLE_TABS.map((t) => (
              <button
                key={t.key}
                onClick={() => setRole(t.key)}
                className={`inline-flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-lg border transition-all ${
                  role === t.key
                    ? 'bg-primary-600 border-primary-600 text-white shadow-sm'
                    : 'bg-transparent border-slate-200 dark:border-gray-700 text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-gray-800'
                }`}
              >
                {t.dot && (
                  <span className="w-1.5 h-1.5 rounded-full shrink-0"
                    style={{ backgroundColor: role === t.key ? 'white' : t.dot }} />
                )}
                {t.label}
              </button>
            ))}
            {hasFilters && (
              <button
                onClick={() => { setSearchInput(''); setSearch(''); setRole(''); setStatus(''); }}
                className="text-xs text-red-500 dark:text-red-400 hover:underline mr-2"
              >
                پاک کردن فیلترها
              </button>
            )}
          </div>
        </div>

        {/* Bulk actions bar */}
        {selected.length > 0 && (
          <div className="px-4 py-2.5 bg-primary-50 dark:bg-primary-500/10 border-b border-primary-200 dark:border-primary-500/20 flex items-center gap-3">
            <span className="text-sm font-medium text-primary-700 dark:text-primary-300">
              {formatNumber(selected.length)} کاربر انتخاب شده
            </span>
            <div className="flex gap-2 mr-auto">
              <button
                onClick={() => setConfirmBulkDel(true)}
                className="text-xs px-3 py-1.5 rounded-lg bg-red-100 dark:bg-red-400/10 text-red-600 dark:text-red-400 hover:bg-red-200 dark:hover:bg-red-400/20 transition-colors font-medium"
              >
                حذف انتخاب‌شده‌ها
              </button>
              <button onClick={() => setSelected([])} className="text-xs px-3 py-1.5 rounded-lg text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-gray-700 transition-colors">
                لغو انتخاب
              </button>
            </div>
          </div>
        )}

        {/* Table */}
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="bg-slate-50 dark:bg-gray-800/60 border-b border-slate-200 dark:border-gray-700/50">
                <th className="px-4 py-3 w-10">
                  <input type="checkbox" checked={allSelected} onChange={toggleAll}
                    className="rounded border-slate-300 dark:border-gray-600 text-primary-600 cursor-pointer" />
                </th>
                <th className="px-4 py-3 text-right text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide whitespace-nowrap">کاربر</th>
                <th className="px-4 py-3 text-right text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide whitespace-nowrap hidden sm:table-cell">موبایل</th>
                <th className="px-4 py-3 text-right text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide whitespace-nowrap hidden md:table-cell">ایمیل</th>
                <th className="px-4 py-3 text-right text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide whitespace-nowrap">نقش</th>
                <th className="px-4 py-3 text-right text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide whitespace-nowrap hidden sm:table-cell">وضعیت</th>
                <th className="px-4 py-3 text-right text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide whitespace-nowrap hidden lg:table-cell">عضویت</th>
                <th className="px-4 py-3 w-10" />
              </tr>
            </thead>

            <tbody className="divide-y divide-slate-100 dark:divide-gray-700/40">

              {/* Loading skeleton */}
              {usersQ.isLoading && Array.from({ length: 8 }).map((_, i) => (
                <tr key={i}>
                  <td className="px-4 py-3.5"><div className="w-4 h-4 rounded skeleton" /></td>
                  <td className="px-4 py-3.5">
                    <div className="flex items-center gap-3">
                      <div className="w-8 h-8 rounded-full skeleton shrink-0" />
                      <div className="space-y-1.5 flex-1">
                        <div className="h-3.5 rounded skeleton w-28" />
                        <div className="h-3 rounded skeleton w-10" />
                      </div>
                    </div>
                  </td>
                  <td className="px-4 py-3.5 hidden sm:table-cell"><div className="h-3.5 rounded skeleton w-24" /></td>
                  <td className="px-4 py-3.5 hidden md:table-cell"><div className="h-3.5 rounded skeleton w-36" /></td>
                  <td className="px-4 py-3.5"><div className="h-5 rounded-full skeleton w-14" /></td>
                  <td className="px-4 py-3.5 hidden sm:table-cell"><div className="h-5 rounded-full skeleton w-12" /></td>
                  <td className="px-4 py-3.5 hidden lg:table-cell"><div className="h-3.5 rounded skeleton w-20" /></td>
                  <td className="px-4 py-3.5"><div className="w-6 h-6 rounded skeleton" /></td>
                </tr>
              ))}

              {/* Empty state */}
              {!usersQ.isLoading && items.length === 0 && (
                <tr>
                  <td colSpan={8} className="py-16 text-center">
                    <div className="flex flex-col items-center gap-3">
                      <div className="w-14 h-14 rounded-2xl bg-slate-100 dark:bg-gray-800 flex items-center justify-center">
                        <UserGroupIcon className="w-7 h-7 text-slate-400 dark:text-slate-500" />
                      </div>
                      <p className="text-sm text-slate-500 dark:text-slate-400">
                        {hasFilters ? 'نتیجه‌ای برای فیلترهای انتخابی یافت نشد' : 'هیچ کاربری ثبت نشده'}
                      </p>
                      {hasFilters && (
                        <button onClick={() => { setSearchInput(''); setSearch(''); setRole(''); setStatus(''); }}
                          className="text-xs text-primary-600 dark:text-primary-400 hover:underline">
                          پاک کردن فیلترها
                        </button>
                      )}
                    </div>
                  </td>
                </tr>
              )}

              {/* Data rows */}
              {!usersQ.isLoading && items.map((user) => (
                <tr
                  key={user.uuid}
                  className={`transition-colors ${
                    selected.includes(user.uuid)
                      ? 'bg-primary-50/60 dark:bg-primary-500/5'
                      : 'hover:bg-slate-50/80 dark:hover:bg-gray-800/40'
                  }`}
                >
                  {/* Checkbox */}
                  <td className="px-4 py-3.5" onClick={(e) => e.stopPropagation()}>
                    <input type="checkbox" checked={selected.includes(user.uuid)}
                      onChange={() => toggleOne(user.uuid)}
                      className="rounded border-slate-300 dark:border-gray-600 text-primary-600 cursor-pointer" />
                  </td>

                  {/* Avatar + Name */}
                  <td className="px-4 py-3.5">
                    <div className="flex items-center gap-3 cursor-pointer group" onClick={() => navigate(`/admin/users/${user.uuid}`)}>
                      <Avatar name={user.name} id={user.id} />
                      <div className="min-w-0">
                        <p className="font-medium text-slate-800 dark:text-slate-200 truncate max-w-36 group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors">
                          {highlight(user.name, search) || '—'}
                        </p>
                        <p className="text-[11px] text-slate-400 dark:text-slate-500">#{user.id}</p>
                      </div>
                    </div>
                  </td>

                  {/* Mobile */}
                  <td className="px-4 py-3.5 hidden sm:table-cell">
                    <span className="font-mono text-xs text-slate-600 dark:text-slate-400" dir="ltr">
                      {highlight(user.mobile_number, search) || maskMobile(user.mobile_number)}
                    </span>
                  </td>

                  {/* Email */}
                  <td className="px-4 py-3.5 hidden md:table-cell">
                    <span className="text-xs text-slate-500 dark:text-slate-400 truncate max-w-44 block">
                      {user.email ? highlight(user.email, search) : '—'}
                    </span>
                  </td>

                  {/* Role */}
                  <td className="px-4 py-3.5"><RoleBadge roles={user.roles} /></td>

                  {/* Status */}
                  <td className="px-4 py-3.5 hidden sm:table-cell"><ActiveBadge active={user.is_active} /></td>

                  {/* Date */}
                  <td className="px-4 py-3.5 hidden lg:table-cell text-xs text-slate-500 dark:text-slate-400 whitespace-nowrap">
                    {formatDate(user.created_at)}
                  </td>

                  {/* Actions dropdown */}
                  <td className="px-4 py-3.5" onClick={(e) => e.stopPropagation()}>
                    <div className="relative flex justify-end" data-menu>
                      <button
                        onClick={() => setActiveMenu(activeMenu === user.uuid ? null : user.uuid)}
                        className="w-7 h-7 flex items-center justify-center rounded-lg text-slate-400 hover:text-slate-600 dark:hover:text-slate-300 hover:bg-slate-100 dark:hover:bg-gray-700 transition-colors"
                        data-menu
                      >
                        <EllipsisVerticalIcon className="w-4 h-4" />
                      </button>

                      {activeMenu === user.uuid && (
                        <div className="absolute left-0 top-8 z-30 w-48 cp-card shadow-2xl border border-slate-200 dark:border-gray-700 py-1.5 animate-scale-in" data-menu>
                          <button
                            onClick={() => { navigate(`/admin/users/${user.uuid}`); setActiveMenu(null); }}
                            className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-gray-800 transition-colors"
                          >
                            <EyeIcon className="w-4 h-4 text-slate-400 shrink-0" />مشاهده پروفایل
                          </button>
                          <button
                            onClick={() => { navigate(`/admin/users/${user.uuid}?edit=1`); setActiveMenu(null); }}
                            className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-gray-800 transition-colors"
                          >
                            <PencilIcon className="w-4 h-4 text-slate-400 shrink-0" />ویرایش اطلاعات
                          </button>
                          <button
                            onClick={() => { setRoleTarget(user); setActiveMenu(null); }}
                            className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-gray-800 transition-colors"
                          >
                            <ShieldCheckIcon className="w-4 h-4 text-slate-400 shrink-0" />تغییر نقش
                          </button>
                          <button
                            onClick={() => { toggleStatusMut.mutate(user.uuid); setActiveMenu(null); }}
                            disabled={toggleStatusMut.isPending}
                            className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-gray-800 transition-colors disabled:opacity-50"
                          >
                            {user.is_active
                              ? <XCircleIcon className="w-4 h-4 text-orange-400 shrink-0" />
                              : <CheckCircleIcon className="w-4 h-4 text-green-500 shrink-0" />
                            }
                            {user.is_active ? 'غیرفعال کردن' : 'فعال‌سازی'}
                          </button>
                          <div className="border-t border-slate-100 dark:border-gray-700 my-1" />
                          <button
                            onClick={() => { setDeleteTarget(user); setActiveMenu(null); }}
                            className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-500/10 transition-colors"
                          >
                            <TrashIcon className="w-4 h-4 shrink-0" />حذف کاربر
                          </button>
                        </div>
                      )}
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        {/* Pagination */}
        <div className="px-4">
          <Pagination page={page} total={total} limit={limit} onPageChange={setPage} />
        </div>
      </div>

      {/* Delete confirm */}
      <ConfirmDialog
        open={!!deleteTarget}
        title="حذف کاربر"
        message={`آیا از حذف کاربر "${deleteTarget?.name ?? deleteTarget?.mobile_number}" اطمینان دارید؟ این عمل قابل بازگشت نیست.`}
        confirmLabel="حذف"
        danger
        loading={deleteMut.isPending}
        onConfirm={() => deleteTarget && deleteMut.mutate(deleteTarget.uuid)}
        onCancel={() => setDeleteTarget(null)}
      />

      {/* Bulk delete confirm */}
      <ConfirmDialog
        open={confirmBulkDel}
        title="حذف گروهی"
        message={`آیا از حذف ${formatNumber(selected.length)} کاربر انتخاب‌شده اطمینان دارید؟ این عمل قابل بازگشت نیست.`}
        confirmLabel={`حذف ${formatNumber(selected.length)} کاربر`}
        danger
        loading={bulkDeleting}
        onConfirm={handleBulkDelete}
        onCancel={() => setConfirmBulkDel(false)}
      />

      {/* Role change modal */}
      {roleTarget && (
        <ChangeRoleModal
          user={roleTarget}
          loading={updateRoleMut.isPending}
          onClose={() => setRoleTarget(null)}
          onSave={(r) => updateRoleMut.mutate({ uuid: roleTarget.uuid, role: r })}
        />
      )}
    </div>
  );
}
