"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import {
  deleteAgentNode,
  getAgentNodeProfile,
  getAgentTree,
  postAgentNode,
  putAgentNode,
  putAgentNodeProfile,
} from "@/api/admin-agents";
import { getAdminPlayers } from "@/api/admin-player";
import {
  AgentLineDetailPanel,
  type AgentDetailTab,
} from "@/modules/agents/agent-line-detail-panel";
import { AgentLineProvisionWizard } from "@/modules/agents/agent-line-provision-wizard";
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 { AdminNoIntegrationSiteState } from "@/components/admin/admin-no-integration-site-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 { percentValueToUi } from "@/lib/admin-rate-percent";
import {
  isLineRootAgentNode,
  isRootProfileEditableByActor,
  validateAgentProfileScalars,
  type AgentProfileValidationIssue,
} from "@/lib/agent-profile-caps";
import {
  validateAdminLoginAccount,
  validateAdminPassword,
} from "@/lib/admin-input-validation";
import { adminHasAnyPermission } from "@/lib/admin-permissions";
import {
  PRD_AGENT_MANAGE,
  PRD_AGENT_LINE_PROVISION_ACCESS_ANY,
  PRD_AGENT_PROFILE_MANAGE,
  PRD_AGENTS_ACCESS_ANY,
  PRD_USERS_MANAGE,
} from "@/lib/admin-prd";
import { useAdminSiteCodeOptions } from "@/hooks/use-admin-site-code-options";
import { isSiteAdminOperator } from "@/lib/admin-session-variants";
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 router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const profile = useAdminProfile();
  const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
  const boundAgent = profile?.agent ?? null;

  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 canProvisionLine =
    boundAgent === null &&
    (isSuperAdmin ||
      adminHasAnyPermission(profile?.permissions, [...PRD_AGENT_LINE_PROVISION_ACCESS_ANY]));
  const { sites: siteOptions, loading: sitesLoading } = 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>("profile");
  const [profileSaving, setProfileSaving] = useState(false);
  const [selectedProfile, setSelectedProfile] = useState<AgentProfileRow | null>(null);
  const [selectedProfileLoading, setSelectedProfileLoading] = useState(false);
  const [selectedProfileErr, setSelectedProfileErr] = useState<string | null>(null);

  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 [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 [profileBaselineCreditLimit, setProfileBaselineCreditLimit] = useState(0);
  const [profileMinCreditLimit, setProfileMinCreditLimit] = useState(0);
  const [editingNodeNeedsPrimaryAccount, setEditingNodeNeedsPrimaryAccount] = useState(false);

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

  const selectedNodeIdFromUrl = Number.parseInt(
    searchParams.get("agent_node_id") ?? searchParams.get("node") ?? "",
    10,
  );

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

  const applyProfileRowToForm = (row: AgentProfileRow) => {
    setProfileShareRate(percentValueToUi(row.total_share_rate ?? 0));
    setProfileCreditLimit(String(row.credit_limit ?? 0));
    setProfileRebateLimit(percentValueToUi(row.rebate_limit ?? 0));
    setProfileDefaultRebate(percentValueToUi(row.default_player_rebate ?? 0));
    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);
    setProfileBaselineCreditLimit(row.credit_limit ?? 0);
    setProfileMinCreditLimit(row.allocated_credit ?? 0);
    setProfileRiskTags((row.risk_tags ?? []).join(", "));
  };

  const profilePayload = (creditNode: AgentNodeRow | null = selectedNode) => {
    const shareRate = Number.parseFloat(profileShareRate) || 0;
    const creditEditable = isRootProfileEditableByActor(creditNode, isSuperAdmin);
    const base = {
      ...(creditEditable
        ? { credit_limit: Number.parseInt(profileCreditLimit, 10) || 0 }
        : {}),
      rebate_limit: Number.parseFloat(profileRebateLimit) || 0,
      default_player_rebate: Number.parseFloat(profileDefaultRebate) || 0,
      can_grant_extra_rebate: profileExtraRebate,
      can_create_child_agent: profileCanCreateChild,
      can_create_player: profileCanCreatePlayer,
      risk_tags: parseRiskTagsInput(profileRiskTags),
    };
    return { ...base, total_share_rate: shareRate };
  };

  const profileValidationMessage = (issue: AgentProfileValidationIssue): string => {
    switch (issue.code) {
      case "share_range":
        return t("profile.validation.shareRange", {
          defaultValue: "占成比例须在 0–100 之间",
        });
      case "share_exceeds_parent":
        return t("profile.validation.shareExceedsParent", {
          defaultValue: "实际占成不能超过上级（最高 {{max}}%）",
          max: issue.max,
        });
      case "credit_invalid":
        return t("profile.validation.creditInvalid", {
          defaultValue: "授信额度须为不小于 0 的整数",
        });
      case "credit_exceeds_parent":
        return t("profile.validation.creditExceedsParentWithMax", {
          defaultValue: "授信额度不能超过 {{max}}",
          max: issue.max,
        });
      case "credit_below_allocated":
        return t("profile.validation.creditBelowAllocated", {
          defaultValue: "授信额度不能低于已下发给下级/玩家的总额（当前至少 {{min}}）",
          min: issue.min,
        });
      case "rebate_limit_range":
        return t("profile.validation.rebateLimitRange", {
          defaultValue: "回水上限须在 0–100% 之间",
        });
      case "default_rebate_range":
        return t("profile.validation.defaultRebateRange", {
          defaultValue: "默认玩家回水须在 0–100% 之间",
        });
      case "default_exceeds_limit":
        return t("profile.validation.defaultExceedsLimitWithMax", {
          defaultValue: "默认玩家回水不能超过 {{max}}%",
          max: issue.max,
        });
      case "rebate_exceeds_parent":
        return t("profile.validation.rebateExceedsParent", {
          defaultValue: "回水上限不能超过上级（最高 {{max}}%）",
          max: issue.max,
        });
      default:
        return t("profile.validation.invalid", { defaultValue: "配置数值不合法" });
    }
  };

  const validateProfileFields = (creditNode: AgentNodeRow | null = selectedNode): string | null => {
    const issue = validateAgentProfileScalars({
      shareRateText: profileShareRate,
      creditLimitText: profileCreditLimit,
      rebateLimitText: profileRebateLimit,
      defaultRebateText: profileDefaultRebate,
      parentCaps: profileParentCaps,
      baselineCreditLimit: profileBaselineCreditLimit,
      minCreditLimit: profileMinCreditLimit,
      usesRelativeShare: false,
      validateCredit: isRootProfileEditableByActor(creditNode, isSuperAdmin),
    });

    if (issue !== null) {
      return profileValidationMessage(issue);
    }

    return null;
  };

  const flatNodes = useMemo(() => flattenTree(tree), [tree]);
  const parentNameMap = useMemo(
    () => new Map<number, string>(flatNodes.map((node) => [node.id, node.name])),
    [flatNodes],
  );
  const visibleAgentRows = flatNodes;
  const boundSite = profile?.site ?? null;
  const rootNode = useMemo(
    () => flatNodes.find((node) => node.is_root || node.depth === 0) ?? null,
    [flatNodes],
  );
  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;
    }
    if (boundSite != null && boundSite.id === adminSiteId) {
      return boundSite.code.trim();
    }
    return rootNode?.site_code?.trim() ?? "";
  }, [adminSiteId, boundAgent?.site_code, boundSite, rootNode?.site_code, siteOptions]);

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

  const lineRootProfileLocked = useMemo(
    () => isLineRootAgentNode(selectedNode) && !isSuperAdmin,
    [isSuperAdmin, selectedNode],
  );

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

  const canViewProfileTab = canManageProfile && selectedNode !== null;

  const canEditSelectedProfile =
    canViewProfileTab && isRootProfileEditableByActor(selectedNode, isSuperAdmin);

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

  const dialogProfileEditable = isRootProfileEditableByActor(editingDialogNode, isSuperAdmin);

  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 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);
    }
  }, [setAdminSiteId, tRef]);

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

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

  useEffect(() => {
    if (visibleAgentRows.length === 0) {
      setSelectedNodeId(null);
      return;
    }

    const urlId =
      Number.isInteger(selectedNodeIdFromUrl) && selectedNodeIdFromUrl > 0
        ? selectedNodeIdFromUrl
        : null;
    const urlValid =
      urlId !== null && visibleAgentRows.some((row) => row.id === urlId);

    setSelectedNodeId((current) => {
      if (urlValid) {
        return urlId;
      }
      if (
        current !== null &&
        visibleAgentRows.some((row) => row.id === current)
      ) {
        return current;
      }
      return visibleAgentRows[0]?.id ?? null;
    });
  }, [visibleAgentRows, selectedNodeIdFromUrl]);

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

    const nodeId = selectedNode.id;
    let cancelled = false;
    setSelectedProfileLoading(true);
    setSelectedProfileErr(null);

    void getAgentNodeProfile(nodeId)
      .then((row) => {
        if (cancelled) {
          return;
        }
        setSelectedProfile(row);
        if (!nodeDialogOpen) {
          applyProfileRowToForm(row);
        }
      })
      .catch(() => {
        if (!cancelled) {
          setSelectedProfile(null);
          resetProfileForm();
          setSelectedProfileErr(
            t("profile.loadFailed", { defaultValue: "代理档案加载失败，请稍后重试。" }),
          );
        }
      })
      .finally(() => {
        if (!cancelled) {
          setSelectedProfileLoading(false);
        }
      });

    return () => {
      cancelled = true;
    };
  }, [selectedNode?.id, nodeDialogOpen]);

  const isSiteAdmin = isSiteAdminOperator(profile);

  const canShowDownlineTab = selectedNode !== null;

  const canShowPlayersTab = useMemo(
    () =>
      selectedNode !== null &&
      (hasUsersManagePermission || isSiteAdmin || isSuperAdmin),
    [hasUsersManagePermission, isSiteAdmin, isSuperAdmin, selectedNode],
  );

  const canCreatePlayerOnSelected = useMemo(() => {
    if (selectedNode === null || selectedProfileLoading || !hasUsersManagePermission) {
      return false;
    }
    if (boundAgent !== null && selectedNode.id !== boundAgent.id) {
      return false;
    }
    if (isSuperAdmin || isSiteAdmin) {
      return selectedProfile?.can_create_player !== false;
    }
    if (boundAgent !== null) {
      return selectedProfile?.can_create_player === true;
    }
    return false;
  }, [
    boundAgent,
    hasUsersManagePermission,
    isSiteAdmin,
    isSuperAdmin,
    selectedNode,
    selectedProfile?.can_create_player,
    selectedProfileLoading,
  ]);

  const [directPlayerCountById, setDirectPlayerCountById] = useState<Map<number, number>>(
    () => new Map(),
  );
  const [selectedDirectPlayerCount, setSelectedDirectPlayerCount] = useState(0);

  const prevSelectedNodeIdRef = useRef<number | null>(null);

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

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

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

  useEffect(() => {
    if (selectedNodeId === null) {
      prevSelectedNodeIdRef.current = null;
      return;
    }

    const nodeChanged = prevSelectedNodeIdRef.current !== selectedNodeId;
    prevSelectedNodeIdRef.current = selectedNodeId;

    if (!nodeChanged) {
      return;
    }

    setDetailTab((current) => {
      if (current === "profile" && canViewProfileTab) {
        return current;
      }
      if (current === "downline" && canShowDownlineTab) {
        return current;
      }
      if (current === "players" && canShowPlayersTab) {
        return current;
      }
      if (canViewProfileTab) {
        return "profile";
      }
      if (canShowPlayersTab) {
        return "players";
      }
      return "downline";
    });
  }, [canShowDownlineTab, canShowPlayersTab, canViewProfileTab, selectedNodeId]);

  useEffect(() => {
    if (selectedNodeId === null || activeSiteCode.trim() === "") {
      setSelectedDirectPlayerCount(0);
      return;
    }

    let cancelled = false;
    void getAdminPlayers({
      site_code: activeSiteCode.trim(),
      agent_node_id: selectedNodeId,
      agent_scope: "direct",
      page: 1,
      per_page: 1,
    })
      .then((data) => {
        if (cancelled) {
          return;
        }
        setSelectedDirectPlayerCount(data.meta.total);
        setDirectPlayerCountById((prev) => {
          const next = new Map(prev);
          next.set(selectedNodeId, data.meta.total);
          return next;
        });
      })
      .catch(() => {
        if (!cancelled) {
          setSelectedDirectPlayerCount(0);
        }
      });

    return () => {
      cancelled = true;
    };
  }, [activeSiteCode, selectedNodeId]);

  useEffect(() => {
    if (detailTab !== "downline" || activeSiteCode.trim() === "") {
      return;
    }

    let cancelled = false;
    for (const child of selectedChildAgents) {
      void getAdminPlayers({
        site_code: activeSiteCode.trim(),
        agent_node_id: child.id,
        agent_scope: "direct",
        page: 1,
        per_page: 1,
      })
        .then((data) => {
          if (cancelled) {
            return;
          }
          setDirectPlayerCountById((prev) => {
            const next = new Map(prev);
            next.set(child.id, data.meta.total);
            return next;
          });
        })
        .catch(() => {
          /* 删除按钮降级为仅后端校验 */
        });
    }

    return () => {
      cancelled = true;
    };
  }, [activeSiteCode, detailTab, selectedChildAgents]);

  const syncSelectedNodeToUrl = useCallback(
    (nodeId: number) => {
      const params = new URLSearchParams(searchParams.toString());
      params.set("agent_node_id", String(nodeId));
      params.delete("node");
      const qs = params.toString();
      router.replace(qs ? `${pathname}?${qs}` : pathname, { scroll: false });
    },
    [pathname, router, searchParams],
  );

  const selectAgentNode = useCallback(
    (node: AgentNodeRow) => {
      setSelectedNodeId(node.id);
      syncSelectedNodeToUrl(node.id);
    },
    [syncSelectedNodeToUrl],
  );

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

  const openCreateChildForNode = (node: AgentNodeRow) => {
    setNodeDialogMode("create");
    setTargetParentId(node.id);
    setEditingNodeId(null);
    setNodeName("");
    setNodeStatus(1);
    setNodeUsername("");
    setNodePassword("");
    setProfileLoading(canManageProfile);
    setProfileLoaded(!canManageProfile);
    setEditingNodeNeedsPrimaryAccount(false);
    resetProfileForm("create");
    setNodeDialogOpen(true);
    if (canManageProfile) {
      void getAgentNodeProfile(node.id)
        .then((p) => {
          // 使用父代理自身的 caps，不是 p.parent_caps（祖父）
          setProfileParentCaps({
            agent_node_id: node.id,
            total_share_rate: p.total_share_rate ?? 100,
            rebate_limit: p.rebate_limit ?? 0,
            available_credit: p.available_credit ?? 0,
          });
          setProfileAvailableCredit(p.available_credit ?? null);
          setProfileLoaded(true);
        })
        .catch(() => {
          setProfileParentCaps(null);
          setProfileAvailableCredit(null);
          setProfileLoaded(false);
        })
        .finally(() => {
          setProfileLoading(false);
        });
    } else {
      setProfileLoading(false);
    }
  };

  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;
    const blockedByPlayers = (directPlayerCountById.get(node.id) ?? 0) > 0;

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

  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 (!canViewProfileTab) {
      return null;
    }

    return {
      disabled:
        isOwnAgentNode || lineRootProfileLocked || !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,
      extraRebate: profileExtraRebate,
      onExtraRebateChange: setProfileExtraRebate,
      canCreatePlayer: profileCanCreatePlayer,
      onCanCreatePlayerChange: setProfileCanCreatePlayer,
      canCreateChild: profileCanCreateChild,
      onCanCreateChildChange: setProfileCanCreateChild,
      riskTags: profileRiskTags,
      onRiskTagsChange: setProfileRiskTags,
      baselineCreditLimit: profileBaselineCreditLimit,
      minCreditLimit: profileMinCreditLimit,
      profileScalarsEditable: isRootProfileEditableByActor(selectedNode, isSuperAdmin),
    };
  }, [
    canCreateChildAgent,
    canEditSelectedProfile,
    canViewProfileTab,
    isSuperAdmin,
    isOwnAgentNode,
    lineRootProfileLocked,
    selectedNode,
    profileAvailableCredit,
    profileCanCreateChild,
    profileCanCreatePlayer,
    profileCreditLimit,
    profileDefaultRebate,
    profileExtraRebate,
    profileBaselineCreditLimit,
    profileMinCreditLimit,
    profileParentCaps,
    profileRebateLimit,
    profileRiskTags,
    profileShareRate,
    selectedProfileLoading,
  ]);

  const showAgentSidebar = loading || visibleAgentRows.length > 0 || err !== null;

  const hasSiteContext =
    siteOptions.length > 0 ||
    profile?.site != null ||
    (profile?.accessible_sites?.length ?? 0) > 0;

  const isAgentLineBootLoading =
    canViewAgents &&
    (sitesLoading ||
      profile === null ||
      (hasSiteContext && adminSiteId === null) ||
      (adminSiteId !== null && loading));

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

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

    const usernameIssue = validateAdminLoginAccount(nodeUsername);
    if (usernameIssue === "invalid_charset") {
      toast.error(
        t("usernameInvalidCharset", {
          defaultValue: "登录名只能使用字母、数字、点（.）、下划线和连字符",
        }),
      );
      return;
    }

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

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

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

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

    setNodeSaving(true);
    try {
      let createdNodeId: number | null = null;
      if (nodeDialogMode === "create" && targetParentId !== null) {
        const created = await postAgentNode({
          parent_id: targetParentId,
          name: nodeName.trim(),
          username: nodeUsername.trim(),
          password: nodePassword,
          status: nodeStatus,
          ...(canManageProfile ? profilePayload(null) : {}),
        });
        createdNodeId = created.id;
        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(editingDialogNode));
        }
        toast.success(t("updateSuccess", { name: nodeName.trim() }));
      }

      setNodeDialogOpen(false);
      await loadTree(adminSiteId);
      if (nodeDialogMode === "create" && createdNodeId !== null) {
        setSelectedNodeId(createdNodeId);
        syncSelectedNodeToUrl(createdNodeId);
      } else if (nodeDialogMode === "edit" && editingNodeId !== null) {
        setSelectedNodeId(editingNodeId);
        syncSelectedNodeToUrl(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);
    }
  };

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

  if (canViewAgents && profile?.agent == null && !sitesLoading && !hasSiteContext) {
    return <AdminNoIntegrationSiteState canCreate={isSuperAdmin} />;
  }

  if (canViewAgents && isAgentLineBootLoading) {
    return <AdminLoadingState label={t("listTitle", { defaultValue: "代理列表" })} minHeight="28rem" />;
  }

  const showSiteAdminAwaitingRoot =
    !loading &&
    flatNodes.length === 0 &&
    !canProvisionLine &&
    isSiteAdminOperator(profile);

  if (showSiteAdminAwaitingRoot) {
    return (
      <div className="rounded-2xl border border-border/70 bg-card px-5 py-10 text-center shadow-sm">
        <p className="text-sm font-medium text-foreground">
          {t("lineUi.awaitingRootAgentTitle", {
            defaultValue: "本站尚未开通一级代理",
          })}
        </p>
        <p className="mx-auto mt-2 max-w-md text-sm text-muted-foreground">
          {t("lineUi.awaitingRootAgentHint", {
            defaultValue:
              "一级代理需由平台超级管理员在「开通一级代理」中创建。开通后您可在此管理下级代理、占成与授信。",
          })}
        </p>
      </div>
    );
  }

  const showProvisionEmpty =
    !loading && flatNodes.length === 0 && canProvisionLine;

  if (showProvisionEmpty) {
    return (
      <div className="flex min-h-0 flex-1 flex-col gap-0">
        <AgentLineProvisionWizard
          embedded
          defaultSiteCode={activeSiteCode}
          onSuccess={async (result) => {
            await loadTree(adminSiteId);
            const nodeId = result.line_root?.agent_node_id ?? result.agent_node?.id ?? null;
            if (nodeId !== null) {
              setSelectedNodeId(nodeId);
              syncSelectedNodeToUrl(nodeId);
            }
          }}
        />
      </div>
    );
  }

  return (
    <div className="flex min-h-0 flex-1 flex-col gap-0">
      <ConfirmDialog />

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

      {canViewAgents ? (
        <div className="flex max-h-[calc(100dvh-14rem)] min-h-0 flex-1 flex-col overflow-hidden rounded-2xl border border-border/70 bg-card shadow-sm lg:flex-row">
          {showAgentSidebar ? (
          <AgentLineSidebar
            tree={tree}
            parentNameMap={parentNameMap}
            selectedId={selectedNodeId}
            keyword={keyword}
            loading={loading && visibleAgentRows.length === 0}
            onKeywordChange={(value) => {
              setKeyword(value);
            }}
            onSelect={selectAgentNode}
            errorMessage={!loading && visibleAgentRows.length === 0 ? err : null}
            onRetry={() => void loadTree(adminSiteId)}
          />
        ) : null}

          <AgentLineDetailPanel
            node={selectedNode}
            profile={selectedProfile}
            profileLoading={selectedProfileLoading}
            profileError={selectedProfileErr}
          childAgents={selectedChildAgents}
          childCountById={childCountById}
          directPlayerCount={selectedDirectPlayerCount}
          onDirectPlayerCountChange={setSelectedDirectPlayerCount}
          siteCode={activeSiteCode}
          parentName={
            selectedNode?.parent_id !== null && selectedNode?.parent_id !== undefined
              ? (parentNameMap.get(selectedNode.parent_id) ?? null)
              : null
          }
          detailTab={detailTab}
          onDetailTabChange={setDetailTab}
          canViewProfileTab={canViewProfileTab}
          canSaveProfileTab={canManageProfile && canEditSelectedProfile && !isOwnAgentNode}
          canViewDownlineTab={canShowDownlineTab}
          canViewPlayersTab={canShowPlayersTab}
          canManageNode={canManageNode}
          canCreateChild={canCreateChildOnSelected}
          canCreatePlayerAction={canCreatePlayerOnSelected}
          canDeleteChild={canDeleteNode}
          onEditChild={(node) => openEditForNode(node)}
          onAddChild={() => selectedNode && openCreateChildForNode(selectedNode)}
          onEditCurrent={() => selectedNode && openEditForNode(selectedNode)}
          onDeleteChild={(node) => handleDeleteNode(node)}
          onSelectChild={selectAgentNode}
          profileFields={inlineProfileFields}
          profileSaving={profileSaving}
          onSaveProfile={() => void saveInlineProfile()}
          />
        </div>
      ) : (
        <div className="rounded-2xl border border-border/70 bg-card px-5 py-8 text-sm text-muted-foreground shadow-sm">
          {flatNodes.length === 0
            ? t("lineUi.noRootAgentHint", {
                defaultValue: "该站点尚未开通一级代理，请联系平台管理员在「开通一级代理」中创建线路。",
              })
            : t("lineUi.provisionOnlyHint", {
                defaultValue: "当前账号仅可开通一级代理线路，请前往「开通一级代理」页面创建新线路。",
              })}
        </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 overflow-y-auto overscroll-contain px-5 py-5">
            <div className="grid gap-5">
              <div className="space-y-2">
                <Label htmlFor="agent-name" className="text-muted-foreground">{t("name", { defaultValue: "名称" })}</Label>
                <Input
                  id="agent-name"
                  value={nodeName}
                  placeholder={t("namePlaceholder")}
                  onChange={(e) => setNodeName(e.target.value)}
                  autoComplete="off"
                  className="bg-background/50 transition-colors focus:bg-background"
                />
              </div>

              <div className="grid gap-x-4 gap-y-5 sm:grid-cols-2">
                <div className="space-y-2">
                  <Label htmlFor="agent-username" className="text-muted-foreground">{t("users.username", { defaultValue: "登录名" })}</Label>
                  <Input
                    id="agent-username"
                    value={nodeUsername}
                    placeholder={t("usernamePlaceholder")}
                    onChange={(e) => setNodeUsername(e.target.value)}
                    autoComplete="off"
                    className="bg-background/50 transition-colors focus:bg-background"
                  />
                </div>

                <div className="space-y-2">
                  <Label htmlFor="agent-password" className="text-muted-foreground">
                    {nodeDialogMode === "create" || editingNodeNeedsPrimaryAccount
                      ? t("users.password", { defaultValue: "密码" })
                      : t("resetPassword", { defaultValue: "重置密码" })}
                  </Label>
                  <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"
                    className="bg-background/50 transition-colors focus:bg-background"
                  />
                  {nodeDialogMode === "edit" && editingNodeNeedsPrimaryAccount ? (
                    <p className="text-[11px] text-muted-foreground/80">
                      {t("bindAccountHint", {
                        defaultValue: "该代理尚无登录账号，保存时将自动创建并绑定。",
                      })}
                    </p>
                  ) : null}
                </div>
              </div>

              <div className="flex items-center justify-between rounded-xl border border-border/70 bg-card px-4 py-3 shadow-sm">
                <Label className="font-medium cursor-pointer" onClick={() => setNodeStatus(nodeStatus === 1 ? 0 : 1)}>
                  {t("status", { defaultValue: "状态" })}
                </Label>
                <Switch checked={nodeStatus === 1} onCheckedChange={(value) => setNodeStatus(value ? 1 : 0)} />
              </div>

              {canManageProfile &&
              (nodeDialogMode === "create" ||
                (editingNodeId !== null &&
                  boundAgent?.id !== editingNodeId &&
                  dialogProfileEditable)) ? (
                <div className="space-y-4 border-t border-border/60 pt-5 mt-1">
                  <h3 className="text-sm font-semibold tracking-tight">
                    {t("profile.section", { defaultValue: "占成与授信配置" })}
                  </h3>
                  <AgentProfileFields
                    disabled={nodeDialogMode === "edit" && !dialogProfileEditable}
                    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}
                    extraRebate={profileExtraRebate}
                    onExtraRebateChange={setProfileExtraRebate}
                    canCreatePlayer={profileCanCreatePlayer}
                    onCanCreatePlayerChange={setProfileCanCreatePlayer}
                    canCreateChild={profileCanCreateChild}
                    onCanCreateChildChange={setProfileCanCreateChild}
                    riskTags={profileRiskTags}
                    onRiskTagsChange={setProfileRiskTags}
                    baselineCreditLimit={nodeDialogMode === "create" ? 0 : profileBaselineCreditLimit}
                    minCreditLimit={nodeDialogMode === "create" ? 0 : profileMinCreditLimit}
                    profileScalarsEditable={dialogProfileEditable}
                    idPrefix="dialog-agent-profile"
                  />
                </div>
              ) : null}
            </div>
          </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>
  );
}
