import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  ArrowRight,
  Briefcase,
  Building2,
  Check,
  ChevronDown,
  ChevronRight,
  CornerDownRight,
  Network,
  Plus,
  RefreshCw,
  Search,
  Trash2,
  UserCircle,
  UserPlus,
  Users,
} from "lucide-react";
import * as React from "react";
import { useMemo, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import { Badge } from "../../../components/ui/badge";
import { Button } from "../../../components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../../components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "../../../components/ui/dialog";
import { Input } from "../../../components/ui/input";
import { Label } from "../../../components/ui/label";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../../../components/ui/table";
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "../../../components/ui/tabs";
import { toast } from "../../../components/ui/use-toast";
import {
  type GroupSummary,
  type TenantSummary,
  type UserSummary,
  createUser,
  fetchGroups,
  fetchTenants,
  fetchUsers,
  updateTenant,
  updateUser,
} from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";
import { type TenantNode, buildTenantFullTree } from "../../../lib/tenantTree";

const getTenantIcon = (type?: string) => {
  switch (type?.toUpperCase()) {
    case "COMPANY_GROUP":
      return Briefcase;
    case "PERSONAL":
      return UserCircle;
    case "USER_GROUP":
      return Network;
    default:
      return Building2;
  }
};

const MemberListDialog: React.FC<{
  node: TenantNode;
  trigger?: React.ReactNode;
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
}> = ({ node, trigger, open, onOpenChange }) => {
  const [activeTab, setActiveTab] = useState("direct");

  const {
    data: directData,
    isLoading: isDirectLoading,
    refetch: refetchDirect,
  } = useQuery({
    queryKey: ["tenant-members", node.slug],
    queryFn: () => fetchUsers(100, 0, undefined, node.slug),
    enabled: open && activeTab === "direct",
  });

  const descendantSlugs = useMemo(() => {
    const slugs: string[] = [];
    const collect = (n: TenantNode) => {
      for (const child of n.children) {
        slugs.push(child.slug);
        collect(child);
      }
    };
    collect(node);
    return slugs;
  }, [node]);

  const {
    data: descendantData,
    isLoading: isDescendantLoading,
    refetch: refetchDescendant,
  } = useQuery({
    queryKey: ["tenant-descendant-members", node.id],
    queryFn: async () => {
      if (descendantSlugs.length === 0) return [];
      // Fetch users for all descendant slugs in parallel
      const results = await Promise.all(
        descendantSlugs
          .slice(0, 10)
          .map((slug) => fetchUsers(50, 0, undefined, slug)),
      );
      return results.flatMap((res) => res.items);
    },
    enabled: open && activeTab === "descendants" && descendantSlugs.length > 0,
  });

  const directMembers = directData?.items ?? [];
  const descendantMembers = descendantData ?? [];

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      {trigger && <DialogTrigger asChild>{trigger}</DialogTrigger>}
      <DialogContent className="sm:max-w-[700px] max-h-[90vh] flex flex-col p-0 overflow-hidden">
        <DialogHeader className="p-6 pb-2">
          <DialogTitle className="flex items-center gap-2 text-xl">
            <Users size={24} className="text-primary" />
            {node.name}{" "}
            {t("ui.admin.tenants.members.list_title", "구성원 관리")}
            <span className="text-sm font-normal text-muted-foreground ml-1">
              ({isDirectLoading ? "..." : (directData?.total ?? 0)})
            </span>
          </DialogTitle>
          <DialogDescription>
            {t(
              "msg.admin.tenants.members.desc",
              "조직에 소속된 사용자 목록을 확인합니다.",
            )}
          </DialogDescription>
        </DialogHeader>

        <Tabs
          value={activeTab}
          onValueChange={setActiveTab}
          className="flex-1 flex flex-col overflow-hidden"
        >
          <div className="px-6 border-b">
            <TabsList className="bg-transparent h-auto p-0 gap-6">
              <TabsTrigger
                value="direct"
                className="rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-transparent px-0 py-2"
              >
                {t("ui.admin.tenants.members.direct", "소속 멤버")} (
                {isDirectLoading ? "..." : (directData?.total ?? 0)})
              </TabsTrigger>
              <TabsTrigger
                value="descendants"
                disabled={node.children.length === 0}
                className="rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-transparent px-0 py-2"
              >
                {t("ui.admin.tenants.members.descendants", "하위 조직 멤버")} (
                {node.recursiveMemberCount - (node.memberCount || 0)})
              </TabsTrigger>
            </TabsList>
          </div>

          <TabsContent value="direct" className="flex-1 overflow-auto p-6 m-0">
            <MemberTable
              members={directMembers}
              isLoading={isDirectLoading}
              onRefresh={refetchDirect}
            />
          </TabsContent>

          <TabsContent
            value="descendants"
            className="flex-1 overflow-auto p-6 m-0"
          >
            <MemberTable
              members={descendantMembers}
              isLoading={isDescendantLoading}
              onRefresh={refetchDescendant}
              showTenant
            />
            {descendantSlugs.length > 10 && (
              <p className="text-[10px] text-muted-foreground mt-2 text-center">
                *{" "}
                {t(
                  "msg.admin.tenants.members.limit_notice",
                  "하위 조직이 많아 상위 10개 조직의 멤버만 표시됩니다.",
                )}
              </p>
            )}
          </TabsContent>
        </Tabs>

        <DialogFooter className="p-6 pt-2 bg-muted/5 border-t">
          <Button variant="outline" onClick={() => onOpenChange?.(false)}>
            {t("ui.common.close", "닫기")}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};

const MemberTable: React.FC<{
  members: UserSummary[];
  isLoading: boolean;
  onRefresh: () => void;
  showTenant?: boolean;
}> = ({ members, isLoading, onRefresh, showTenant }) => (
  <div className="border rounded-md overflow-hidden">
    <Table>
      <TableHeader className="sticky top-0 z-10 bg-secondary shadow-sm">
        <TableRow>
          <TableHead className="h-9">
            {t("ui.admin.users.table.name", "NAME")}
          </TableHead>
          <TableHead className="h-9">
            {t("ui.admin.users.table.email", "EMAIL")}
          </TableHead>
          {showTenant && (
            <TableHead className="h-9">
              {t("ui.admin.tenants.table.slug", "TENANT")}
            </TableHead>
          )}
          <TableHead className="h-9 text-right">
            {t("ui.admin.users.table.role", "ROLE")}
          </TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {isLoading ? (
          <TableRow>
            <TableCell
              colSpan={showTenant ? 4 : 3}
              className="text-center py-12"
            >
              {t("msg.common.loading", "로딩 중...")}
            </TableCell>
          </TableRow>
        ) : members.length === 0 ? (
          <TableRow>
            <TableCell
              colSpan={showTenant ? 4 : 3}
              className="text-center py-12"
            >
              <div className="flex flex-col items-center gap-2 opacity-40">
                <Users size={40} />
                <p>{t("msg.admin.users.list.empty", "멤버가 없습니다.")}</p>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={onRefresh}
                  className="mt-2"
                >
                  <RefreshCw size={14} className="mr-1" />{" "}
                  {t("ui.common.refresh", "다시 불러오기")}
                </Button>
              </div>
            </TableCell>
          </TableRow>
        ) : (
          members.map((user) => (
            <TableRow
              key={user.id}
              className="hover:bg-muted/50 transition-colors"
            >
              <TableCell className="font-medium py-2">{user.name}</TableCell>
              <TableCell className="text-xs font-mono py-2">
                {user.email}
              </TableCell>
              {showTenant && (
                <TableCell className="py-2">
                  <Badge variant="outline" className="text-[10px] h-5">
                    {user.tenantSlug}
                  </Badge>
                </TableCell>
              )}
              <TableCell className="text-right py-2">
                <Badge
                  variant="secondary"
                  className="text-[10px] uppercase h-5 font-bold"
                >
                  {user.role}
                </Badge>
              </TableCell>
            </TableRow>
          ))
        )}
      </TableBody>
    </Table>
  </div>
);

const UserAddDialog: React.FC<{
  tenantSlug: string;
  tenantName: string;
  trigger?: React.ReactNode;
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
}> = ({ tenantSlug, tenantName, trigger, open, onOpenChange }) => {
  const queryClient = useQueryClient();
  const [activeTab, setActiveTab] = useState("select");

  // Create state
  const [email, setEmail] = useState("");
  const [name, setName] = useState("");

  // Select state
  const [userSearch, setUserSearch] = useState("");
  const [isSearching, setIsSearching] = useState(false);
  const [searchResults, setSearchResults] = useState<UserSummary[]>([]);
  const [selectedUserId, setSelectedUserId] = useState<string | null>(null);

  const [isSubmitting, setIsSubmitting] = useState(false);

  const handleSearch = async () => {
    if (!userSearch) return;
    setIsSearching(true);
    try {
      const res = await fetchUsers(20, 0, userSearch);
      setSearchResults(res.items);
    } catch (err) {
      toast.error(t("msg.admin.users.list.fetch_error", "사용자 검색 실패"));
    } finally {
      setIsSearching(false);
    }
  };

  const handleCreate = async () => {
    if (!email || !name) {
      toast.error(
        t(
          "msg.admin.users.create.form.email_required",
          "이메일과 이름은 필수입니다.",
        ),
      );
      return;
    }
    setIsSubmitting(true);
    try {
      const res = await createUser({
        email,
        name,
        tenantSlug: tenantSlug,
        role: "user",
      });
      toast.success(
        t("msg.admin.users.create.success", "사용자가 생성되었습니다."),
        {
          description: res.initialPassword
            ? `초기 비밀번호: ${res.initialPassword}`
            : undefined,
        },
      );

      // Refresh tenant tree to update member counts
      setTimeout(() => {
        queryClient.invalidateQueries({ queryKey: ["tenants-full-tree-v2"] });
      }, 1000); // Wait 1s for backend async sync

      onOpenChange?.(false);
      resetFields();
    } catch (err: unknown) {
      const error = err as { response?: { data?: { error?: string } } };
      toast.error(
        error.response?.data?.error ||
          t("msg.admin.users.create.error", "사용자 생성 실패"),
      );
    } finally {
      setIsSubmitting(false);
    }
  };

  const handleAssign = async () => {
    if (!selectedUserId) return;
    setIsSubmitting(true);
    try {
      await updateUser(selectedUserId, { tenantSlug: tenantSlug });
      toast.success(
        t("msg.info.saved_success", "사용자가 테넌트에 배정되었습니다."),
      );

      // Refresh tenant tree to update member counts
      setTimeout(() => {
        queryClient.invalidateQueries({ queryKey: ["tenants-full-tree-v2"] });
      }, 1000); // Wait 1s for backend async sync

      onOpenChange?.(false);
      resetFields();
    } catch (err: unknown) {
      const error = err as { response?: { data?: { error?: string } } };
      toast.error(
        error.response?.data?.error ||
          t("msg.admin.users.detail.update_error", "배정 실패"),
      );
    } finally {
      setIsSubmitting(false);
    }
  };

  const resetFields = () => {
    setEmail("");
    setName("");
    setUserSearch("");
    setSearchResults([]);
    setSelectedUserId(null);
  };

  return (
    <Dialog
      open={open}
      onOpenChange={(v) => {
        onOpenChange?.(v);
        if (!v) resetFields();
      }}
    >
      {trigger && <DialogTrigger asChild>{trigger}</DialogTrigger>}
      <DialogContent className="sm:max-w-[500px]">
        <DialogHeader>
          <DialogTitle>
            {t("ui.admin.users.create.title", "사용자 추가")}
          </DialogTitle>
          <DialogDescription>
            [{tenantName}] 테넌트에 사용자를 등록하거나 기존 사용자를
            배정합니다.
          </DialogDescription>
        </DialogHeader>

        <Tabs value={activeTab} onValueChange={setActiveTab} className="mt-4">
          <TabsList className="grid w-full grid-cols-2">
            <TabsTrigger value="select">
              {t("ui.common.select", "기존 사용자 선택")}
            </TabsTrigger>
            <TabsTrigger value="create">
              {t("ui.common.create", "신규 생성")}
            </TabsTrigger>
          </TabsList>

          <TabsContent value="select" className="space-y-4 py-4">
            <div className="flex gap-2">
              <Input
                placeholder={t(
                  "ui.admin.users.list.search_placeholder",
                  "이메일 또는 이름으로 검색...",
                )}
                value={userSearch}
                onChange={(e) => setUserSearch(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && handleSearch()}
              />
              <Button
                variant="secondary"
                onClick={handleSearch}
                disabled={isSearching}
              >
                <Search size={16} />
              </Button>
            </div>

            <div className="max-h-[250px] overflow-y-auto border rounded-md">
              <Table>
                <TableBody>
                  {searchResults.length === 0 ? (
                    <TableRow>
                      <TableCell className="text-center py-8 text-muted-foreground">
                        {isSearching
                          ? t("msg.common.loading", "검색 중...")
                          : t(
                              "msg.admin.users.list.empty",
                              "사용자를 검색해 주세요.",
                            )}
                      </TableCell>
                    </TableRow>
                  ) : (
                    searchResults.map((user) => (
                      <TableRow
                        key={user.id}
                        className={`cursor-pointer hover:bg-muted/50 ${selectedUserId === user.id ? "bg-primary/5" : ""}`}
                        onClick={() => setSelectedUserId(user.id)}
                      >
                        <TableCell className="flex items-center justify-between">
                          <div>
                            <div className="font-medium text-sm">
                              {user.name}
                            </div>
                            <div className="text-xs text-muted-foreground">
                              {user.email}
                            </div>
                            {user.tenantSlug && (
                              <Badge
                                variant="outline"
                                className="text-[10px] mt-1"
                              >
                                {user.tenantSlug}
                              </Badge>
                            )}
                          </div>
                          {selectedUserId === user.id && (
                            <Check size={16} className="text-primary" />
                          )}
                        </TableCell>
                      </TableRow>
                    ))
                  )}
                </TableBody>
              </Table>
            </div>
          </TabsContent>

          <TabsContent value="create" className="space-y-4 py-4">
            <div className="grid gap-2">
              <Label htmlFor="email">
                {t("ui.admin.users.create.form.email", "이메일")}
              </Label>
              <Input
                id="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder="user@example.com"
              />
            </div>
            <div className="grid gap-2">
              <Label htmlFor="name">
                {t("ui.admin.users.create.form.name", "이름")}
              </Label>
              <Input
                id="name"
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder="홍길동"
              />
            </div>
          </TabsContent>
        </Tabs>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange?.(false)}>
            {t("ui.common.cancel", "취소")}
          </Button>
          {activeTab === "create" ? (
            <Button onClick={handleCreate} disabled={isSubmitting}>
              {isSubmitting
                ? t("msg.common.saving", "저장 중...")
                : t("ui.common.create", "생성 및 추가")}
            </Button>
          ) : (
            <Button
              onClick={handleAssign}
              disabled={isSubmitting || !selectedUserId}
            >
              {isSubmitting
                ? t("msg.common.saving", "저장 중...")
                : t("ui.common.add", "선택 사용자 배정")}
            </Button>
          )}
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};

const TenantTreeRow: React.FC<{
  node: TenantNode;
  level: number;
  isRoot: boolean;
  onRemove: (id: string, name: string) => void;
  onMove: (id: string, newParentId: string) => void;
  isUpdating: boolean;
  searchTerm?: string;
}> = ({ node, level, isRoot, onRemove, onMove, isUpdating, searchTerm }) => {
  const navigate = useNavigate();
  const [isExpanded, setIsExpanded] = useState(true);
  const [isUserAddOpen, setIsUserAddOpen] = useState(false);
  const [isMemberListOpen, setIsMemberListOpen] = useState(false);
  const [isDragOver, setIsDragOver] = useState(false);
  const hasChildren = node.children && node.children.length > 0;

  // Auto expand if search matches children
  React.useEffect(() => {
    if (searchTerm) {
      const hasMatchingChild = (n: TenantNode): boolean => {
        return n.children.some(
          (c) =>
            c.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
            c.slug.toLowerCase().includes(searchTerm.toLowerCase()) ||
            hasMatchingChild(c),
        );
      };
      if (hasMatchingChild(node)) {
        setIsExpanded(true);
      }
    }
  }, [searchTerm, node]);

  const isMatching =
    searchTerm &&
    (node.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
      node.slug.toLowerCase().includes(searchTerm.toLowerCase()));

  const TypeIcon = getTenantIcon(node.type);

  // DnD Handlers
  const handleDragStart = (e: React.DragEvent) => {
    if (isRoot) return;
    e.dataTransfer.setData("nodeId", node.id);
    e.dataTransfer.setData("nodeName", node.name);
    e.dataTransfer.effectAllowed = "move";
  };

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    if (isUpdating) return;
    setIsDragOver(true);
  };

  const handleDragLeave = () => {
    setIsDragOver(false);
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragOver(false);
    const draggedId = e.dataTransfer.getData("nodeId");
    if (!draggedId || draggedId === node.id) return;
    onMove(draggedId, node.id);
  };

  const hoverTitle = `${node.name} (${node.type})\n${t("ui.admin.tenants.members.direct", "소속 멤버")}: ${node.memberCount || 0}\n${t("ui.admin.tenants.members.total", "총 멤버")}: ${node.recursiveMemberCount || 0}`;

  return (
    <>
      <TableRow
        draggable={!isRoot}
        onDragStart={handleDragStart}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
        className={`group hover:bg-muted/30 transition-colors ${isRoot ? "bg-primary/5 font-bold" : ""} ${isMatching ? "bg-primary/10 ring-1 ring-primary/20" : ""} ${isDragOver ? "bg-primary/20 border-2 border-dashed border-primary" : ""}`}
        title={hoverTitle}
      >
        <TableCell style={{ paddingLeft: `${1 + level * 2}rem` }}>
          <div className="flex items-center gap-2">
            {hasChildren ? (
              <Button
                variant="ghost"
                size="icon"
                className="h-6 w-6 p-0 hover:bg-primary/10"
                onClick={(e) => {
                  e.stopPropagation();
                  setIsExpanded(!isExpanded);
                }}
              >
                {isExpanded ? (
                  <ChevronDown size={14} className="text-primary" />
                ) : (
                  <ChevronRight size={14} />
                )}
              </Button>
            ) : (
              level > 0 && (
                <div className="w-6 flex justify-center">
                  <div className="w-px h-full bg-border" />
                </div>
              )
            )}
            {!isRoot && (
              <CornerDownRight size={14} className="text-muted-foreground/50" />
            )}
            <div
              className={`p-1 rounded ${isRoot ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`}
            >
              <TypeIcon size={14} />
            </div>
            <span className="truncate max-w-[200px]">{node.name}</span>
            {isRoot && (
              <Badge
                variant="secondary"
                className="ml-2 text-[10px] uppercase font-bold px-1.5 h-5"
              >
                Root
              </Badge>
            )}
            <Badge
              variant="outline"
              className="text-[10px] font-mono opacity-60 ml-auto hidden sm:inline-flex"
            >
              {t(`domain.tenant_type.${node.type?.toLowerCase()}`, node.type)}
            </Badge>
          </div>
        </TableCell>
        <TableCell className="text-xs font-mono opacity-60 hidden md:table-cell">
          {node.slug}
        </TableCell>
        <TableCell>
          <button
            type="button"
            className="flex items-center gap-2 cursor-pointer hover:bg-muted p-1.5 rounded-md transition-all group/members w-full text-left"
            onClick={() => setIsMemberListOpen(true)}
            title={t(
              "msg.admin.org.hover_member_info",
              "클릭하여 멤버 상세 조회",
            )}
          >
            <div className="bg-primary/10 p-1.5 rounded text-primary">
              <Users size={16} />
            </div>
            <div className="flex flex-col">
              <div className="flex items-baseline gap-1">
                <span className="text-sm font-bold leading-none">
                  {node.memberCount || 0}
                </span>
                <span className="text-[9px] text-muted-foreground font-medium uppercase">
                  {t("ui.admin.tenants.members.direct_label", "Direct")}
                </span>
              </div>
              {node.recursiveMemberCount > (node.memberCount || 0) && (
                <div className="flex items-baseline gap-1 mt-0.5">
                  <span className="text-[11px] font-semibold text-muted-foreground leading-none">
                    {node.recursiveMemberCount}
                  </span>
                  <span className="text-[9px] text-muted-foreground/60 font-medium uppercase">
                    {t("ui.admin.tenants.members.total_label", "Total")}
                  </span>
                </div>
              )}
            </div>
          </button>
          <MemberListDialog
            node={node}
            open={isMemberListOpen}
            onOpenChange={setIsMemberListOpen}
          />
        </TableCell>
        <TableCell>
          <Badge
            variant={node.status === "active" ? "default" : "secondary"}
            className="text-[10px] h-5"
          >
            {t(`ui.common.status.${node.status}`, node.status)}
          </Badge>
        </TableCell>
        <TableCell className="text-right pr-6">
          <div className="flex justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
            <Button
              variant="ghost"
              size="icon"
              className="h-8 w-8 text-primary hover:bg-primary/10"
              onClick={() => setIsUserAddOpen(true)}
              title={t("ui.admin.users.list.add", "사용자 추가")}
            >
              <UserPlus size={14} />
            </Button>
            <Button
              variant="ghost"
              size="icon"
              className="h-8 w-8"
              onClick={() => {
                if (node.type === "USER_GROUP") {
                  // User groups have a different detail path
                  const baseTenantId =
                    (node as unknown as { tenantId?: string }).tenantId ||
                    node.parentId ||
                    "";
                  navigate(`/tenants/${baseTenantId}/organization/${node.id}`);
                } else {
                  navigate(`/tenants/${node.id}`);
                }
              }}
              title={t("ui.common.manage", "관리")}
            >
              <ArrowRight size={14} />
            </Button>
            {!isRoot && (
              <Button
                variant="ghost"
                size="icon"
                className="h-8 w-8 text-destructive hover:text-destructive hover:bg-destructive/10"
                onClick={() => onRemove(node.id, node.name)}
                disabled={isUpdating}
                title={t("ui.common.remove", "제외")}
              >
                <Trash2 size={14} />
              </Button>
            )}
          </div>
          <UserAddDialog
            tenantSlug={node.slug}
            tenantName={node.name}
            open={isUserAddOpen}
            onOpenChange={setIsUserAddOpen}
          />
        </TableCell>
      </TableRow>
      {isExpanded &&
        node.children.map((child) => (
          <TenantTreeRow
            key={child.id}
            node={child}
            level={level + 1}
            isRoot={false}
            onRemove={onRemove}
            onMove={onMove}
            isUpdating={isUpdating}
            searchTerm={searchTerm}
          />
        ))}
    </>
  );
};

function TenantUserGroupsTab() {
  const { tenantId } = useParams<{ tenantId: string }>();
  const queryClient = useQueryClient();
  const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
  const [isHeaderUserAddOpen, setIsHeaderUserAddOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  const [treeSearchTerm, setTreeSearchTerm] = useState("");

  if (!tenantId) return null;

  const { data, isLoading, refetch } = useQuery({
    queryKey: ["tenants-full-tree-v2"],
    queryFn: () => fetchTenants(1000, 0),
  });

  const { data: groupsData, isLoading: isGroupsLoading } = useQuery({
    queryKey: ["tenant-groups", tenantId],
    queryFn: () => fetchGroups(tenantId),
    enabled: !!tenantId,
  });

  const groupNodes = useMemo(() => {
    if (!groupsData) return [];
    return groupsData.map((g) => ({
      ...g,
      type: "USER_GROUP",
      children: [], // Simplified for now, just a list or separate tree
      memberCount: g.members?.length || 0,
      recursiveMemberCount: g.members?.length || 0,
    })) as unknown as TenantNode[];
  }, [groupsData]);

  const updateParentMutation = useMutation({
    mutationFn: ({
      id,
      parentId,
    }: { id: string; parentId: string | undefined }) =>
      updateTenant(id, { parentId: parentId || "" }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["tenants-full-tree-v2"] });
      toast.success(t("msg.info.saved_success", "저장되었습니다."));
      setIsAddDialogOpen(false);
    },
    onError: (error: AxiosError<{ error?: string }>) => {
      toast.error(t("msg.common.error", "오류 발생"), {
        description: error.response?.data?.error || error.message,
      });
    },
  });

  const allTenants = data?.items ?? [];

  const { currentBase, subTree } = useMemo(() => {
    const tree = buildTenantFullTree(allTenants, tenantId);
    if (tree.currentBase) {
      // Merge backend-provided UserGroups into the tree as virtual children
      tree.currentBase.children = [...tree.currentBase.children, ...groupNodes];
    }
    return tree;
  }, [allTenants, tenantId, groupNodes]);

  const handleAdd = (id: string) =>
    updateParentMutation.mutate({ id, parentId: tenantId });
  const handleMove = (id: string, newParentId: string) => {
    if (id === newParentId) return;
    updateParentMutation.mutate({ id, parentId: newParentId });
  };
  const handleRemove = (id: string, name: string) => {
    if (
      window.confirm(
        t(
          "msg.admin.tenants.remove_sub_confirm",
          `${name} 테넌트를 하위 조직에서 제외할까요?`,
          { name },
        ),
      )
    ) {
      updateParentMutation.mutate({ id, parentId: undefined });
    }
  };

  if (isLoading)
    return (
      <div className="p-12 text-center text-muted-foreground animate-pulse">
        {t("msg.common.loading", "로딩 중...")}
      </div>
    );
  if (!currentBase)
    return (
      <div className="p-12 text-center text-muted-foreground">
        {t("msg.admin.tenants.not_found", "현재 테넌트를 찾을 수 없습니다.")}{" "}
        (ID: {tenantId})
      </div>
    );

  const candidates = allTenants.filter((t) => {
    if (t.id === tenantId) return false;
    // Check if it's already a child
    if (t.parentId === tenantId) return false;
    // Basic search
    if (searchTerm === "") return true;
    return (
      t.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
      t.slug.toLowerCase().includes(searchTerm.toLowerCase())
    );
  });

  const BaseIcon = getTenantIcon(currentBase.type);

  return (
    <div className="space-y-6 mt-6 flex flex-col h-[calc(100vh-theme(spacing.32))]">
      <Card className="flex-1 flex flex-col min-h-0 bg-[var(--color-panel)] border-none shadow-sm overflow-hidden">
        <CardHeader className="flex flex-row items-center justify-between border-b bg-muted/5 py-4 flex-shrink-0">
          <div className="space-y-1">
            <CardTitle className="text-xl font-bold flex items-center gap-2">
              <BaseIcon size={20} className="text-primary" />
              {t("ui.admin.tenants.sub.title", "조직 계층 구조", {
                count: subTree.length,
              })}
            </CardTitle>
            <CardDescription>
              {t(
                "msg.admin.tenants.sub.subtitle",
                "하위 조직망을 구성하고 관리합니다.",
              )}
            </CardDescription>
          </div>
          <div className="flex flex-wrap gap-2">
            <Button variant="outline" size="sm" onClick={() => refetch()}>
              <RefreshCw size={14} className="mr-1" />{" "}
              {t("ui.common.refresh", "새로고침")}
            </Button>

            <Button
              variant="outline"
              size="sm"
              onClick={() => setIsHeaderUserAddOpen(true)}
            >
              <UserPlus size={14} className="mr-1" />
              {t("ui.admin.users.list.add", "사용자 추가")}
            </Button>
            <UserAddDialog
              tenantSlug={currentBase.slug}
              tenantName={currentBase.name}
              open={isHeaderUserAddOpen}
              onOpenChange={setIsHeaderUserAddOpen}
            />

            <Button variant="outline" size="sm" asChild>
              <Link to={`/tenants/new?parentId=${tenantId}`}>
                <Plus size={14} className="mr-1" />
                {t("ui.admin.tenants.sub.add", "신규 생성")}
              </Link>
            </Button>

            <Dialog open={isAddDialogOpen} onOpenChange={setIsAddDialogOpen}>
              <DialogTrigger asChild>
                <Button size="sm">
                  <Plus size={14} className="mr-1" />{" "}
                  {t("ui.admin.tenants.sub.add_existing", "기존 테넌트 추가")}
                </Button>
              </DialogTrigger>
              <DialogContent className="sm:max-w-[600px] p-0 overflow-hidden">
                <DialogHeader className="p-6 pb-2">
                  <DialogTitle>
                    {t(
                      "ui.admin.tenants.sub.add_dialog_title",
                      "하위 테넌트 추가",
                    )}
                  </DialogTitle>
                  <DialogDescription>
                    {t(
                      "ui.admin.tenants.sub.add_dialog_desc",
                      "기존에 등록된 테넌트를 검색하여 하위 조직으로 추가합니다.",
                    )}
                  </DialogDescription>
                </DialogHeader>
                <div className="p-6 pt-2 space-y-4">
                  <div className="relative">
                    <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                    <Input
                      className="pl-9"
                      placeholder={t(
                        "ui.admin.tenants.sub.search_placeholder",
                        "검색...",
                      )}
                      value={searchTerm}
                      onChange={(e) => setSearchTerm(e.target.value)}
                    />
                  </div>
                  <div className="max-h-[300px] overflow-y-auto border rounded-md">
                    <Table>
                      <TableBody>
                        {candidates.length === 0 ? (
                          <TableRow>
                            <TableCell className="text-center py-8 text-muted-foreground">
                              {t(
                                "ui.admin.tenants.sub.no_candidates",
                                "검색 결과 없음",
                              )}
                            </TableCell>
                          </TableRow>
                        ) : (
                          candidates.map((tenant) => {
                            const CandidateIcon = getTenantIcon(tenant.type);
                            return (
                              <TableRow
                                key={tenant.id}
                                className="hover:bg-muted/50"
                              >
                                <TableCell>
                                  <div className="flex items-center gap-2">
                                    <div className="p-1 rounded bg-muted text-muted-foreground">
                                      <CandidateIcon size={12} />
                                    </div>
                                    <div>
                                      <div className="font-medium text-sm">
                                        {tenant.name}
                                      </div>
                                      <div className="text-[10px] text-muted-foreground font-mono">
                                        {tenant.slug}
                                      </div>
                                    </div>
                                  </div>
                                </TableCell>
                                <TableCell>
                                  <Badge
                                    variant="outline"
                                    className="text-[10px]"
                                  >
                                    {t(
                                      `domain.tenant_type.${tenant.type?.toLowerCase()}`,
                                      tenant.type,
                                    )}
                                  </Badge>
                                </TableCell>
                                <TableCell className="text-right">
                                  <Button
                                    size="sm"
                                    variant="outline"
                                    className="h-8"
                                    onClick={() => handleAdd(tenant.id)}
                                    disabled={updateParentMutation.isPending}
                                  >
                                    {t("ui.common.add", "추가")}
                                  </Button>
                                </TableCell>
                              </TableRow>
                            );
                          })
                        )}
                      </TableBody>
                    </Table>
                  </div>
                </div>
              </DialogContent>
            </Dialog>
          </div>
        </CardHeader>
        <div className="px-6 py-3 bg-muted/5 border-b flex items-center gap-4 flex-shrink-0">
          <div className="relative flex-1 max-w-sm">
            <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
            <Input
              placeholder={t(
                "ui.admin.tenants.sub.tree_search_placeholder",
                "조직도 내 검색...",
              )}
              className="pl-9 h-9"
              value={treeSearchTerm}
              onChange={(e) => setTreeSearchTerm(e.target.value)}
            />
          </div>
          {treeSearchTerm && (
            <Button
              variant="ghost"
              size="sm"
              onClick={() => setTreeSearchTerm("")}
              className="text-xs"
            >
              {t("ui.common.clear_search", "검색 초기화")}
            </Button>
          )}
        </div>
        <CardContent className="flex-1 flex flex-col min-h-0 p-0">
          <div className="flex-1 rounded-md border-0 overflow-hidden flex flex-col">
            <div className="flex-1 overflow-auto relative custom-scrollbar">
              <Table>
                <TableHeader className="sticky top-0 z-10 bg-secondary shadow-sm">
                  <TableRow>
                    <TableHead className="pl-6 w-[40%]">
                      {t("ui.admin.tenants.table.name", "NAME")}
                    </TableHead>
                    <TableHead className="hidden md:table-cell">
                      {t("ui.admin.tenants.table.slug", "SLUG")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.members", "MEMBERS")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.status", "STATUS")}
                    </TableHead>
                    <TableHead className="text-right pr-6">
                      {t("ui.admin.tenants.table.actions", "ACTIONS")}
                    </TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  <TenantTreeRow
                    node={currentBase}
                    level={0}
                    isRoot={true}
                    onRemove={handleRemove}
                    onMove={handleMove}
                    isUpdating={updateParentMutation.isPending}
                    searchTerm={treeSearchTerm}
                  />
                </TableBody>
              </Table>
            </div>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}

export default TenantUserGroupsTab;
