"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import {
  deleteAgentNode,
  getAgentNodeProfile,
  getAgentTree,
  postAgentNode,
  putAgentNode,
  putAgentNodeProfile,
} from "@/api/admin-agents";
import {
  AgentLineDetailPanel,
  type AgentDetailTab,
} from "@/modules/agents/agent-line-detail-panel";
import { AgentLineSidebar } from "@/modules/agents/agent-line-sidebar";
import { AgentProfileFields } from "@/modules/agents/agent-profile-fields";
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
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 { Switch } from "@/components/ui/switch";
import { useAsyncEffect } from "@/hooks/use-async-effect";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import { useTranslationRef } from "@/hooks/use-translation-ref";
import {
  percentUiToRatio,
  percentValueToUi,
  parsePercentUi,
  ratioToPercentUi,
} from "@/lib/admin-rate-percent";
import { adminHasAnyPermission } from "@/lib/admin-permissions";
import {
  PRD_AGENT_MANAGE,
  PRD_AGENT_PROFILE_MANAGE,
  PRD_AGENTS_ACCESS_ANY,
  PRD_USERS_MANAGE,
} from "@/lib/admin-prd";
import { normalizeAgentSettlementCycle } from "@/lib/agent-settlement-cycle";
import { useAdminSiteCodeOptions } from "@/hooks/use-admin-site-code-options";
import { useAdminProfile } from "@/stores/admin-session";
import { useAgentManagementSiteStore } from "@/stores/agent-management-site";
import type { AgentNodeRow, AgentParentCaps, AgentProfileRow } from "@/types/api/admin-agent";
import { LotteryApiBizError } from "@/types/api/errors";

function parseRiskTagsInput(text: string): string[] {
  return Array.from(
    new Set(
      text
        .split(/[,，\s]+/)
        .map((tag) => tag.trim())
        .filter((tag) => tag.length > 0),
    ),
  );
}

function flattenTree(nodes: AgentNodeRow[]): AgentNodeRow[] {
  const out: AgentNodeRow[] = [];
  const walk = (list: AgentNodeRow[]) => {
    for (const node of list) {
      out.push(node);
      if (node.children?.length) {
        walk(node.children);
      }
    }
  };
  walk(nodes);

  return out;
}

