/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import { MCPServerStatus, type MCPServerConfig } from '@google/gemini-cli-core';
import { Box, Text } from 'ink';
import type React from 'react';
import { MAX_MCP_RESOURCES_TO_SHOW } from '../../constants.js';
import { theme } from '../../semantic-colors.js';
import type {
  HistoryItemMcpStatus,
  JsonMcpPrompt,
  JsonMcpResource,
  JsonMcpTool,
} from '../../types.js';

interface McpStatusProps {
  servers: Record<string, MCPServerConfig>;
  tools: JsonMcpTool[];
  prompts: JsonMcpPrompt[];
  resources: JsonMcpResource[];
  blockedServers: Array<{ name: string; extensionName: string }>;
  serverStatus: (serverName: string) => MCPServerStatus;
  authStatus: HistoryItemMcpStatus['authStatus'];
  enablementState: HistoryItemMcpStatus['enablementState'];
  errors: Record<string, string>;
  discoveryInProgress: boolean;
  connectingServers: string[];
  showDescriptions: boolean;
  showSchema: boolean;
}

export const McpStatus: React.FC<McpStatusProps> = ({
  servers,
  tools,
  prompts,
  resources,
  blockedServers,
  serverStatus,
  authStatus,
  enablementState,
  errors,
  discoveryInProgress,
  connectingServers,
  showDescriptions,
  showSchema,
}) => {
  const serverNames = Object.keys(servers).filter(
    (serverName) =>
      !blockedServers.some(
        (blockedServer) => blockedServer.name === serverName,
      ),
  );

  if (serverNames.length === 0 && blockedServers.length === 0) {
    return (
      <Box flexDirection="column">
        <Text>No MCP servers configured.</Text>
        <Text>
          Please view MCP documentation in your browser:{' '}
          <Text color={theme.text.link}>
            https://goo.gle/gemini-cli-docs-mcp
          </Text>{' '}
          or use the cli /docs command
        </Text>
      </Box>
    );
  }

  return (
    <Box flexDirection="column">
      {discoveryInProgress && (
        <Box flexDirection="column" marginBottom={1}>
          <Text color={theme.status.warning}>
            ⏳ MCP servers are starting up ({connectingServers.length}{' '}
            initializing)...
          </Text>
          <Text color={theme.text.primary}>
            Note: First startup may take longer. Tool availability will update
            automatically.
          </Text>
        </Box>
      )}

      <Text bold>Configured MCP servers:</Text>
      <Box height={1} />
      {serverNames.map((serverName) => {
        const server = servers[serverName];
        const serverTools = tools.filter(
          (tool) => tool.serverName === serverName,
        );
        const serverPrompts = prompts.filter(
          (prompt) => prompt.serverName === serverName,
        );
        const serverResources = resources.filter(
          (resource) => resource.serverName === serverName,
        );
        const originalStatus = serverStatus(serverName);
        const hasCachedItems =
          serverTools.length > 0 ||
          serverPrompts.length > 0 ||
          serverResources.length > 0;
        const status =
          originalStatus === MCPServerStatus.DISCONNECTED && hasCachedItems
            ? MCPServerStatus.CONNECTED
            : originalStatus;

        let statusIndicator = '';
        let statusText = '';
        let statusColor = theme.text.primary;

        // Check enablement state
        const serverEnablement = enablementState[serverName];
        const isDisabled = serverEnablement && !serverEnablement.enabled;

        if (isDisabled) {
          statusIndicator = '⏸️';
          statusText = serverEnablement.isSessionDisabled
            ? 'Disabled (session)'
            : 'Disabled';
          statusColor = theme.text.secondary;
        } else {
          switch (status) {
            case MCPServerStatus.CONNECTED:
              statusIndicator = '🟢';
              statusText = 'Ready';
              statusColor = theme.status.success;
              break;
            case MCPServerStatus.CONNECTING:
              statusIndicator = '🔄';
              statusText = 'Starting... (first startup may take longer)';
              statusColor = theme.status.warning;
              break;
            case MCPServerStatus.DISCONNECTED:
            default:
              statusIndicator = '🔴';
              statusText = 'Disconnected';
              statusColor = theme.status.error;
              break;
          }
        }

        let serverDisplayName = serverName;
        if (server.extension?.name) {
          serverDisplayName += ` (from ${server.extension?.name})`;
        }

        const toolCount = serverTools.length;
        const promptCount = serverPrompts.length;
        const resourceCount = serverResources.length;
        const parts = [];
        if (toolCount > 0) {
          parts.push(`${toolCount} ${toolCount === 1 ? 'tool' : 'tools'}`);
        }
        if (promptCount > 0) {
          parts.push(
            `${promptCount} ${promptCount === 1 ? 'prompt' : 'prompts'}`,
          );
        }
        if (resourceCount > 0) {
          parts.push(
            `${resourceCount} ${resourceCount === 1 ? 'resource' : 'resources'}`,
          );
        }

        const serverAuthStatus = authStatus[serverName];
        let authStatusNode: React.ReactNode = null;
        if (serverAuthStatus === 'authenticated') {
          authStatusNode = <Text> (OAuth)</Text>;
        } else if (serverAuthStatus === 'expired') {
          authStatusNode = (
            <Text color={theme.status.error}> (OAuth expired)</Text>
          );
        } else if (serverAuthStatus === 'unauthenticated') {
          authStatusNode = (
            <Text color={theme.status.warning}> (OAuth not authenticated)</Text>
          );
        }

        return (
          <Box key={serverName} flexDirection="column" marginBottom={1}>
            <Box>
              <Text color={statusColor}>{statusIndicator} </Text>
              <Text bold>{serverDisplayName}</Text>
              <Text>
                {' - '}
                {statusText}
                {status === MCPServerStatus.CONNECTED &&
                  parts.length > 0 &&
                  ` (${parts.join(', ')})`}
              </Text>
              {authStatusNode}
            </Box>
            {status === MCPServerStatus.CONNECTING && (
              <Text> (tools and prompts will appear when ready)</Text>
            )}
            {status === MCPServerStatus.DISCONNECTED && toolCount > 0 && (
              <Text> ({toolCount} tools cached)</Text>
            )}

            {errors[serverName] && (
              <Box marginLeft={2}>
                <Text color={theme.status.error}>
                  Error: {errors[serverName]}
                </Text>
              </Box>
            )}

            {showDescriptions && server?.description && (
              <Text color={theme.text.secondary}>
                {server.description.trim()}
              </Text>
            )}

            {serverTools.length > 0 && (
              <Box flexDirection="column" marginLeft={2}>
                <Text color={theme.text.primary}>Tools:</Text>
                {serverTools.map((tool) => {
                  const schemaContent =
                    showSchema &&
                    tool.schema &&
                    (tool.schema.parametersJsonSchema || tool.schema.parameters)
                      ? JSON.stringify(
                          tool.schema.parametersJsonSchema ??
                            tool.schema.parameters,
                          null,
                          2,
                        )
                      : null;

                  return (
                    <Box key={tool.name} flexDirection="column">
                      <Text>
                        - <Text color={theme.text.primary}>{tool.name}</Text>
                      </Text>
                      {showDescriptions && tool.description && (
                        <Box marginLeft={2}>
                          <Text color={theme.text.secondary}>
                            {tool.description.trim()}
                          </Text>
                        </Box>
                      )}
                      {schemaContent && (
                        <Box flexDirection="column" marginLeft={4}>
                          <Text color={theme.text.secondary}>Parameters:</Text>
                          <Text color={theme.text.secondary}>
                            {schemaContent}
                          </Text>
                        </Box>
                      )}
                    </Box>
                  );
                })}
              </Box>
            )}

            {serverPrompts.length > 0 && (
              <Box flexDirection="column" marginLeft={2}>
                <Text color={theme.text.primary}>Prompts:</Text>
                {serverPrompts.map((prompt) => (
                  <Box key={prompt.name} flexDirection="column">
                    <Text>
                      - <Text color={theme.text.primary}>{prompt.name}</Text>
                    </Text>
                    {showDescriptions && prompt.description && (
                      <Box marginLeft={2}>
                        <Text color={theme.text.primary}>
                          {prompt.description.trim()}
                        </Text>
                      </Box>
                    )}
                  </Box>
                ))}
              </Box>
            )}

            {serverResources.length > 0 && (
              <Box flexDirection="column" marginLeft={2}>
                <Text color={theme.text.primary}>Resources:</Text>
                {serverResources
                  .slice(0, MAX_MCP_RESOURCES_TO_SHOW)
                  .map((resource, index) => {
                    const label = resource.name || resource.uri || 'resource';
                    return (
                      <Box
                        key={`${resource.serverName}-resource-${index}`}
                        flexDirection="column"
                      >
                        <Text>
                          - <Text color={theme.text.primary}>{label}</Text>
                          {resource.uri ? ` (${resource.uri})` : ''}
                          {resource.mimeType ? ` [${resource.mimeType}]` : ''}
                        </Text>
                        {showDescriptions && resource.description && (
                          <Box marginLeft={2}>
                            <Text color={theme.text.secondary}>
                              {resource.description.trim()}
                            </Text>
                          </Box>
                        )}
                      </Box>
                    );
                  })}
                {serverResources.length > MAX_MCP_RESOURCES_TO_SHOW && (
                  <Text color={theme.text.secondary}>
                    {'  '}...{' '}
                    {serverResources.length - MAX_MCP_RESOURCES_TO_SHOW}{' '}
                    {serverResources.length - MAX_MCP_RESOURCES_TO_SHOW === 1
                      ? 'resource'
                      : 'resources'}{' '}
                    hidden
                  </Text>
                )}
              </Box>
            )}
          </Box>
        );
      })}

      {blockedServers.map((server) => (
        <Box key={server.name} marginBottom={1}>
          <Text color={theme.status.error}>🔴 </Text>
          <Text bold>
            {server.name}
            {server.extensionName ? ` (from ${server.extensionName})` : ''}
          </Text>
          <Text> - Blocked</Text>
        </Box>
      ))}
    </Box>
  );
};
