// Frontend MCP client that communicates with Electron main process
// This replaces the direct MCP client import to avoid spawn issues in renderer process

interface MCPTool {
  name: string;
  description?: string;
  inputSchema?: any;
  server?: string; // Add server information
}

interface MCPResponse {
  success: boolean;
  tools?: MCPTool[];
  result?: any;
  error?: string;
  toolCallId?: string;
}

interface ElectronMCPApi {
  getTools: () => Promise<MCPResponse>;
  executeTool: (
    toolName: string,
    args: Record<string, any>,
    toolCallId?: string
  ) => Promise<MCPResponse>;
  getStatus: () => Promise<{ isInitialized: boolean; hasClient: boolean }>;
  resetClient: () => Promise<MCPResponse>;
  getConfig: () => Promise<{ success: boolean; config?: any; error?: string }>;
  updateConfig: (config: any) => Promise<MCPResponse>;
  getToolsConfig: () => Promise<{ success: boolean; config?: any; error?: string }>;
  updateToolsConfig: (config: any) => Promise<MCPResponse>;
  setToolEnabled: (serverName: string, toolName: string, enabled: boolean) => Promise<MCPResponse>;
  getToolStats: (
    serverName: string,
    toolName: string
  ) => Promise<{ success: boolean; stats?: any; error?: string }>;
}

// desktopApi is already declared on Window by @kinvolk/headlamp-plugin as `any`.
// We use a helper to access it with proper typing.
function getDesktopMCPApi(): ElectronMCPApi | undefined {
  const api = (window as any).desktopApi;
  if (api && typeof api.mcp !== 'undefined') {
    return api.mcp as ElectronMCPApi;
  }
  return undefined;
}
// Type augmentation is handled by src/types/electron.d.ts

class ElectronMCPClient {
  private isElectron: boolean;

  constructor() {
    this.isElectron = typeof window !== 'undefined' && getDesktopMCPApi() !== undefined;
  }

  /**
   * Check if running in Electron environment with MCP support
   */
  isAvailable(): boolean {
    return this.isElectron;
  }

  /**
   * Get available MCP tools from Electron main process
   */
  async getTools(): Promise<MCPTool[]> {
    if (!this.isElectron) {
      console.warn('MCP client not available - not running in Electron environment');
      return [];
    }

    try {
      const mcpApi = getDesktopMCPApi()!;
      const response = await mcpApi.getTools();
      console.log('mcp response from getting tools is', response);
      console.log('mcp window desktop api', mcpApi.getTools);
      if (response.success && response.tools) {
        console.log('Retrieved MCP tools from Electron:', response.tools.length, 'tools');
        return response.tools;
      } else {
        console.warn('Failed to get MCP tools:', response.error);
        return [];
      }
    } catch (error) {
      console.error('Error getting MCP tools from Electron:', error);
      return [];
    }
  }

  /**
   * Execute an MCP tool via Electron main process
   */
  async executeTool(
    toolName: string,
    args: Record<string, any>,
    toolCallId?: string
  ): Promise<any> {
    if (!this.isElectron) {
      throw new Error('MCP client not available - not running in Electron environment');
    }

    try {
      console.debug('args for tool executed is ', args);
      const response = await getDesktopMCPApi()!.executeTool(toolName, args, toolCallId);

      if (response.success) {
        return response.result;
      } else {
        throw new Error(response.error || 'Unknown error executing MCP tool');
      }
    } catch (error) {
      console.error(`Error executing MCP tool ${toolName}:`, error);
      throw error;
    }
  }

  /**
   * Get MCP client status from Electron main process
   */
  async getStatus(): Promise<{ isInitialized: boolean; hasClient: boolean }> {
    if (!this.isElectron) {
      return { isInitialized: false, hasClient: false };
    }

    try {
      return await getDesktopMCPApi()!.getStatus();
    } catch (error) {
      console.error('Error getting MCP status:', error);
      return { isInitialized: false, hasClient: false };
    }
  }

  /**
   * Reset/restart MCP client in Electron main process
   */
  async resetClient(): Promise<boolean> {
    if (!this.isElectron) {
      return false;
    }

    try {
      const response = await getDesktopMCPApi()!.resetClient();
      return response.success;
    } catch (error) {
      console.error('Error resetting MCP client:', error);
      return false;
    }
  }

