export interface McpFeatureGroup {
  id: string
  name: string
  description: string
}

export type McpOnCopyCallback = 'url' | 'config' | 'command'

export interface McpClientDeepLinkOptions {
  isPlatform?: boolean
}

export interface McpClientInstructionOptions {
  isPlatform?: boolean
}

export interface McpClient {
  key: string
  label: string
  icon?: string
  /** When true, use -icon-dark.svg in dark theme; otherwise the same -icon.svg is used for both themes. */
  hasDistinctDarkIcon?: boolean
  docsUrl?: string
  externalDocsUrl?: string
  configFile?: string
  generateDeepLink?: (config: McpClientConfig, options?: McpClientDeepLinkOptions) => string | null
  transformConfig?: (config: McpClientBaseConfig) => McpClientConfig
  /** Optional custom description shown above the deep link button generated by generateDeepLink */
  deepLinkDescription?: React.ReactNode
  primaryInstructions?: (
    config: McpClientConfig,
    onCopy: (type?: McpOnCopyCallback) => void,
    options?: McpClientInstructionOptions
  ) => React.ReactNode
  alternateInstructions?: (
    config: McpClientConfig,
    onCopy: (type?: McpOnCopyCallback) => void,
    options?: McpClientInstructionOptions
  ) => React.ReactNode
}

export interface McpUrlBuilderConfig {
  projectRef: string
  readonly?: boolean
  features?: string[]
}

export interface McpClientBaseConfig {
  mcpServers: {
    briven: {
      url: string
    }
  }
}

export interface CursorMcpConfig extends McpClientBaseConfig {}

export interface VSCodeMcpConfig {
  servers: {
    briven: {
      type: 'http'
      url: string
    }
  }
}

export interface WindsurfMcpConfig {
  mcpServers: {
    briven: {
      command: 'npx'
      args: ['-y', 'mcp-remote', string]
    }
  }
}

export interface ClaudeCodeMcpConfig extends McpClientBaseConfig {
  mcpServers: {
    briven: {
      type: 'http'
      url: string
    }
  }
}

export interface ClaudeDesktopMcpConfig extends McpClientBaseConfig {
  mcpServers: {
    briven: {
      type: 'http'
      url: string
    }
  }
}

export interface OtherMcpConfig extends McpClientBaseConfig {
  mcpServers: {
    briven: {
      type: 'http'
      url: string
    }
  }
}

export interface GooseMcpConfig {
  extensions: {
    briven: {
      available_tools: string[]
      bundled: null
      description: string
      enabled: boolean
      env_keys: string[]
      envs: Record<string, string>
      headers: Record<string, string>
      name: string
      timeout: number
      type: 'streamable_http'
      uri: string
    }
  }
}

export interface FactoryMcpConfig extends McpClientBaseConfig {
  mcpServers: {
    briven: {
      type: 'http'
      url: string
    }
  }
}

export interface CodexMcpConfig {
  mcp_servers: {
    briven: {
      url: string
    }
  }
}

/**
 * Configuration format for Gemini CLI MCP client.
 * Uses httpUrl instead of url to match Gemini CLI's expected format.
 */
export interface GeminiMcpConfig {
  mcpServers: {
    briven: {
      httpUrl: string
    }
  }
}

export interface OpenCodeMcpConfig {
  $schema: string
  mcp: {
    briven: {
      type: 'remote'
      url: string
      enabled?: boolean
    }
  }
}

export interface AntigravityMcpConfig {
  mcpServers: {
    briven: {
      serverUrl: string
    }
  }
}

export interface CopilotMcpConfig extends McpClientBaseConfig {
  mcpServers: {
    briven: {
      type: 'http'
      url: string
    }
  }
}

// Union of all possible config types
export type McpClientConfig =
  | AntigravityMcpConfig
  | ClaudeCodeMcpConfig
  | CopilotMcpConfig
  | ClaudeDesktopMcpConfig
  | CodexMcpConfig
  | CursorMcpConfig
  | FactoryMcpConfig
  | GeminiMcpConfig
  | GooseMcpConfig
  | McpClientBaseConfig
  | OpenCodeMcpConfig
  | OtherMcpConfig
  | VSCodeMcpConfig
  | WindsurfMcpConfig

// Type guards
export function isVSCodeMcpConfig(config: McpClientConfig): config is VSCodeMcpConfig {
  return 'servers' in config && 'briven' in config.servers
}

export function isGooseMcpConfig(config: McpClientConfig): config is GooseMcpConfig {
  return 'extensions' in config && 'briven' in config.extensions
}

export function isCodexMcpConfig(config: McpClientConfig): config is CodexMcpConfig {
  return 'mcp_servers' in config && 'briven' in config.mcp_servers
}

export function isGeminiMcpConfig(config: McpClientConfig): config is GeminiMcpConfig {
  return (
    'mcpServers' in config &&
    'briven' in config.mcpServers &&
    'httpUrl' in config.mcpServers.briven
  )
}

export function isOpenCodeMcpConfig(config: McpClientConfig): config is OpenCodeMcpConfig {
  return '$schema' in config && 'mcp' in config && 'briven' in config.mcp
}

export function isAntigravityMcpConfig(config: McpClientConfig): config is AntigravityMcpConfig {
  return (
    'mcpServers' in config &&
    'briven' in config.mcpServers &&
    'serverUrl' in config.mcpServers.briven
  )
}

export function isMcpServersConfig(
  config: McpClientConfig
): config is McpClientBaseConfig | ClaudeCodeMcpConfig | FactoryMcpConfig {
  return 'mcpServers' in config && 'briven' in config.mcpServers
}

// Helper to extract MCP URL from any config type
export function getMcpUrl(config: McpClientConfig): string {
  if (isVSCodeMcpConfig(config)) {
    return config.servers.briven.url
  }
  if (isGooseMcpConfig(config)) {
    return config.extensions.briven.uri
  }
  if (isCodexMcpConfig(config)) {
    return config.mcp_servers.briven.url
  }
  if (isGeminiMcpConfig(config)) {
    return config.mcpServers.briven.httpUrl
  }
  if (isOpenCodeMcpConfig(config)) {
    return config.mcp.briven.url
  }
  if (isAntigravityMcpConfig(config)) {
    return config.mcpServers.briven.serverUrl
  }
  if (isMcpServersConfig(config)) {
    return config.mcpServers.briven.url
  }
  throw new Error('Invalid MCP config type')
}
