import { Agent, McpServer } from "@/types";
import { useAccessControlsStore, useSocketStore } from "@/store";
import { useMemo } from "react";
import { getTotalConnectedTools } from "@/hooks/toolCount";

interface UseToolsMetricProps {
  agents: Agent[];
  servers: McpServer[];
}

/**
 * Custom hook to calculate the available tools metric.
 * Returns a string in the format "{availableTools}/{connectedTools}".
 *
 * Available tools are calculated as the unique count of tools from tool groups
 * assigned to connected agents. If no agents are connected or no tool groups
 * are assigned, it returns the total connected tools count.
 */
export const useToolsMetric = ({ agents, servers }: UseToolsMetricProps) => {
  const toolGroups = useAccessControlsStore((state) => state.toolGroups);
  const appConfig = useSocketStore((state) => state.appConfig);
  const connectedClients = useSocketStore(
    (state) => state.systemState?.connectedClients ?? [],
  );

  const connectedTools = useMemo(
    () => getTotalConnectedTools(servers, appConfig?.targetServerAttributes),
    [servers, appConfig?.targetServerAttributes],
  );

  const toolGroupByNameMap = useMemo(() => {
    const map = new Map<string, (typeof toolGroups)[0]>();
    toolGroups.forEach((group) => {
      map.set(group.name, group);
    });
    return map;
  }, [toolGroups]);

  // Map session IDs to consumer tags for efficient lookup
  const sessionIdToConsumerTagMap = useMemo(() => {
    const map = new Map<string, string>();
    connectedClients.forEach((client) => {
      if (client.sessionId && client.consumerTag) {
        map.set(client.sessionId, client.consumerTag);
      }
    });
    return map;
  }, [connectedClients]);

  const availableTools = useMemo(() => {
    const connectedAgents = agents.filter(
      (agent) => agent.status === "connected",
    );

    // If no agents connected, show all connected tools
    if (connectedAgents.length === 0) {
      return connectedTools;
    }

    if (!appConfig?.permissions?.consumers) {
      return connectedTools;
    }

    try {
      const assignedToolGroupNames = new Set<string>();
      let hasAnyAgentWithAllTools = false;
      let allAgentsHaveEmptyAllow = true;

      // Single pass through agents to collect all information
      for (const agent of connectedAgents) {
        // Get consumer tags for this agent's sessions
        const agentConsumerTags: string[] = [];
        for (const sessionId of agent.sessionIds) {
          const consumerTag = sessionIdToConsumerTagMap.get(sessionId);
          if (consumerTag) {
            agentConsumerTags.push(consumerTag);
          }
        }

        if (agentConsumerTags.length === 0) {
          allAgentsHaveEmptyAllow = false;
          continue;
        }

        // Check each consumer tag's config
        let agentHasAllTools = false;
        let agentHasEmptyAllow = false;
        let agentHasToolGroups = false;

        for (const consumerTag of agentConsumerTags) {
          const consumerConfig = appConfig.permissions.consumers[consumerTag];

          // If no consumer config, agent has all tools (falls back to default)
          if (!consumerConfig) {
            agentHasAllTools = true;
            break;
          }

          // If _type is "default-allow" with empty block array, agent has all tools
          if (
            consumerConfig._type === "default-allow" &&
            consumerConfig.block.length === 0
          ) {
            agentHasAllTools = true;
            break;
          }

          // If _type is "default-block" and allow array is empty, agent has 0 tools
          if (
            consumerConfig._type === "default-block" &&
            consumerConfig.allow.length === 0
          ) {
            agentHasEmptyAllow = true;
            continue;
          }

          // Collect tool group names from allow array (default-block)
          if (
            consumerConfig._type === "default-block" &&
            consumerConfig.allow.length > 0
          ) {
            consumerConfig.allow.forEach((groupName) =>
              assignedToolGroupNames.add(groupName),
            );
            agentHasToolGroups = true;
          }
        }

        if (agentHasAllTools) {
          hasAnyAgentWithAllTools = true;
        }
        if (!agentHasEmptyAllow || agentHasToolGroups) {
          allAgentsHaveEmptyAllow = false;
        }
      }

      // If any agent has all tools enabled, show all connected tools
      if (hasAnyAgentWithAllTools) {
        return connectedTools;
      }

      // If no tool groups assigned and all agents have empty allow arrays, return 0
      if (assignedToolGroupNames.size === 0) {
        return allAgentsHaveEmptyAllow ? 0 : connectedTools;
      }

      // Only count tools from servers that exist and are not inactive (deleted/inactive excluded)
      const activeServerNames = new Set(
        servers
          .filter(
            (s) =>
              appConfig?.targetServerAttributes?.[s.name]?.inactive !== true,
          )
          .map((s) => s.name),
      );

      const uniqueTools = new Set<string>();
      for (const groupName of assignedToolGroupNames) {
        const group = toolGroupByNameMap.get(groupName);
        if (!group?.services) continue;

        for (const [serverName, tools] of Object.entries(group.services)) {
          if (!activeServerNames.has(serverName)) continue;
          if (Array.isArray(tools)) {
            for (const tool of tools) {
              uniqueTools.add(tool);
            }
          }
        }
      }

      return uniqueTools.size;
    } catch (_error) {
      // Silently fallback to showing all connected tools on error
      return connectedTools;
    }
  }, [
    agents,
    servers,
    connectedTools,
    appConfig,
    toolGroupByNameMap,
    sessionIdToConsumerTagMap,
  ]);

  return useMemo(
    () => `${availableTools}/${connectedTools}`,
    [availableTools, connectedTools],
  );
};