  /**
   * Get MCP configuration from Electron main process
   */
  async getConfig(): Promise<{ success: boolean; config?: any; error?: string }> {
    if (!this.isElectron) {
      return {
        success: false,
        error: 'MCP client not available - not running in Electron environment',
      };
    }

    try {
      const response = await window.desktopApi!.mcp.getConfig();
      return response;
    } catch (error) {
      console.error('Error getting MCP config:', error);
      return { success: false, error: String(error) };
    }
  }

  /**
   * Get MCP tools configuration from Electron main process
   */
  async getToolsConfig(): Promise<{ success: boolean; config?: any; error?: string }> {
    if (!this.isElectron) {
      return {
        success: false,
        error: 'MCP client not available - not running in Electron environment',
      };
    }

    try {
      const response = await window.desktopApi!.mcp.getToolsConfig();
      return response;
    } catch (error) {
      console.error('Error getting MCP tools config:', error);
      return { success: false, error: String(error) };
    }
  }

  /**
   * Update MCP tools configuration in Electron main process
   */
  async updateToolsConfig(config: any): Promise<boolean> {
    if (!this.isElectron) {
      return false;
    }

    try {
      const response = await window.desktopApi!.mcp.updateToolsConfig(config);
      console.debug('response from updating mcp tools config is ', response);
      return response.success;
    } catch (error) {
      console.error('Error updating MCP tools config:', error);
      return false;
    }
  }

  /**
   * Enable or disable a specific MCP tool
   */
  async setToolEnabled(serverName: string, toolName: string, enabled: boolean): Promise<boolean> {
    if (!this.isElectron) {
      return false;
    }

    try {
      const response = await window.desktopApi!.mcp.setToolEnabled(serverName, toolName, enabled);
      return response.success;
    } catch (error) {
      console.error('Error setting tool enabled state:', error);
      return false;
    }
  }

  /**
   * Get tool statistics for a specific MCP tool
   */
  async getToolStats(serverName: string, toolName: string): Promise<any | null> {
    if (!this.isElectron) {
      return null;
    }

    try {
      const response = await window.desktopApi!.mcp.getToolStats(serverName, toolName);
      return response.success ? response.stats : null;
    } catch (error) {
      console.error('Error getting tool stats:', error);
      return null;
    }
  }

  /**
   * Parse MCP tool name to extract server and tool components
   * Format: "serverName__toolName"
   */
  parseToolName(fullToolName: string): { serverName: string; toolName: string } {
    const parts = fullToolName.split('__');
    if (parts.length >= 2) {
      return {
        serverName: parts[0],
        toolName: parts.slice(1).join('__'),
      };
    }
    return {
      serverName: 'default',
      toolName: fullToolName,
    };
  }

  /**
   * Check if a specific tool is enabled
   */
  async isToolEnabled(fullToolName: string): Promise<boolean> {
    if (!this.isElectron) {
      return true; // Default to enabled if not in Electron
    }

    try {
      const { serverName, toolName } = this.parseToolName(fullToolName);
      const toolsConfig = await this.getToolsConfig();

      if (!toolsConfig.success || !toolsConfig.config) {
        return true; // Default to enabled if config not available
      }

      const serverConfig = toolsConfig.config[serverName];
      if (!serverConfig || !serverConfig[toolName]) {
        return true; // Default to enabled for new tools
      }

      return serverConfig[toolName].enabled;
    } catch (error) {
      console.error('Error checking tool enabled state:', error);
      return true; // Default to enabled on error
    }
  }

  /**
   * Get all enabled MCP tools
   */
  async getEnabledTools(): Promise<MCPTool[]> {
    if (!this.isElectron) {
      return [];
    }

    try {
      const toolsConfigResponse = await this.getToolsConfig();
      if (!toolsConfigResponse.success || !toolsConfigResponse.config) {
        return [];
      }

      const enabledTools: MCPTool[] = [];
      for (const [serverName, serverTools] of Object.entries(toolsConfigResponse.config)) {
        for (const [toolName, toolConfig] of Object.entries(serverTools as Record<string, any>)) {
          if (toolConfig.enabled !== false) {
            enabledTools.push({
              name: `${serverName}__${toolName}`,
              description: toolConfig.description,
              inputSchema: toolConfig.inputSchema,
              server: serverName,
            });
          }
        }
      }

      return enabledTools;
    } catch (error) {
      console.error('Error getting enabled tools:', error);
      return [];
    }
  }
}

// Export a function that returns tools (compatible with existing interface)
const tools = async function (): Promise<MCPTool[]> {
  const client = new ElectronMCPClient();
  return (await client.getToolsConfig()).config;
};

// Export both the client class and the tools function for flexibility
export { ElectronMCPClient };
export default tools;