export function AgentsConsole(): React.ReactElement {
  const { t } = useTranslation(["agents", "common"]);
  const tRef = useTranslationRef(["agents", "common"]);
  const profile = useAdminProfile();
  const { request: requestConfirm, ConfirmDialog } = useConfirmAction();

  const isSuperAdmin = profile?.is_super_admin === true;
  const canManageNode =
    isSuperAdmin || adminHasAnyPermission(profile?.permissions, [PRD_AGENT_MANAGE]);
  const canViewAgents =
    isSuperAdmin ||
    adminHasAnyPermission(profile?.permissions, [...PRD_AGENTS_ACCESS_ANY]);
  const canManageProfile =
    isSuperAdmin ||
    adminHasAnyPermission(profile?.permissions, [
      PRD_AGENT_PROFILE_MANAGE,
      PRD_AGENT_MANAGE,
    ]);
  const { sites: siteOptions } = useAdminSiteCodeOptions();
  const adminSiteId = useAgentManagementSiteStore((s) => s.adminSiteId);
  const setAdminSiteId = useAgentManagementSiteStore((s) => s.setAdminSiteId);
  const [tree, setTree] = useState<AgentNodeRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [err, setErr] = useState<string | null>(null);
  const [keyword, setKeyword] = useState("");
  const [selectedNodeId, setSelectedNodeId] = useState<number | null>(null);
  const [detailTab, setDetailTab] = useState<AgentDetailTab>("overview");
  const [profileSaving, setProfileSaving] = useState(false);
  const [selectedProfile, setSelectedProfile] = useState<AgentProfileRow | null>(null);
  const [selectedProfileLoading, setSelectedProfileLoading] = useState(false);

  const [nodeDialogOpen, setNodeDialogOpen] = useState(false);
  const [nodeDialogMode, setNodeDialogMode] = useState<"create" | "edit">("create");
  const [targetParentId, setTargetParentId] = useState<number | null>(null);
  const [editingNodeId, setEditingNodeId] = useState<number | null>(null);
  const [nodeName, setNodeName] = useState("");
  const [nodeStatus, setNodeStatus] = useState(1);
  const [nodeUsername, setNodeUsername] = useState("");
  const [nodePassword, setNodePassword] = useState("");
  const [nodeSaving, setNodeSaving] = useState(false);
  const [profileShareRate, setProfileShareRate] = useState("0");
  const [profileCreditLimit, setProfileCreditLimit] = useState("0");
  const [profileRebateLimit, setProfileRebateLimit] = useState("0");
  const [profileDefaultRebate, setProfileDefaultRebate] = useState("0");
  const [profileSettlementCycle, setProfileSettlementCycle] = useState<
    "daily" | "weekly" | "monthly"
  >("weekly");
  const [profileExtraRebate, setProfileExtraRebate] = useState(false);
  const [profileCanCreateChild, setProfileCanCreateChild] = useState(false);
  const [profileCanCreatePlayer, setProfileCanCreatePlayer] = useState(true);
  const [profileRiskTags, setProfileRiskTags] = useState("");
  const [profileLoading, setProfileLoading] = useState(false);
  const [profileLoaded, setProfileLoaded] = useState(true);
  const [profileParentCaps, setProfileParentCaps] = useState<AgentParentCaps | null>(null);
  const [profileAvailableCredit, setProfileAvailableCredit] = useState<number | null>(null);
  const [editingNodeNeedsPrimaryAccount, setEditingNodeNeedsPrimaryAccount] = useState(false);

  const boundAgent = profile?.agent ?? null;
  /** 登录账号是否可向子代理下放「允许创建下级」 */
  const canCreateChildAgent =
    isSuperAdmin || boundAgent?.can_create_child_agent !== false;
  const hasUsersManagePermission =
    isSuperAdmin ||
    adminHasAnyPermission(profile?.permissions, [PRD_USERS_MANAGE]);
  const [rootProfile, setRootProfile] = useState<AgentProfileRow | null>(null);

  const resetProfileForm = (mode: "create" | "edit" = "create") => {
    setProfileShareRate("0");
    setProfileCreditLimit("0");
    setProfileRebateLimit("0");
    setProfileDefaultRebate("0");
    setProfileSettlementCycle("weekly");
    setProfileExtraRebate(false);
    setProfileCanCreateChild(mode === "create" ? false : false);
    setProfileCanCreatePlayer(true);
    setProfileRiskTags("");
    setProfileParentCaps(null);
    setProfileAvailableCredit(null);
  };

  const applyProfileRowToForm = (row: AgentProfileRow) => {
    setProfileShareRate(percentValueToUi(row.total_share_rate ?? 0));
    setProfileCreditLimit(String(row.credit_limit ?? 0));
    setProfileRebateLimit(ratioToPercentUi(row.rebate_limit ?? 0));
    setProfileDefaultRebate(ratioToPercentUi(row.default_player_rebate ?? 0));
    setProfileSettlementCycle(normalizeAgentSettlementCycle(row.settlement_cycle));
    setProfileExtraRebate(Boolean(row.can_grant_extra_rebate));
    setProfileCanCreateChild(Boolean(row.can_create_child_agent));
    setProfileCanCreatePlayer(row.can_create_player !== false);
    setProfileParentCaps(row.parent_caps ?? null);
    setProfileAvailableCredit(row.available_credit ?? null);
    setProfileRiskTags((row.risk_tags ?? []).join(", "));
  };

  const profilePayload = () => ({
    total_share_rate: Number.parseFloat(profileShareRate) || 0,
    credit_limit: Number.parseInt(profileCreditLimit, 10) || 0,
    rebate_limit: percentUiToRatio(profileRebateLimit),
    default_player_rebate: percentUiToRatio(profileDefaultRebate),
    settlement_cycle: normalizeAgentSettlementCycle(profileSettlementCycle),
    can_grant_extra_rebate: profileExtraRebate,
    can_create_child_agent: profileCanCreateChild,
    can_create_player: profileCanCreatePlayer,
    risk_tags: parseRiskTagsInput(profileRiskTags),
  });

  const validateProfileFields = (): string | null => {
    const shareRate = Number.parseFloat(profileShareRate);
    const creditLimit = Number.parseInt(profileCreditLimit, 10);
    const rebateLimit = parsePercentUi(profileRebateLimit);
    const defaultRebate = parsePercentUi(profileDefaultRebate);

    if (Number.isNaN(shareRate) || shareRate < 0 || shareRate > 100) {
      return t("profile.validation.shareRange", {
        defaultValue: "占成比例须在 0–100 之间",
      });
    }

    if (Number.isNaN(creditLimit) || creditLimit < 0) {
      return t("profile.validation.creditInvalid", {
        defaultValue: "授信额度不能为负数",
      });
    }

    if (rebateLimit === null || rebateLimit < 0 || rebateLimit > 100) {
      return t("profile.validation.rebateLimitRange", {
        defaultValue: "回水上限须在 0–100% 之间",
      });
    }

    if (defaultRebate === null || defaultRebate < 0 || defaultRebate > 100) {
      return t("profile.validation.defaultRebateRange", {
        defaultValue: "默认玩家回水须在 0–100% 之间",
      });
    }

    if (rebateLimit > 0 && defaultRebate > rebateLimit) {
      return t("profile.validation.defaultExceedsLimit", {
        defaultValue: "默认玩家回水不能超过回水上限",
      });
    }

    return null;
  };

  const flatNodes = useMemo(() => flattenTree(tree), [tree]);
  const parentNameMap = useMemo(
    () => new Map<number, string>(flatNodes.map((node) => [node.id, node.name])),
    [flatNodes],
  );
  const businessRows = useMemo(() => flatNodes.filter((node) => !node.is_root), [flatNodes]);
  const selectedSiteLabel = useMemo(
    () => siteOptions.find((site) => site.id === adminSiteId)?.name ?? null,
    [adminSiteId, siteOptions],
  );
  const activeSiteCode = useMemo(() => {
    const fromAgent = boundAgent?.site_code?.trim();
    if (fromAgent) {
      return fromAgent;
    }
    const fromSite = siteOptions.find((site) => site.id === adminSiteId)?.code?.trim();
    if (fromSite) {
      return fromSite;
    }
    return flatNodes.find((node) => node.depth === 0)?.code?.trim() ?? "";
  }, [adminSiteId, boundAgent?.site_code, flatNodes, siteOptions]);
  const rootNode = useMemo(
    () => flatNodes.find((node) => node.is_root || node.depth === 0) ?? null,
    [flatNodes],
  );

  const selectedNode = useMemo(
    () =>
      selectedNodeId !== null
        ? (flatNodes.find((node) => node.id === selectedNodeId) ?? null)
        : null,
    [flatNodes, selectedNodeId],
  );

  const isOwnAgentNode =
    boundAgent !== null && selectedNodeId !== null && selectedNodeId === boundAgent.id;

  const canEditSelectedProfile =
    canManageProfile && selectedNode !== null && (isSuperAdmin || !isOwnAgentNode);

  const selectedChildAgents = useMemo(() => {
    if (selectedNode === null) {
      return [];
    }

    return flatNodes.filter((node) => node.parent_id === selectedNode.id);
  }, [flatNodes, selectedNode]);

  const childCountById = useMemo(() => {
    const counts = new Map<number, number>();
    for (const node of flatNodes) {
      if (node.parent_id === null) {
        continue;
      }
      counts.set(node.parent_id, (counts.get(node.parent_id) ?? 0) + 1);
    }
    return counts;
  }, [flatNodes]);

  const filteredRows = useMemo(() => {
    const normalized = keyword.trim().toLowerCase();

    return businessRows.filter((node) => {
      if (normalized === "") {
        return true;
      }

      const parentName =
        node.parent_id !== null ? (parentNameMap.get(node.parent_id) ?? "") : "";

      return [node.name, node.code, node.username ?? "", parentName]
        .join(" ")
        .toLowerCase()
        .includes(normalized);
    });
  }, [businessRows, keyword, parentNameMap]);

  const loadTree = useCallback(async (siteId?: number | null) => {
    setLoading(true);
    setErr(null);
    try {
      const data = await getAgentTree(siteId ?? undefined);
      setTree(data.tree);
      setAdminSiteId(data.admin_site_id);
    } catch (e) {
      setErr(e instanceof LotteryApiBizError ? e.message : tRef.current("loadFailed"));
      setTree([]);
    } finally {
      setLoading(false);
    }
  }, [tRef]);

  useEffect(() => {
    if (!canViewAgents) {
      return;
    }

    if (adminSiteId === null) {
      if (profile?.agent?.admin_site_id) {
        setAdminSiteId(profile.agent.admin_site_id);
        return;
      }
      if (siteOptions.length > 0 && isSuperAdmin) {
        setAdminSiteId(siteOptions[0]?.id ?? null);
      }
    }
  }, [adminSiteId, canViewAgents, isSuperAdmin, profile?.agent?.admin_site_id, setAdminSiteId, siteOptions]);

  useAsyncEffect(() => {
    if (selectedNode === null) {
      setSelectedProfile(null);
      setSelectedProfileLoading(false);
      return;
    }

    setSelectedProfileLoading(true);
    void getAgentNodeProfile(selectedNode.id)
      .then((row) => {
        setSelectedProfile(row);
        if (!nodeDialogOpen) {
          applyProfileRowToForm(row);
        }
      })
      .catch(() => setSelectedProfile(null))
      .finally(() => setSelectedProfileLoading(false));
  }, [selectedNode?.id, nodeDialogOpen]);

  useAsyncEffect(() => {
    if (rootNode === null) {
      setRootProfile(null);
      return;
    }

    void getAgentNodeProfile(rootNode.id)
      .then((p) => setRootProfile(p))
      .catch(() => setRootProfile(null));
  }, [rootNode?.id]);

  /** 仅上级/平台维护下级占成授信；代理查看自己时不展示配置 Tab */
  const canShowProfileTab = canEditSelectedProfile;

  const canShowDownlineTab = useMemo(
    () =>
      selectedNode !== null &&
      !selectedProfileLoading &&
      selectedProfile?.can_create_child_agent === true,
    [selectedNode, selectedProfile, selectedProfileLoading],
  );

  const canShowPlayersTab = useMemo(
    () =>
      selectedNode !== null &&
      !selectedProfileLoading &&
      selectedProfile?.can_create_player === true &&
      hasUsersManagePermission,
    [hasUsersManagePermission, selectedNode, selectedProfile, selectedProfileLoading],
  );

  const canCreateChildOnSelected = useMemo(
    () => canManageNode && selectedProfile?.can_create_child_agent === true,
    [canManageNode, selectedProfile?.can_create_child_agent],
  );

  useEffect(() => {
    if (selectedProfileLoading || selectedNode === null) {
      return;
    }

    if (detailTab === "profile" && !canShowProfileTab) {
      setDetailTab("overview");
    } else if (detailTab === "downline" && !canShowDownlineTab) {
      setDetailTab(canShowPlayersTab ? "players" : "overview");
    } else if (detailTab === "players" && !canShowPlayersTab) {
      setDetailTab(canShowDownlineTab ? "downline" : "overview");
    }
  }, [
    canShowDownlineTab,
    canShowPlayersTab,
    canShowProfileTab,
    detailTab,
    selectedNode,
    selectedProfileLoading,
  ]);

  useAsyncEffect(() => {
    if (filteredRows.length === 0) {
      setSelectedNodeId(null);
      return;
    }

    if (selectedNodeId === null || !filteredRows.some((row) => row.id === selectedNodeId)) {
      setSelectedNodeId(filteredRows[0]?.id ?? null);
    }
  }, [filteredRows, selectedNodeId]);

  useEffect(() => {
    setDetailTab("overview");
  }, [selectedNodeId]);

  useEffect(() => {
    if (isOwnAgentNode && detailTab === "profile") {
      setDetailTab("overview");
    }
  }, [detailTab, isOwnAgentNode]);

  useAsyncEffect(() => {
    if (adminSiteId !== null) {
      void loadTree(adminSiteId);
    }
  }, [adminSiteId, loadTree]);

  const openCreateChildForNode = (node: AgentNodeRow) => {
    setNodeDialogMode("create");
    setTargetParentId(node.id);
    setEditingNodeId(null);
    setNodeName("");
    setNodeStatus(1);
    setNodeUsername("");
    setNodePassword("");
    resetProfileForm("create");
    setProfileLoading(false);
    setProfileLoaded(true);
    setEditingNodeNeedsPrimaryAccount(false);
    setNodeDialogOpen(true);
    if (canManageProfile) {
      void getAgentNodeProfile(node.id)
        .then((p) => setProfileParentCaps(p.parent_caps ?? null))
        .catch(() => setProfileParentCaps(null));
    }
  };

  const openEditForNode = (node: AgentNodeRow) => {
    setNodeDialogMode("edit");
    setTargetParentId(node.parent_id);
    setEditingNodeId(node.id);
    setNodeName(node.name);
    setNodeStatus(node.status);
    setNodeUsername(node.username ?? "");
    setEditingNodeNeedsPrimaryAccount((node.username ?? "").trim() === "");
    setNodePassword("");
    resetProfileForm("edit");
    setNodeDialogOpen(true);

    if (!canManageProfile) {
      setProfileLoading(false);
      setProfileLoaded(true);
      return;
    }

    setProfileLoading(true);
    setProfileLoaded(false);
    void getAgentNodeProfile(node.id)
      .then((p) => {
        applyProfileRowToForm(p);
        setProfileLoaded(true);
      })
      .catch(() => {
        toast.error(
          t("profile.loadFailed", { defaultValue: "加载占成与授信失败，请关闭后重试" }),
        );
        setProfileLoaded(false);
      })
      .finally(() => {
        setProfileLoading(false);
      });
  };

  const canDeleteNode = (node: AgentNodeRow): boolean => {
    const blockedByChildren = (node.children?.length ?? 0) > 0;
    const blockedBySelf = profile?.agent?.id === node.id;

    return canManageNode && !blockedByChildren && !blockedBySelf;
  };

  const handleDeleteNode = (node: AgentNodeRow): void => {
    if (!canDeleteNode(node)) {
      return;
    }

    requestConfirm({
      title: t("deleteNode", { defaultValue: "删除代理" }),
      description: t("deleteNodeConfirm", {
        defaultValue: "删除后将同时移除该代理的唯一登录账号，且不可恢复。",
      }),
      confirmLabel: t("deleteNode", { defaultValue: "删除代理" }),
      confirmVariant: "destructive",
      onConfirm: async () => {
        await deleteAgentNode(node.id);
        toast.success(t("deleteSuccess", { name: node.name }));
        if (selectedNodeId === node.id) {
          setSelectedNodeId(null);
        }
        await loadTree(adminSiteId);
      },
    });
  };

  const saveInlineProfile = async (): Promise<void> => {
    if (selectedNode === null || !canEditSelectedProfile) {
      return;
    }

    const validationError = validateProfileFields();
    if (validationError) {
      toast.error(validationError);
      return;
    }

    setProfileSaving(true);
    try {
      const updated = await putAgentNodeProfile(selectedNode.id, profilePayload());
      setSelectedProfile(updated);
      applyProfileRowToForm(updated);
      toast.success(t("profile.saveSuccess", { defaultValue: "占成与授信已保存" }));
      await loadTree(adminSiteId);
    } catch (e) {
      toast.error(e instanceof LotteryApiBizError ? e.message : t("saveFailed"));
    } finally {
      setProfileSaving(false);
    }
  };

  const inlineProfileFields = useMemo(() => {
    if (!canShowProfileTab) {
      return null;
    }

    return {
      disabled: !canEditSelectedProfile,
      loading: selectedProfileLoading,
      parentCaps: profileParentCaps,
      availableCredit: profileAvailableCredit,
      canCreateChildAgent,
      isSuperAdmin,
      shareRate: profileShareRate,
      onShareRateChange: setProfileShareRate,
      creditLimit: profileCreditLimit,
      onCreditLimitChange: setProfileCreditLimit,
      rebateLimit: profileRebateLimit,
      onRebateLimitChange: setProfileRebateLimit,
      defaultRebate: profileDefaultRebate,
      onDefaultRebateChange: setProfileDefaultRebate,
      settlementCycle: profileSettlementCycle,
      onSettlementCycleChange: setProfileSettlementCycle,
      extraRebate: profileExtraRebate,
      onExtraRebateChange: setProfileExtraRebate,
      canCreatePlayer: profileCanCreatePlayer,
      onCanCreatePlayerChange: setProfileCanCreatePlayer,
      canCreateChild: profileCanCreateChild,
      onCanCreateChildChange: setProfileCanCreateChild,
      riskTags: profileRiskTags,
      onRiskTagsChange: setProfileRiskTags,
    };
  }, [
    canCreateChildAgent,
    canEditSelectedProfile,
    canShowProfileTab,
    isSuperAdmin,
    profileAvailableCredit,
    profileCanCreateChild,
    profileCanCreatePlayer,
    profileCreditLimit,
    profileDefaultRebate,
    profileExtraRebate,
    profileParentCaps,
    profileRebateLimit,
    profileRiskTags,
    profileSettlementCycle,
    profileShareRate,
    selectedProfileLoading,
  ]);

  const showAgentSidebar = businessRows.length > 1;

  const openAddAgent = (): void => {
    const parent = selectedNode ?? rootNode;
    if (parent !== null) {
      openCreateChildForNode(parent);
    }
  };

  const saveNode = async () => {
    if (!nodeName.trim()) {
      toast.error(t("nameRequired", { defaultValue: "请填写代理名称" }));
      return;
    }

    if (!nodeUsername.trim()) {
      toast.error(t("usernameRequired", { defaultValue: "请填写登录名" }));
      return;
    }

    if (nodeDialogMode === "create") {
      if (targetParentId === null) {
        return;
      }
      if (!nodePassword.trim()) {
        toast.error(t("passwordRequired", { defaultValue: "请填写密码" }));
        return;
      }
      if (nodePassword.trim().length < 8) {
        toast.error(t("passwordMinLength", { defaultValue: "密码至少 8 位" }));
        return;
      }
    } else if (nodePassword.trim() && nodePassword.trim().length < 8) {
      toast.error(t("passwordMinLength", { defaultValue: "密码至少 8 位" }));
      return;
    } else if (nodeDialogMode === "edit" && editingNodeNeedsPrimaryAccount && !nodePassword.trim()) {
      toast.error(
        t("bindAccountPasswordRequired", {
          defaultValue: "该代理尚未绑定登录账号，请填写初始密码以创建账号",
        }),
      );
      return;
    }

    const includeProfileInDialog =
      canManageProfile &&
      (nodeDialogMode === "create" ||
        (editingNodeId !== null && boundAgent?.id !== editingNodeId));

    if (includeProfileInDialog) {
      if (nodeDialogMode === "edit" && !profileLoaded) {
        toast.error(
          t("profile.loadingBlocked", {
            defaultValue: "占成与授信尚未加载完成，请稍候再保存",
          }),
        );
        return;
      }

      const profileError = validateProfileFields();
      if (profileError !== null) {
        toast.error(profileError);
        return;
      }
    }

    setNodeSaving(true);
    try {
      if (nodeDialogMode === "create" && targetParentId !== null) {
        await postAgentNode({
          parent_id: targetParentId,
          name: nodeName.trim(),
          username: nodeUsername.trim(),
          password: nodePassword,
          status: nodeStatus,
          ...(canManageProfile ? profilePayload() : {}),
        });
        toast.success(t("createSuccess", { name: nodeName.trim() }));
      } else if (nodeDialogMode === "edit" && editingNodeId !== null) {
        await putAgentNode(editingNodeId, {
          name: nodeName.trim(),
          username: nodeUsername.trim(),
          password: editingNodeNeedsPrimaryAccount
            ? nodePassword.trim()
            : nodePassword.trim() || undefined,
          status: nodeStatus,
        });
        if (includeProfileInDialog) {
          await putAgentNodeProfile(editingNodeId, profilePayload());
        }
        toast.success(t("updateSuccess", { name: nodeName.trim() }));
      }

      setNodeDialogOpen(false);
      await loadTree(adminSiteId);
      if (nodeDialogMode === "create" && targetParentId !== null) {
        const refreshed = flattenTree((await getAgentTree(adminSiteId ?? undefined)).tree);
        const created = refreshed.find(
          (node) => node.parent_id === targetParentId && node.name === nodeName.trim(),
        );
        if (created) {
          setSelectedNodeId(created.id);
        }
      } else if (nodeDialogMode === "edit" && editingNodeId !== null) {
        setSelectedNodeId(editingNodeId);
        if (canManageProfile) {
          void getAgentNodeProfile(editingNodeId)
            .then((p) => {
              if (selectedNodeId === editingNodeId || selectedNodeId === null) {
                setSelectedProfile(p);
              }
            })
            .catch(() => {
              /* 树已刷新，占成区可能短暂不可用 */
            });
        }
      }
    } catch (e) {
      toast.error(e instanceof LotteryApiBizError ? e.message : t("saveFailed"));
    } finally {
      setNodeSaving(false);
    }
  };

  const addParent = selectedNode ?? rootNode;
  const parentProfileForAdd = useMemo(() => {
    if (addParent === null) {
      return null;
    }
    if (addParent.id === selectedNodeId && selectedProfile !== null) {
      return selectedProfile;
    }
    if (rootNode !== null && addParent.id === rootNode.id) {
      return rootProfile;
    }

    return null;
  }, [addParent, rootNode, rootProfile, selectedNodeId, selectedProfile]);

  if (!canViewAgents) {
    return (
      <p className="text-sm text-muted-foreground">
        {t("noAccess", { defaultValue: "您没有代理经营相关权限，请联系管理员开通。" })}
      </p>
    );
  }

  if (loading && tree.length === 0) {
    return <AdminLoadingState label={t("listTitle", { defaultValue: "代理列表" })} />;
  }

  return (
    <div className="flex min-h-[32rem] flex-col gap-0">
      <ConfirmDialog />

      {err ? <p className="px-1 text-sm text-destructive">{err}</p> : null}

      <div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-2xl border border-border/70 bg-card shadow-sm lg:flex-row">
        {showAgentSidebar ? (
          <AgentLineSidebar
            siteLabel={selectedSiteLabel}
            tree={tree}
            parentNameMap={parentNameMap}
            selectedId={selectedNodeId}
            keyword={keyword}
            agentCount={businessRows.length}
            onKeywordChange={(value) => {
              setKeyword(value);
            }}
            onSelect={(node) => {
              setSelectedNodeId(node.id);
            }}
          />
        ) : null}

        <AgentLineDetailPanel
          node={selectedNode}
          profile={selectedProfile}
          profileLoading={selectedProfileLoading}
          childAgents={selectedChildAgents}
          childCountById={childCountById}
          siteCode={activeSiteCode}
          siteLabel={selectedSiteLabel}
          parentName={
            selectedNode?.parent_id !== null && selectedNode?.parent_id !== undefined
              ? (parentNameMap.get(selectedNode.parent_id) ?? null)
              : null
          }
          detailTab={detailTab}
          onDetailTabChange={setDetailTab}
          canViewProfileTab={canShowProfileTab}
          canEditProfileTab={canEditSelectedProfile}
          profileReadOnly={isOwnAgentNode}
          canViewDownlineTab={canShowDownlineTab}
          canViewPlayersTab={canShowPlayersTab}
          canManageNode={canManageNode}
          canCreateChild={canCreateChildOnSelected}
          canDeleteChild={canDeleteNode}
          onEditChild={(node) => openEditForNode(node)}
          onAddChild={() => selectedNode && openCreateChildForNode(selectedNode)}
          onEditCurrent={() => selectedNode && openEditForNode(selectedNode)}
          onDeleteChild={(node) => handleDeleteNode(node)}
          onSelectChild={(child) => {
            setSelectedNodeId(child.id);
          }}
          profileFields={inlineProfileFields}
          profileSaving={profileSaving}
          onSaveProfile={() => void saveInlineProfile()}
        />
      </div>

      <Dialog open={nodeDialogOpen} onOpenChange={setNodeDialogOpen}>
        <DialogContent
          showCloseButton
          className="flex h-[min(90vh,760px)] !max-w-[min(520px,calc(100vw-2rem))] flex-col gap-0 overflow-hidden rounded-2xl p-0 sm:!max-w-[min(520px,calc(100vw-2rem))]"
        >
          <DialogHeader className="shrink-0 border-b px-4 py-4 pr-12">
            <DialogTitle>
              {nodeDialogMode === "create"
                ? t("createChild", { defaultValue: "添加下级代理" })
                : t("editNode", { defaultValue: "编辑代理" })}
            </DialogTitle>
          </DialogHeader>

          <div className="min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain px-4 py-4">
          <div className="space-y-2">
            <Label htmlFor="agent-name">{t("name", { defaultValue: "名称" })}</Label>
            <Input
              id="agent-name"
              value={nodeName}
              placeholder={t("namePlaceholder")}
              onChange={(e) => setNodeName(e.target.value)}
              autoComplete="off"
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="agent-username">{t("users.username", { defaultValue: "登录名" })}</Label>
            <Input
              id="agent-username"
              value={nodeUsername}
              placeholder={t("usernamePlaceholder")}
              onChange={(e) => setNodeUsername(e.target.value)}
              autoComplete="off"
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="agent-password">
              {nodeDialogMode === "create" || editingNodeNeedsPrimaryAccount
                ? t("users.password", { defaultValue: "密码" })
                : t("resetPassword", { defaultValue: "重置密码" })}
            </Label>
            {nodeDialogMode === "edit" && editingNodeNeedsPrimaryAccount ? (
              <p className="text-xs text-muted-foreground">
                {t("bindAccountHint", {
                  defaultValue: "该代理尚无登录账号，保存时将自动创建并绑定。",
                })}
              </p>
            ) : null}
            <Input
              id="agent-password"
              type="password"
              value={nodePassword}
              onChange={(e) => setNodePassword(e.target.value)}
              placeholder={
                nodeDialogMode === "edit" && !editingNodeNeedsPrimaryAccount
                  ? t("passwordOptionalHint")
                  : t("passwordPlaceholder")
              }
              autoComplete="new-password"
            />
          </div>

          <div className="flex items-center gap-2">
            <Switch checked={nodeStatus === 1} onCheckedChange={(value) => setNodeStatus(value ? 1 : 0)} />
            <Label>{t("status", { defaultValue: "状态" })}</Label>
          </div>

          {canManageProfile &&
          (nodeDialogMode === "create" ||
            (editingNodeId !== null && boundAgent?.id !== editingNodeId)) ? (
            <div className="space-y-3 border-t pt-3">
              <p className="text-sm font-medium">
                {t("profile.section", { defaultValue: "占成与授信" })}
              </p>
              <AgentProfileFields
                loading={profileLoading}
                parentCaps={profileParentCaps}
                availableCredit={profileAvailableCredit}
                canCreateChildAgent={canCreateChildAgent}
                isSuperAdmin={isSuperAdmin}
                shareRate={profileShareRate}
                onShareRateChange={setProfileShareRate}
                creditLimit={profileCreditLimit}
                onCreditLimitChange={setProfileCreditLimit}
                rebateLimit={profileRebateLimit}
                onRebateLimitChange={setProfileRebateLimit}
                defaultRebate={profileDefaultRebate}
                onDefaultRebateChange={setProfileDefaultRebate}
                settlementCycle={profileSettlementCycle}
                onSettlementCycleChange={setProfileSettlementCycle}
                extraRebate={profileExtraRebate}
                onExtraRebateChange={setProfileExtraRebate}
                canCreatePlayer={profileCanCreatePlayer}
                onCanCreatePlayerChange={setProfileCanCreatePlayer}
                canCreateChild={profileCanCreateChild}
                onCanCreateChildChange={setProfileCanCreateChild}
                riskTags={profileRiskTags}
                onRiskTagsChange={setProfileRiskTags}
                idPrefix="dialog-agent-profile"
              />
            </div>
          ) : null}
          </div>

          <DialogFooter className="!m-0 shrink-0 rounded-b-xl border-t bg-background px-4 py-4">
            <Button type="button" variant="outline" onClick={() => setNodeDialogOpen(false)}>
              {t("common:actions.cancel", { defaultValue: "取消" })}
            </Button>
            <Button
              type="button"
              disabled={nodeSaving || (nodeDialogMode === "edit" && canManageProfile && profileLoading)}
              onClick={() => void saveNode()}
            >
              {t("common:actions.save", { defaultValue: "保存" })}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

    </div>
  );
}
