"use client";

import React, { useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import DataService from "@/config/axios";
import { getApiErrorMessage } from "@/lib/api-error";
import { tenantApiPath } from "@/lib/tenant-api";
import { cn } from "@/lib/utils";
import { toast } from "sonner";
import { Filter, Pencil, Search, Trash2, UserPlus, X } from "lucide-react";
import { AddManagementRoleDialog } from "./client-management-roles-list";
import ClientWorkspaceLayout, {
  type ClientWorkspaceChildCtx,
} from "./client-workspace-layout";

type Row = {
  _id: string;
  username: string;
  email: string;
  firstName?: string;
  lastName?: string;
  status: string;
  client?: string | { _id?: string } | null;
  role?: { _id?: string; name?: string } | string | null;
  managementRole?: { _id?: string; name?: string } | string | null;
  linkedProperty?: { _id?: string; name?: string } | string | null;
};

function userClientDbId(u: Row): string | null {
  const c = u.client;
  if (!c) return null;
  if (typeof c === "object" && c !== null && "_id" in c && c._id) return String(c._id);
  return String(c);
}

function roleIdFromRow(u: Row): string {
  const r = u.role;
  if (!r) return "";
  if (typeof r === "string") return r;
  if (typeof r === "object" && r._id) return String(r._id);
  return "";
}

function managementRoleIdFromRow(u: Row): string {
  const r = u.managementRole;
  if (!r) return "";
  if (typeof r === "string") return r;
  if (typeof r === "object" && r._id) return String(r._id);
  return "";
}

type RoleOpt = {
  _id: string;
  name: string;
};

type PropertyOpt = {
  _id: string;
  name: string;
};

type AddUserFormErrors = {
  firstName?: string;
  lastName?: string;
  email?: string;
  password?: string;
  roleId?: string;
  managementRoleId?: string;
  propertyId?: string;
};

/** Sonner renders in a portal; pointer/focus there must not dismiss a Radix modal. */
function preventDialogDismissOnSonnerOutside(
  event: CustomEvent<{ originalEvent: FocusEvent | PointerEvent }>
) {
  const t = event.detail.originalEvent.target;
  if (
    t instanceof Element &&
    t.closest("[data-sonner-toaster],[data-sonner-toast]")
  ) {
    event.preventDefault();
  }
}

function hasManagementRole(u: Row): boolean {
  return managementRoleIdFromRow(u) !== "";
}

function orgAppRoleNameLower(u: Row): string {
  const r = u.role;
  if (typeof r === "object" && r !== null && "name" in r && r.name != null) {
    return String(r.name).trim().toLowerCase();
  }
  return "";
}

/** Detail page exists only for users whose organization (app) role is not named Management. */
function canOpenUserDetail(u: Row, currentUserId: string): boolean {
  if (!u._id || String(u._id) === currentUserId) return false;
  return orgAppRoleNameLower(u) !== "management";
}

function linkedPropertyLabel(u: Row): string {
  const lp = u.linkedProperty;
  if (!lp) return "—";
  if (typeof lp === "object" && lp !== null && "name" in lp && lp.name) {
    return String(lp.name);
  }
  return "—";
}

function userInitials(u: Row): string {
  const first = (u.firstName || "").trim();
  const last = (u.lastName || "").trim();
  const initials = `${first.charAt(0)}${last.charAt(0)}`.trim();
  if (initials) return initials.toUpperCase();
  return (u.email || "U").charAt(0).toUpperCase();
}

type UserFilterTab = "all" | "management" | string;

function ClientUsersTableBody({ ctx }: { ctx: ClientWorkspaceChildCtx }) {
  const { app } = useParams() as { app: string };
  const { tenantApiKey, tenantReady, tenantClientId, isSuperAdmin, workspaceClientDbId, me } = ctx;
  const currentUserId = me._id ? String(me._id) : "";
  const [userTab, setUserTab] = useState<UserFilterTab>("all");
  const [roleTabs, setRoleTabs] = useState<RoleOpt[]>([]);
  const [rows, setRows] = useState<Row[]>([]);
  const [assignableRoles, setAssignableRoles] = useState<RoleOpt[]>([]);
  const [assignableMgmtRoles, setAssignableMgmtRoles] = useState<RoleOpt[]>([]);
  const [properties, setProperties] = useState<PropertyOpt[]>([]);
  const [listLoading, setListLoading] = useState(false);

  const [userOpen, setUserOpen] = useState(false);
  const [uFirst, setUFirst] = useState("");
  const [uLast, setULast] = useState("");
  const [uEmail, setUEmail] = useState("");
  const [uPassword, setUPassword] = useState("");
  const [uRoleId, setURoleId] = useState("");
  const [uMgmtRoleId, setUMgmtRoleId] = useState("");
  const [uPropertyId, setUPropertyId] = useState("");
  const [addUserErrors, setAddUserErrors] = useState<AddUserFormErrors>({});
  const [mgmtAddRoleDialogOpen, setMgmtAddRoleDialogOpen] = useState(false);
  const [userSaving, setUserSaving] = useState(false);

  const [editOpen, setEditOpen] = useState(false);
  const [editId, setEditId] = useState<string | null>(null);
  const [eFirst, setEFirst] = useState("");
  const [eLast, setELast] = useState("");
  const [eEmail, setEEmail] = useState("");
  const [ePassword, setEPassword] = useState("");
  const [eRoleId, setERoleId] = useState("");
  const [eMgmtRoleId, setEMgmtRoleId] = useState("");
  const [selectedUserIds, setSelectedUserIds] = useState<string[]>([]);
  const [statusOverrides, setStatusOverrides] = useState<Record<string, string>>({});
  const [statusActionOpen, setStatusActionOpen] = useState(false);
  const [pendingStatusValue, setPendingStatusValue] = useState<"active" | "inactive">("active");
  const [searchInput, setSearchInput] = useState("");
  const [appliedSearch, setAppliedSearch] = useState("");
  const [page, setPage] = useState(1);
  const [pageSize] = useState(10);
  const [totalUsers, setTotalUsers] = useState(0);

  const loadUsers = useCallback(async (key: string) => {
    const queryParams: Record<string, string | number> = {
      offset: (page - 1) * pageSize,
      limit: pageSize,
    };
    if (appliedSearch.trim()) {
      queryParams.query = appliedSearch.trim();
    }
    if (userTab === "management") {
      queryParams.managementOnly = "true";
    } else if (userTab !== "all") {
      queryParams.roleId = userTab;
    }
    try {
      const res = await DataService.get(tenantApiPath(key, "/users"), {
        params: queryParams,
      });
      setRows(res.data?.data || []);
      setTotalUsers(Number(res.data?.count || 0));
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not load users"));
      setRows([]);
      setTotalUsers(0);
    }
  }, [appliedSearch, page, pageSize, userTab]);

  const loadAssignable = useCallback(async (key: string) => {
    try {
      const res = await DataService.get(tenantApiPath(key, "/assignable-roles"));
      setAssignableRoles(res.data?.data || []);
    } catch {
      setAssignableRoles([]);
    }
  }, []);

  const loadAssignableManagement = useCallback(async (key: string) => {
    try {
      const res = await DataService.get(tenantApiPath(key, "/assignable-management-roles"));
      setAssignableMgmtRoles(res.data?.data || []);
    } catch {
      setAssignableMgmtRoles([]);
    }
  }, []);

  const loadOrgRolesForTabs = useCallback(async (key: string) => {
    try {
      const res = await DataService.get(tenantApiPath(key, "/roles"));
      const data = res.data?.data;
      if (!Array.isArray(data)) {
        setRoleTabs([]);
        return;
      }
      setRoleTabs(
        data.map((r: { _id: string; name?: string }) => ({
          _id: String(r._id),
          name: r.name?.trim() ? String(r.name) : "Role",
        }))
      );
    } catch {
      setRoleTabs([]);
    }
  }, []);

  const loadProperties = useCallback(async (key: string) => {
    try {
      const res = await DataService.get(tenantApiPath(key, "/properties"));
      const data = res.data?.data;
      if (!Array.isArray(data)) {
        setProperties([]);
        return;
      }
      setProperties(
        data.map((p: { _id: string; name?: string }) => ({
          _id: String(p._id),
          name: p.name?.trim() ? String(p.name) : "Untitled property",
        }))
      );
    } catch {
      setProperties([]);
    }
  }, []);

  const loadSupportData = useCallback(
    async (key: string) => {
      try {
        await Promise.all([
          loadAssignable(key),
          loadAssignableManagement(key),
          loadOrgRolesForTabs(key),
          loadProperties(key),
        ]);
      } catch {
        /* load functions handle fallback state */
      }
    },
    [
      loadAssignable,
      loadAssignableManagement,
      loadOrgRolesForTabs,
      loadProperties,
    ]
  );

  useEffect(() => {
    if (!tenantReady) return;
    void loadSupportData(tenantApiKey);
  }, [tenantReady, tenantApiKey, loadSupportData]);

  useEffect(() => {
    if (!tenantReady) return;
    setListLoading(true);
    void loadUsers(tenantApiKey).finally(() => setListLoading(false));
  }, [tenantReady, tenantApiKey, loadUsers]);

  useEffect(() => {
    if (userTab === "all" || userTab === "management") return;
    const exists = roleTabs.some((r) => r._id === userTab);
    if (!exists && roleTabs.length > 0) setUserTab("all");
  }, [roleTabs, userTab]);

  const isManagementTab = userTab === "management";
  const tabRoleName =
    userTab !== "all" && userTab !== "management"
      ? roleTabs.find((r) => r._id === userTab)?.name
      : null;
  const showManagementRoleColumn = isManagementTab;
  const showPropertySelectOnAdd = isManagementTab;
  const isManagementNamedAppRole =
    assignableRoles.find((r) => r._id === uRoleId)?.name?.trim().toLowerCase() === "management";
  const showMgmtRolePickerInAdd =
    !!uRoleId.trim() && (isManagementTab || isManagementNamedAppRole);

  const submitUser = async () => {
    const nextErrors: AddUserFormErrors = {};
    const emailValue = uEmail.trim();
    const passwordValue = uPassword.trim();
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const hasLetter = /[A-Za-z]/.test(passwordValue);
    const hasNumber = /\d/.test(passwordValue);

    if (!uFirst.trim()) nextErrors.firstName = "First name is required";
    if (!uLast.trim()) nextErrors.lastName = "Last name is required";
    if (!emailValue) {
      nextErrors.email = "Email is required";
    } else if (!emailRegex.test(emailValue)) {
      nextErrors.email = "Enter a valid email address";
    }
    if (!passwordValue) {
      nextErrors.password = "Password is required";
    } else if (passwordValue.length < 8) {
      nextErrors.password = "Password must be at least 8 characters";
    } else if (!hasLetter || !hasNumber) {
      nextErrors.password = "Password must include at least 1 letter and 1 number";
    }
    if (!uRoleId.trim()) nextErrors.roleId = "Role is required";
    if (showMgmtRolePickerInAdd && !uMgmtRoleId.trim()) {
      nextErrors.managementRoleId = "Management role is required";
    }
    if (showPropertySelectOnAdd && !uPropertyId.trim()) {
      nextErrors.propertyId = "Property is required";
    }

    setAddUserErrors(nextErrors);
    if (Object.keys(nextErrors).length > 0) {
      return;
    }
    setUserSaving(true);
    try {
      const body: Record<string, unknown> = {
        firstName: uFirst.trim(),
        lastName: uLast.trim(),
        email: uEmail.trim(),
        password: uPassword,
        role: uRoleId,
      };
      if (isManagementTab || isManagementNamedAppRole) {
        body.managementRole = uMgmtRoleId.trim() ? uMgmtRoleId : null;
      }
      if (showPropertySelectOnAdd && uPropertyId.trim()) {
        body.propertyId = uPropertyId.trim();
      }
      await DataService.post(tenantApiPath(tenantApiKey, "/users"), body);
      toast.success("User added");
      setUserOpen(false);
      setUFirst("");
      setULast("");
      setUEmail("");
      setUPassword("");
      setURoleId("");
      setUMgmtRoleId("");
      setUPropertyId("");
      setAddUserErrors({});
      await loadUsers(tenantApiKey);
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not add user"));
    } finally {
      setUserSaving(false);
    }
  };

  const canManageUser = (u: Row) => {
    const wid = workspaceClientDbId;
    const uid = userClientDbId(u);
    return !!wid && !!uid && uid === String(wid);
  };

  const openEdit = (u: Row) => {
    setEditId(u._id);
    setEFirst(u.firstName || "");
    setELast(u.lastName || "");
    setEEmail(u.email || "");
    setEPassword("");
    setERoleId(roleIdFromRow(u));
    setEMgmtRoleId(managementRoleIdFromRow(u));
    setEditOpen(true);
  };

  const submitEdit = async () => {
    if (!editId || !eFirst.trim() || !eLast.trim() || !eEmail.trim() || !eRoleId) {
      toast.error("Fill all required fields and pick a role");
      return;
    }
    setUserSaving(true);
    try {
      const body: Record<string, string | null> = {
        firstName: eFirst.trim(),
        lastName: eLast.trim(),
        email: eEmail.trim(),
        role: eRoleId,
      };
      if (ePassword.trim()) body.password = ePassword.trim();
      body.managementRole = eMgmtRoleId.trim() ? eMgmtRoleId : null;
      await DataService.patch(tenantApiPath(tenantApiKey, `/users/${editId}`), body);
      toast.success("User updated");
      setEditOpen(false);
      setEditId(null);
      setEMgmtRoleId("");
      await loadUsers(tenantApiKey);
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not update user"));
    } finally {
      setUserSaving(false);
    }
  };

  const removeUser = async (u: Row) => {
    if (!canManageUser(u)) return;
    if (
      !confirm(
        `Remove ${[u.firstName, u.lastName].filter(Boolean).join(" ") || u.email} from this organization?`
      )
    ) {
      return;
    }
    try {
      await DataService.delete(tenantApiPath(tenantApiKey, `/users/${u._id}`));
      toast.success("User removed");
      await loadUsers(tenantApiKey);
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not remove user"));
    }
  };

  const visibleRows = rows.filter((u) => String(u._id) !== currentUserId);
  const tableRows = visibleRows;
  const normalizedAppliedSearch = appliedSearch.trim().toLowerCase();
  const filteredTableRows = tableRows;
  const colCount =
    6 +
    (showPropertySelectOnAdd ? 1 : 0) +
    (showManagementRoleColumn ? 1 : 0) +
    2;
  const allVisibleSelected =
    filteredTableRows.length > 0 &&
    filteredTableRows.every((u) => selectedUserIds.includes(String(u._id)));

  if (!tenantReady) {
    return <p className="text-sm text-gray-500">Select a client to load users.</p>;
  }

  const tabTriggerClass = (active: boolean) =>
    cn(
      "inline-flex items-center border-b-2 border-transparent px-0.5 pb-2 pt-1 text-sm font-medium transition-colors",
      active
        ? "border-primary text-slate-800"
        : "text-muted-foreground hover:text-foreground"
    );

  const openAddUserDialog = () => {
    if (userTab !== "all" && userTab !== "management") {
      setURoleId(userTab);
    } else {
      setURoleId("");
    }
    setUMgmtRoleId("");
    setUPropertyId("");
    setAddUserErrors({});
    setUserOpen(true);
  };

  const toggleAllVisibleRows = () => {
    if (allVisibleSelected) {
      setSelectedUserIds((prev) =>
        prev.filter((id) => !filteredTableRows.some((row) => String(row._id) === id))
      );
      return;
    }
    setSelectedUserIds((prev) => {
      const next = new Set(prev);
      filteredTableRows.forEach((row) => next.add(String(row._id)));
      return Array.from(next);
    });
  };

  const toggleRowSelection = (id: string) => {
    setSelectedUserIds((prev) =>
      prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]
    );
  };

  const effectiveStatus = (u: Row) => statusOverrides[String(u._id)] ?? u.status ?? "inactive";
  const selectedVisibleUserIds = filteredTableRows
    .map((u) => String(u._id))
    .filter((id) => selectedUserIds.includes(id));
  const filterIsActive =
    normalizedAppliedSearch.length > 0 &&
    searchInput.trim().toLowerCase() === normalizedAppliedSearch;
  const totalPages = Math.max(1, Math.ceil(totalUsers / pageSize));

  const openBulkStatusModal = (nextStatus: "active" | "inactive") => {
    if (selectedVisibleUserIds.length === 0) return;
    setPendingStatusValue(nextStatus);
    setStatusActionOpen(true);
  };

  const confirmBulkStatusChange = () => {
    if (selectedVisibleUserIds.length === 0) {
      setStatusActionOpen(false);
      return;
    }
    setStatusOverrides((prev) => {
      const next = { ...prev };
      selectedVisibleUserIds.forEach((id) => {
        next[id] = pendingStatusValue;
      });
      return next;
    });
    setStatusActionOpen(false);
  };
  const handleFilterButtonClick = () => {
    if (filterIsActive) {
      setAppliedSearch("");
      setSearchInput("");
      setPage(1);
      return;
    }
    setAppliedSearch(searchInput.trim());
    setPage(1);
  };

  return (
    <>
      <div className="min-w-0 overflow-hidden rounded-xl border bg-white">
        <div className="space-y-3 border-b px-3 py-3 sm:px-4">
          <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
            <h2 className="font-semibold text-gray-900">Users</h2>
            <div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center sm:justify-end">
              <div className="relative w-full sm:w-56">
                <Search className="pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-gray-400" />
                <Input
                  className="h-9 pl-8"
                  placeholder="Search"
                  value={searchInput}
                  onChange={(e) => setSearchInput(e.target.value)}
                />
              </div>
              <Button
                type="button"
                variant="outline"
                size="sm"
                className="h-9 px-3"
                onClick={handleFilterButtonClick}
              >
                {filterIsActive ? (
                  <X className="mr-2 size-4" />
                ) : (
                  <Filter className="mr-2 size-4" />
                )}
                {filterIsActive ? "Cancel" : "Filters"}
              </Button>
            </div>
          </div>
          <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div className="flex flex-wrap items-center gap-5 border-b border-border/70">
              <button
                type="button"
                className={tabTriggerClass(userTab === "all")}
                onClick={() => {
                  setUserTab("all");
                  setPage(1);
                  setSelectedUserIds([]);
                }}
              >
                All
              </button>
              {roleTabs.map((r) => (
                <button
                  key={r._id}
                  type="button"
                  className={tabTriggerClass(userTab === r._id)}
                  onClick={() => {
                    setUserTab(r._id);
                    setPage(1);
                    setSelectedUserIds([]);
                  }}
                >
                  {r.name}
                </button>
              ))}
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <Button size="sm" className="h-9 px-4" onClick={() => openAddUserDialog()}>
                <UserPlus className="mr-1 size-4" />
                Add user
              </Button>
              {selectedVisibleUserIds.length > 0 ? (
                <>
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    className="h-9 px-4"
                    onClick={() => openBulkStatusModal("active")}
                  >
                    Active
                  </Button>
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    className="h-9 px-4"
                    onClick={() => openBulkStatusModal("inactive")}
                  >
                    Inactive
                  </Button>
                </>
              ) : null}
            </div>
          </div>
        </div>
        {listLoading ? (
          <div className="p-6 text-center text-sm text-gray-500 sm:p-8">Loading users…</div>
        ) : (
          <Table
            className={
              showManagementRoleColumn && showPropertySelectOnAdd
                ? "min-w-[900px]"
                : showManagementRoleColumn || showPropertySelectOnAdd
                  ? "min-w-[800px]"
                  : "min-w-[640px]"
            }
          >
            <TableHeader>
              <TableRow className="bg-muted/30">
                <TableHead className="w-10">
                  <input
                    type="checkbox"
                    className="size-4 rounded border-gray-300 accent-primary"
                    checked={allVisibleSelected}
                    onChange={toggleAllVisibleRows}
                  />
                </TableHead>
                <TableHead className="w-20">Image</TableHead>
                <TableHead>Name</TableHead>
                <TableHead>Email Address</TableHead>
                {showPropertySelectOnAdd ? <TableHead>Property</TableHead> : null}
                <TableHead>Assign Role</TableHead>
                {showManagementRoleColumn ? (
                  <TableHead>Management Role</TableHead>
                ) : null}
                <TableHead>Status</TableHead>
                <TableHead className="w-[88px] text-right sm:w-[100px]">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {filteredTableRows.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={colCount} className="text-center text-gray-400">
                    {normalizedAppliedSearch.length > 0
                      ? "No users match your current filter."
                      : isManagementTab && visibleRows.length > 0
                        ? "No users with a management role yet. Assign one via Edit, or add below (Role, then Management role)."
                        : userTab !== "all" && userTab !== "management" && visibleRows.length > 0
                          ? `No users with this role yet. Add one above (role is pre-selected) or pick another tab.`
                          : rows.length === 0
                            ? "No users for this client yet."
                            : "No other team members yet (your account is hidden from this list)."}
                  </TableCell>
                </TableRow>
              ) : (
                filteredTableRows.map((u) => {
                  const showActions = canManageUser(u);
                  const roleName =
                    typeof u.role === "object" && u.role !== null && "name" in u.role
                      ? u.role.name
                      : "—";
                  const mgmtRoleName =
                    typeof u.managementRole === "object" &&
                      u.managementRole !== null &&
                      "name" in u.managementRole
                      ? u.managementRole.name
                      : "—";
                  const nameText = [u.firstName, u.lastName].filter(Boolean).join(" ") || "—";
                  return (
                    <TableRow key={u._id}>
                      <TableCell>
                        <input
                          type="checkbox"
                          className="size-4 rounded border-gray-300 accent-primary"
                          checked={selectedUserIds.includes(String(u._id))}
                          onChange={() => toggleRowSelection(String(u._id))}
                        />
                      </TableCell>
                      <TableCell>
                        <div className="flex size-9 items-center justify-center rounded-full bg-gray-100 text-xs font-semibold text-gray-700 ring-1 ring-gray-200">
                          {userInitials(u)}
                        </div>
                      </TableCell>
                      <TableCell className="font-medium">
                        {canOpenUserDetail(u, currentUserId) ? (
                          <Link
                            href={`/${app}/users/${u._id}`}
                            className="text-primary underline decoration-primary/40 underline-offset-2 hover:decoration-primary"
                          >
                            {nameText}
                          </Link>
                        ) : (
                          nameText
                        )}
                        <p className="text-xs font-normal text-gray-500">{u.username || "—"}</p>
                      </TableCell>
                      <TableCell>{u.email}</TableCell>
                      {showPropertySelectOnAdd ? (
                        <TableCell className="max-w-[140px] truncate text-gray-700">
                          {linkedPropertyLabel(u)}
                        </TableCell>
                      ) : null}
                      <TableCell>{roleName || "—"}</TableCell>
                      {showManagementRoleColumn ? (
                        <TableCell>{mgmtRoleName || "—"}</TableCell>
                      ) : null}
                      <TableCell>
                        <span
                          className={cn(
                            "inline-flex rounded-full px-2 py-0.5 text-xs font-medium",
                            effectiveStatus(u).toLowerCase() === "active"
                              ? "bg-emerald-50 text-emerald-700 ring-1 ring-emerald-200"
                              : "bg-gray-100 text-gray-700 ring-1 ring-gray-200"
                          )}
                        >
                          {effectiveStatus(u).toLowerCase() === "active" ? "Active" : "Inactive"}
                        </span>
                      </TableCell>
                      <TableCell className="text-right">
                        {showActions ? (
                          <div className="flex justify-end gap-1">
                            <Button
                              type="button"
                              variant="ghost"
                              size="icon"
                              className="size-8"
                              onClick={() => openEdit(u)}
                              aria-label="Edit user"
                            >
                              <Pencil className="size-4" />
                            </Button>
                            <Button
                              type="button"
                              variant="ghost"
                              size="icon"
                              className="size-8 text-red-600"
                              onClick={() => void removeUser(u)}
                              aria-label="Remove user"
                            >
                              <Trash2 className="size-4" />
                            </Button>
                          </div>
                        ) : (
                          <span className="text-xs text-gray-400">—</span>
                        )}
                      </TableCell>
                    </TableRow>
                  );
                })
              )}
            </TableBody>
          </Table>
        )}
        <div className="flex items-center justify-between border-t px-3 py-3 sm:px-4">
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={page <= 1 || listLoading}
            onClick={() => setPage((prev) => Math.max(1, prev - 1))}
          >
            Previous
          </Button>
          <p className="text-xs text-gray-500">{`Page ${page} of ${totalPages}`}</p>
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={page >= totalPages || listLoading}
            onClick={() => setPage((prev) => Math.min(totalPages, prev + 1))}
          >
            Next
          </Button>
        </div>
        {isSuperAdmin && (
          <p className="border-t px-3 py-3 text-xs leading-relaxed text-gray-500 sm:px-4">
            Full platform user directory:{" "}
            <Link href="/super-admin/admin/users" className="font-medium text-primary underline">
              Super admin → Users
            </Link>
            .
          </p>
        )}
      </div>

      <Dialog
        open={statusActionOpen}
        onOpenChange={setStatusActionOpen}
      >
        <DialogContent className="w-[calc(100vw-1rem)] max-w-md gap-4 p-4 sm:p-6">
          <DialogHeader className="space-y-1 text-left">
            <DialogTitle className="text-base sm:text-lg">Change user status</DialogTitle>
          </DialogHeader>
          <p className="text-sm text-gray-600">
            {`Set status to ${pendingStatusValue === "active" ? "Active" : "Inactive"} for ${selectedVisibleUserIds.length
              } selected user${selectedVisibleUserIds.length > 1 ? "s" : ""}?`}
          </p>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button type="button" variant="outline" onClick={() => setStatusActionOpen(false)}>
              Cancel
            </Button>
            <Button type="button" onClick={confirmBulkStatusChange}>
              {pendingStatusValue === "active" ? "Active" : "Inactive"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={userOpen}
        onOpenChange={(open) => {
          setUserOpen(open);
          if (!open) {
            setUPropertyId("");
            setMgmtAddRoleDialogOpen(false);
            setAddUserErrors({});
          }
        }}
      >
        <DialogContent
          className="max-h-[min(90vh,100dvh)] w-[calc(100vw-1rem)] max-w-lg gap-4 overflow-y-auto p-4 sm:p-6"
          onInteractOutside={preventDialogDismissOnSonnerOutside}
        >
          <DialogHeader className="space-y-1 text-left">
            <DialogTitle className="text-base sm:text-lg">Add user</DialogTitle>
          </DialogHeader>
          <div className="grid gap-3 py-2">
            <div className="grid gap-2 sm:grid-cols-2">
              <div>
                <Label htmlFor="cu-fn">First name</Label>
                <Input
                  id="cu-fn"
                  value={uFirst}
                  onChange={(e) => {
                    setUFirst(e.target.value);
                    setAddUserErrors((prev) => ({ ...prev, firstName: undefined }));
                  }}
                />
                {addUserErrors.firstName ? (
                  <p className="mt-1 text-xs text-red-600">{addUserErrors.firstName}</p>
                ) : null}
              </div>
              <div>
                <Label htmlFor="cu-ln">Last name</Label>
                <Input
                  id="cu-ln"
                  value={uLast}
                  onChange={(e) => {
                    setULast(e.target.value);
                    setAddUserErrors((prev) => ({ ...prev, lastName: undefined }));
                  }}
                />
                {addUserErrors.lastName ? (
                  <p className="mt-1 text-xs text-red-600">{addUserErrors.lastName}</p>
                ) : null}
              </div>
            </div>
            <div>
              <Label htmlFor="cu-em">Email</Label>
              <Input
                id="cu-em"
                type="email"
                value={uEmail}
                onChange={(e) => {
                  setUEmail(e.target.value);
                  setAddUserErrors((prev) => ({ ...prev, email: undefined }));
                }}
              />
              {addUserErrors.email ? (
                <p className="mt-1 text-xs text-red-600">{addUserErrors.email}</p>
              ) : null}
            </div>
            <div>
              <Label htmlFor="cu-pw">Password</Label>
              <Input
                id="cu-pw"
                type="password"
                autoComplete="new-password"
                value={uPassword}
                onChange={(e) => {
                  setUPassword(e.target.value);
                  setAddUserErrors((prev) => ({ ...prev, password: undefined }));
                }}
              />
              {addUserErrors.password ? (
                <p className="mt-1 text-xs text-red-600">{addUserErrors.password}</p>
              ) : (
                <p className="mt-1 text-xs text-gray-500">
                  Minimum 8 characters, including at least 1 letter and 1 number.
                </p>
              )}
            </div>
            <div>
              <Label>Role</Label>
              <Select
                value={uRoleId}
                onValueChange={(v) => {
                  setURoleId(v);
                  setUMgmtRoleId("");
                  setMgmtAddRoleDialogOpen(false);
                  setAddUserErrors((prev) => ({
                    ...prev,
                    roleId: undefined,
                    managementRoleId: undefined,
                  }));
                }}
              >
                <SelectTrigger className="min-w-0 max-w-full">
                  <SelectValue placeholder="Select role" />
                </SelectTrigger>
                <SelectContent>
                  {assignableRoles.map((r) => (
                    <SelectItem key={r._id} value={r._id}>
                      {r.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              {addUserErrors.roleId ? (
                <p className="mt-1 text-xs text-red-600">{addUserErrors.roleId}</p>
              ) : null}
            </div>
            {showMgmtRolePickerInAdd ? (
              <div className="space-y-2">
                <Label>
                  Management roles <span className="text-red-600">*</span>
                </Label>
                <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
                  <Select
                    value={uMgmtRoleId || "__none__"}
                    onValueChange={(v) => {
                      setUMgmtRoleId(v === "__none__" ? "" : v);
                      setAddUserErrors((prev) => ({ ...prev, managementRoleId: undefined }));
                    }}
                  >
                    <SelectTrigger className="min-w-0 w-full sm:flex-1">
                      <SelectValue placeholder="Select management role" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="__none__">None</SelectItem>
                      {assignableMgmtRoles.map((r) => (
                        <SelectItem key={r._id} value={r._id}>
                          {r.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="w-full shrink-0 sm:w-auto"
                    onClick={() => setMgmtAddRoleDialogOpen(true)}
                  >
                    Add
                  </Button>
                </div>
                <p className="text-xs text-gray-500">
                  <strong>Add</strong> opens the same dialog as{" "}
                  <Link href="/client/roles" className="font-medium text-primary underline">
                    Roles
                  </Link>{" "}
                  → Management roles → Add management role (name + allowed actions).
                </p>
                {assignableMgmtRoles.length === 0 ? (
                  <p className="text-xs text-amber-800">
                    No management roles yet—use <strong>Add</strong> above or define them under Roles.
                  </p>
                ) : null}
                {addUserErrors.managementRoleId ? (
                  <p className="text-xs text-red-600">{addUserErrors.managementRoleId}</p>
                ) : null}
              </div>
            ) : null}
            {showPropertySelectOnAdd ? (
              <div>
                <Label>Select property</Label>
                <Select
                  value={uPropertyId || "__none__"}
                  onValueChange={(v) => {
                    setUPropertyId(v === "__none__" ? "" : v);
                    setAddUserErrors((prev) => ({ ...prev, propertyId: undefined }));
                  }}
                >
                  <SelectTrigger className="min-w-0 max-w-full">
                    <SelectValue placeholder="Select property" />
                  </SelectTrigger>
                  <SelectContent>
                    {properties.map((p) => (
                      <SelectItem key={p._id} value={p._id}>
                        {p.name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <p className="mt-1 text-xs text-gray-500">
                  User will be linked to this property at the time of creation.
                </p>
                {addUserErrors.propertyId ? (
                  <p className="mt-1 text-xs text-red-600">{addUserErrors.propertyId}</p>
                ) : null}
              </div>
            ) : null}
            <p className="text-xs text-gray-500">
              {isManagementTab ? (
                <>
                  On this tab, choose <strong>Role</strong> first, then <strong>Management roles</strong>{" "}
                  (or use <strong>Add</strong> beside the dropdown).
                </>
              ) : isManagementNamedAppRole ? (
                <>
                  With app role <strong>Management</strong>, pick a <strong>Management roles</strong> title
                  (or create one with <strong>Add</strong>).
                </>
              ) : (
                <>
                  Organization roles and tabs live on{" "}
                  <Link href="/client/roles" className="font-medium text-primary underline">
                    Roles
                  </Link>
                  . Common user labels: open the matching tab or <strong>All</strong>.
                </>
              )}
            </p>
          </div>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              type="button"
              variant="outline"
              className="w-full sm:w-auto"
              onClick={() => setUserOpen(false)}
            >
              Cancel
            </Button>
            <Button
              type="button"
              className="w-full sm:w-auto"
              onClick={() => void submitUser()}
              disabled={userSaving}
            >
              {userSaving ? "Saving…" : "Add user"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={editOpen}
        onOpenChange={(open) => {
          setEditOpen(open);
          if (!open) {
            setEditId(null);
            setEFirst("");
            setELast("");
            setEEmail("");
            setEPassword("");
            setERoleId("");
            setEMgmtRoleId("");
          }
        }}
      >
        <DialogContent
          className="max-h-[min(90vh,100dvh)] w-[calc(100vw-1rem)] max-w-lg gap-4 overflow-y-auto p-4 sm:p-6"
          onInteractOutside={preventDialogDismissOnSonnerOutside}
        >
          <DialogHeader className="space-y-1 text-left">
            <DialogTitle className="text-base sm:text-lg">Edit user</DialogTitle>
          </DialogHeader>
          <div className="grid gap-3 py-2">
            <div className="grid gap-2 sm:grid-cols-2">
              <div>
                <Label htmlFor="eu-fn">First name</Label>
                <Input id="eu-fn" value={eFirst} onChange={(e) => setEFirst(e.target.value)} />
              </div>
              <div>
                <Label htmlFor="eu-ln">Last name</Label>
                <Input id="eu-ln" value={eLast} onChange={(e) => setELast(e.target.value)} />
              </div>
            </div>
            <div>
              <Label htmlFor="eu-em">Email</Label>
              <Input
                id="eu-em"
                type="email"
                value={eEmail}
                onChange={(e) => setEEmail(e.target.value)}
              />
            </div>
            <div>
              <Label htmlFor="eu-pw">New password (optional)</Label>
              <Input
                id="eu-pw"
                type="password"
                autoComplete="new-password"
                placeholder="Leave blank to keep current"
                value={ePassword}
                onChange={(e) => setEPassword(e.target.value)}
              />
            </div>
            <div>
              <Label>Role</Label>
              <Select value={eRoleId} onValueChange={setERoleId}>
                <SelectTrigger className="min-w-0 max-w-full">
                  <SelectValue placeholder="Select role" />
                </SelectTrigger>
                <SelectContent>
                  {assignableRoles.map((r) => (
                    <SelectItem key={r._id} value={r._id}>
                      {r.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label>Management role (optional)</Label>
              <Select
                value={eMgmtRoleId || "__none__"}
                onValueChange={(v) => setEMgmtRoleId(v === "__none__" ? "" : v)}
              >
                <SelectTrigger className="min-w-0 max-w-full">
                  <SelectValue placeholder="None" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="__none__">None</SelectItem>
                  {assignableMgmtRoles.map((r) => (
                    <SelectItem key={r._id} value={r._id}>
                      {r.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              type="button"
              variant="outline"
              className="w-full sm:w-auto"
              onClick={() => setEditOpen(false)}
            >
              Cancel
            </Button>
            <Button
              type="button"
              className="w-full sm:w-auto"
              onClick={() => void submitEdit()}
              disabled={userSaving}
            >
              {userSaving ? "Saving…" : "Save changes"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <AddManagementRoleDialog
        open={mgmtAddRoleDialogOpen}
        onOpenChange={setMgmtAddRoleDialogOpen}
        tenantApiKey={tenantApiKey}
        tenantReady={tenantReady}
        tenantClientId={tenantClientId}
        onSuccess={async ({ _id }) => {
          await loadAssignableManagement(tenantApiKey);
          setUMgmtRoleId(_id);
        }}
      />
    </>
  );
}

export default function ClientUsersList() {
  return (
    <ClientWorkspaceLayout
      title=""
      barDescription="Filter by organization role (from Roles) or Management. Management assignments use a second title from Roles → Management roles."
      actions={(ctx) =>
        ctx.isSuperAdmin ? (
          <Button variant="outline" size="sm" className="w-full md:w-auto" asChild>
            <Link href="/super-admin/admin/users">
              <UserPlus className="mr-2 size-4" />
              Users (platform admin)
            </Link>
          </Button>
        ) : null
      }
    >
      {(ctx) => <ClientUsersTableBody ctx={ctx} />}
    </ClientWorkspaceLayout>
  );
}
