import React, { useState, useEffect, useRef, useCallback } from "react"
import { Button } from "@renderer/components/ui/button"
import { Input } from "@renderer/components/ui/input"
import { Label } from "@renderer/components/ui/label"
import { Textarea } from "@renderer/components/ui/textarea"
import { Switch } from "@renderer/components/ui/switch"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@renderer/components/ui/card"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@renderer/components/ui/dialog"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@renderer/components/ui/dropdown-menu"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@renderer/components/ui/select"
import { Badge } from "@renderer/components/ui/badge"
import {
  Trash2,
  Edit,
  Plus,
  Upload,
  Download,
  Server,
  CheckCircle,
  XCircle,
  AlertCircle,
  BookOpen,
  RotateCcw,
  Square,
  Play,
  ExternalLink,
  FileText,
  ChevronDown,
  ChevronUp,
  ChevronRight,
  ChevronsUpDown,
  Terminal,
  Trash,
  Search,
  Eye,
  EyeOff,
  Power,
  PowerOff,
  Wrench,
  MoreHorizontal,
} from "lucide-react"
import { Spinner } from "@renderer/components/ui/spinner"
import { MCPConfig, MCPServerConfig, MCPTransportType, OAuthConfig, ServerLogEntry, DetailedToolInfo } from "@shared/types"
import { RESERVED_RUNTIME_TOOL_SERVER_NAMES } from "@shared/runtime-tool-names"
import { tipcClient } from "@renderer/lib/tipc-client"
import { toast } from "sonner"
import { OAuthServerConfig } from "./OAuthServerConfig"
import { OAUTH_MCP_EXAMPLES } from "@shared/oauth-examples"
import { parseShellCommand } from "@dotagents/shared"



type DetailedTool = DetailedToolInfo



interface MCPConfigManagerProps {
  config: MCPConfig
  onConfigChange: (config: MCPConfig) => void
  // UI state persistence for collapsed/expanded sections
  collapsedToolServers?: string[]
  collapsedServers?: string[]
  onCollapsedToolServersChange?: (servers: string[]) => void
  onCollapsedServersChange?: (servers: string[]) => void
}

interface ServerDialogProps {
  server?: { name: string; config: MCPServerConfig }
  onSave: (name: string, config: MCPServerConfig) => void
  onCancel: () => void
  // Import functionality props (only needed for Add mode, not Edit mode)
  onImportFromFile?: () => Promise<void>
  // Returns true on success, false on failure (to preserve user input on errors)
  onImportFromText?: (text: string) => Promise<boolean>
  // Used to trigger state reset when dialog opens/closes (for Add mode where server prop doesn't change)
  isOpen?: boolean
}

// Reserved internal server aliases that cannot be used by user-defined MCP servers.
const RESERVED_SERVER_NAMES = [...RESERVED_RUNTIME_TOOL_SERVER_NAMES]

function ServerDialog({ server, onSave, onCancel, onImportFromFile, onImportFromText, isOpen }: ServerDialogProps) {
  const [name, setName] = useState(server?.name || "")
  // Default to 'examples' tab when adding a new server, 'manual' when editing
  const [activeTab, setActiveTab] = useState<'manual' | 'file' | 'paste' | 'examples'>(server ? 'manual' : 'examples')
  const [jsonInputText, setJsonInputText] = useState("")
  const [isValidatingJson, setIsValidatingJson] = useState(false)
  const [transport, setTransport] = useState<MCPTransportType>(
    server?.config.transport || "stdio",
  )
  const [fullCommand, setFullCommand] = useState(() => {
    if (server?.config.command) {
      const cmd = server.config.command
      const args = server.config.args ? server.config.args.join(" ") : ""
      return args ? `${cmd} ${args}` : cmd
    }
    return ""
  })
  const [url, setUrl] = useState(server?.config.url || "")
  const [env, setEnv] = useState(
    server?.config.env
      ? Object.entries(server.config.env)
          .map(([k, v]) => `${k}=${v}`)
          .join("\n")
      : "",
  )
  const [timeout, setTimeout] = useState(
    server?.config.timeout?.toString() || "",
  )
  const [selectedExample, setSelectedExample] = useState<string>("")
  const [disabled, setDisabled] = useState(server?.config.disabled || false)
  const [headers, setHeaders] = useState(
    server?.config.headers
      ? Object.entries(server.config.headers)
          .map(([k, v]) => `${k}=${v}`)
          .join("\n")
      : "",
  )
  const [oauthConfig, setOAuthConfig] = useState<OAuthConfig>(
    server?.config.oauth || {}
  )
  // OAuth configuration is automatically shown for streamableHttp transport

  // Reset all fields when server prop changes (e.g., when switching from edit to add)
  useEffect(() => {
    setName(server?.name || "")
    // Default to 'examples' tab when adding a new server, 'manual' when editing
    setActiveTab(server ? 'manual' : 'examples')
    setJsonInputText("")  // Clear pasted JSON to prevent data/secrets from persisting across dialog close/open
    setTransport(server?.config.transport || "stdio")

    // Combine command and args for editing, or reset to empty
    if (server?.config.command) {
      const cmd = server.config.command
      const args = server.config.args ? server.config.args.join(" ") : ""
      setFullCommand(args ? `${cmd} ${args}` : cmd)
    } else {
      setFullCommand("")
    }

    setUrl(server?.config.url || "")
    setEnv(
      server?.config.env
        ? Object.entries(server.config.env)
            .map(([k, v]) => `${k}=${v}`)
            .join("\n")
        : ""
    )
    setTimeout(server?.config.timeout?.toString() || "")
    setSelectedExample("")
    setDisabled(server?.config.disabled || false)
    setHeaders(
      server?.config.headers
        ? Object.entries(server.config.headers)
            .map(([k, v]) => `${k}=${v}`)
            .join("\n")
        : ""
    )
    setOAuthConfig(server?.config.oauth || {})
  }, [server])

  // Reset all form state when dialog opens or closes (for Add mode where server prop stays undefined)
  // This ensures sensitive data (JSON, env vars, headers, OAuth secrets) is cleared after Cancel/close
  // and prevents stale values from flashing when the dialog reopens
  useEffect(() => {
    if (!server) {
      // Only reset for Add mode (server is undefined)
      // Edit mode is handled by the server dependency useEffect above
      setName("")
      setActiveTab('examples')  // Default to 'examples' tab when adding a new server
      setJsonInputText("")
      setIsValidatingJson(false) // Reset validation state to prevent UI getting stuck
      setTransport("stdio")
      setFullCommand("")
      setUrl("")
      setEnv("")
      setTimeout("")
      setSelectedExample("")
      setDisabled(false)
      setHeaders("")
      setOAuthConfig({})
    }
  }, [isOpen, server])

  const handleSave = () => {
    if (!name.trim()) {
      toast.error("Server name is required")
      return
    }

    // Check for reserved server names
    if (RESERVED_SERVER_NAMES.includes(name.trim().toLowerCase())) {
      toast.error(`Server name "${name.trim()}" is reserved and cannot be used`)
      return
    }

    // Validate based on transport type
    if (transport === "stdio") {
      if (!fullCommand.trim()) {
        toast.error("Command is required for stdio transport")
        return
      }
    } else if (transport === "websocket" || transport === "streamableHttp") {
      if (!url.trim()) {
        toast.error("URL is required for remote transport")
        return
      }
      // Basic URL validation
      try {
        new URL(url.trim())
      } catch (error) {
        toast.error("Invalid URL format")
        return
      }
    }

    const envObject: Record<string, string> = {}
    if (env.trim()) {
      try {
        env.split("\n").forEach((line) => {
          const [key, ...valueParts] = line.split("=")
          if (key && valueParts.length > 0) {
            envObject[key.trim()] = valueParts.join("=").trim()
          }
        })
      } catch (error) {
        toast.error("Invalid environment variables format")
        return
      }
    }

    const headersObject: Record<string, string> = {}
    if (headers.trim()) {
      try {
        headers.split("\n").forEach((line) => {
          const [key, ...valueParts] = line.split("=")
          if (key && valueParts.length > 0) {
            headersObject[key.trim()] = valueParts.join("=").trim()
          }
        })
      } catch (error) {
        toast.error("Invalid headers format")
        return
      }
    }

    // Parse the full command into command and args
    let parsedCommand = ""
    let parsedArgs: string[] = []
    if (transport === "stdio" && fullCommand.trim()) {
      const parsed = parseShellCommand(fullCommand.trim())
      parsedCommand = parsed.command
      parsedArgs = parsed.args
    }

    const serverConfig: MCPServerConfig = {
      transport,
      ...(transport === "stdio" && {
        command: parsedCommand,
        args: parsedArgs,
      }),
      ...(transport !== "stdio" && {
        url: url.trim(),
      }),
      ...(Object.keys(envObject).length > 0 && { env: envObject }),
      ...(transport === "streamableHttp" && Object.keys(headersObject).length > 0 && { headers: headersObject }),
      ...(timeout && { timeout: parseInt(timeout) }),
      ...(disabled && { disabled }),
      ...(transport === "streamableHttp" && Object.keys(oauthConfig).length > 0 && { oauth: oauthConfig }),
    }

    onSave(name.trim(), serverConfig)
  }

  return (
    <DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
      <DialogHeader>
        <DialogTitle>{server ? "Edit Server" : "Add Server"}</DialogTitle>
        <DialogDescription>
          Add or configure an MCP server
        </DialogDescription>
      </DialogHeader>

      <div className="w-full">
        <div className="flex space-x-1 mb-4">
          <Button
            variant={activeTab === 'manual' ? 'default' : 'outline'}
            onClick={() => setActiveTab('manual')}
            className="flex-1"
            size="sm"
          >
            Manual
          </Button>
          {/* Only show import tabs when adding a new server (not editing) */}
          {!server && onImportFromFile && (
            <Button
              variant={activeTab === 'file' ? 'default' : 'outline'}
              onClick={() => setActiveTab('file')}
              className="flex-1 gap-1"
              size="sm"
            >
              <Upload className="h-3 w-3" />
              From File
            </Button>
          )}
          {!server && onImportFromText && (
            <Button
              variant={activeTab === 'paste' ? 'default' : 'outline'}
              onClick={() => setActiveTab('paste')}
              className="flex-1 gap-1"
              size="sm"
            >
              <FileText className="h-3 w-3" />
              Paste JSON
            </Button>
          )}
          <Button
            variant={activeTab === 'examples' ? 'default' : 'outline'}
            onClick={() => setActiveTab('examples')}
            className="flex-1"
            size="sm"
          >
            Examples
          </Button>
        </div>

        {/* Manual Configuration Tab */}
        {activeTab === 'manual' && (
          <div className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="server-name">Server Name</Label>
              <Input
                id="server-name"
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder="e.g., google-maps"
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="transport">Transport Type</Label>
              <Select
                value={transport}
                onValueChange={(value: MCPTransportType) => setTransport(value)}
              >
                <SelectTrigger id="transport" className="border border-primary/40">
                  <SelectValue placeholder="Select transport type" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="stdio">Local Command (stdio)</SelectItem>
                  <SelectItem value="websocket">WebSocket</SelectItem>
                  <SelectItem value="streamableHttp">Streamable HTTP</SelectItem>
                </SelectContent>
              </Select>
              <p className="text-xs text-muted-foreground">
                Choose how to connect to the MCP server
              </p>
            </div>

            {transport === "stdio" ? (
              <div className="space-y-2">
                <Label htmlFor="fullCommand">Command</Label>
                <Input
                  id="fullCommand"
                  value={fullCommand}
                  onChange={(e) => setFullCommand(e.target.value)}
                  placeholder="e.g., npx -y @modelcontextprotocol/server-google-maps"
                />
                <p className="text-xs text-muted-foreground">
                  Full command with arguments (space-separated)
                </p>
              </div>
            ) : (
              <div className="space-y-2">
                <Label htmlFor="url">Server URL</Label>
                <Input
                  id="url"
                  value={url}
                  onChange={(e) => setUrl(e.target.value)}
                  placeholder={
                    transport === "websocket"
                      ? "ws://localhost:8080"
                      : "http://localhost:8080"
                  }
                />
                <p className="text-xs text-muted-foreground">
                  {transport === "websocket"
                    ? "WebSocket URL (e.g., ws://localhost:8080 or wss://example.com/mcp)"
                    : "HTTP URL for streamable HTTP transport (e.g., http://localhost:8080/mcp)"}
                </p>
              </div>
            )}

            {/* Custom Headers - only shown for streamableHttp transport */}
            {transport === "streamableHttp" && (
              <div className="space-y-2">
                <Label htmlFor="headers">Custom HTTP Headers</Label>
                <Textarea
                  id="headers"
                  value={headers}
                  onChange={(e) => setHeaders(e.target.value)}
                  placeholder="X-API-Key=your-api-key&#10;User-Agent=MyApp/1.0&#10;Content-Type=application/json"
                  rows={4}
                />
                <p className="text-xs text-muted-foreground">
                  One per line in Header-Name=value format. These headers will be included in all HTTP requests to the server.
                </p>
              </div>
            )}

            <div className="space-y-2">
              <Label htmlFor="env">Environment Variables</Label>
              <Textarea
                id="env"
                value={env}
                onChange={(e) => setEnv(e.target.value)}
                placeholder="API_KEY=your-key-here&#10;ANOTHER_VAR=value"
                rows={4}
              />
              <p className="text-xs text-muted-foreground">
                One per line in KEY=value format
              </p>
            </div>

            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label htmlFor="timeout">Timeout (ms)</Label>
                <Input
                  id="timeout"
                  type="number"
                  value={timeout}
                  onChange={(e) => setTimeout(e.target.value)}
                  placeholder="60000"
                />
              </div>

              <div className="flex items-center space-x-2 pt-6">
                <Switch
                  id="disabled"
                  checked={disabled}
                  onCheckedChange={setDisabled}
                />
                <Label htmlFor="disabled">Disabled</Label>
              </div>
            </div>

            {/* OAuth Configuration - automatically shown for streamableHttp transport */}
            {transport === "streamableHttp" && url && (
              <OAuthServerConfig
                serverName={name || "New Server"}
                serverUrl={url}
                oauthConfig={oauthConfig}
                onConfigChange={setOAuthConfig}
                onStartAuth={async () => {
                  if (!name) {
                    toast.error("Please save the server configuration first")
                    return
                  }
                  try {
                    await window.electronAPI.initiateOAuthFlow(name)
                    toast.success("OAuth authentication started. Please complete the flow in your browser.")
                  } catch (error) {
                    toast.error(`Failed to start OAuth flow: ${error instanceof Error ? error.message : String(error)}`)
                  }
                }}
                onRevokeAuth={async () => {
                  if (!name) return
                  try {
                    await window.electronAPI.revokeOAuthTokens(name)
                    toast.success("OAuth tokens revoked successfully")
                  } catch (error) {
                    toast.error(`Failed to revoke OAuth tokens: ${error instanceof Error ? error.message : String(error)}`)
                  }
                }}
                onTestConnection={async () => {
                  if (!name) {
                    toast.error("Please save the server configuration first")
                    return
                  }
                  try {
                    // Create server config for testing
                    const envObject: Record<string, string> = {}
                    if (env.trim()) {
                      env.split("\n").forEach((line) => {
                        const [key, ...valueParts] = line.split("=")
                        if (key && valueParts.length > 0) {
                          envObject[key.trim()] = valueParts.join("=").trim()
                        }
                      })
                    }

                    const headersObject: Record<string, string> = {}
                    if (headers.trim()) {
                      headers.split("\n").forEach((line) => {
                        const [key, ...valueParts] = line.split("=")
                        if (key && valueParts.length > 0) {
                          headersObject[key.trim()] = valueParts.join("=").trim()
                        }
                      })
                    }

                    const testServerConfig: MCPServerConfig = { transport }

                    if ((transport as string) === "stdio") {
                      const parsed = parseShellCommand(fullCommand.trim())
                      testServerConfig.command = parsed.command
                      testServerConfig.args = parsed.args
                    } else {
                      testServerConfig.url = url.trim()
                    }

                    if (Object.keys(envObject).length > 0) {
                      testServerConfig.env = envObject
                    }
                    if (transport === "streamableHttp" && Object.keys(headersObject).length > 0) {
                      testServerConfig.headers = headersObject
                    }
                    if (timeout) {
                      testServerConfig.timeout = parseInt(timeout)
                    }
                    if (disabled) {
                      testServerConfig.disabled = disabled
                    }
                    if (transport === "streamableHttp" && Object.keys(oauthConfig).length > 0) {
                      testServerConfig.oauth = oauthConfig
                    }

                    const result = await window.electronAPI.testMCPServer(name, testServerConfig)
                    if (result.success) {
                      toast.success("Connection test successful!")
                    } else {
                      toast.error(`Connection test failed: ${result.error}`)
                    }
                  } catch (error) {
                    toast.error(`Connection test failed: ${error instanceof Error ? error.message : String(error)}`)
                  }
                }}
              />
            )}
          </div>
        )}

        {/* From File Tab */}
        {activeTab === 'file' && onImportFromFile && (
          <div className="space-y-4">
            <div className="border-2 border-dashed border-border rounded-lg p-8 text-center">
              <Upload className="mx-auto h-12 w-12 text-muted-foreground mb-4" />
              <h3 className="text-lg font-medium mb-2">Import from JSON file</h3>
              <p className="text-sm text-muted-foreground mb-4">
                Select a JSON file containing MCP server configurations
              </p>
              <Button onClick={async () => {
                await onImportFromFile()
              }}>
                Choose File
              </Button>
            </div>
          </div>
        )}

        {/* Paste JSON Tab */}
        {activeTab === 'paste' && onImportFromText && (
          <div className="space-y-4">
            <div className="space-y-2">
              <div className="flex items-center justify-between">
                <Label htmlFor="json-text-dialog">Paste JSON Configuration</Label>
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => {
                    try {
                      const formatted = JSON.stringify(JSON.parse(jsonInputText), null, 2)
                      setJsonInputText(formatted)
                    } catch {
                      // Ignore formatting errors
                    }
                  }}
                  disabled={!jsonInputText.trim()}
                >
                  Format
                </Button>
              </div>
              <Textarea
                id="json-text-dialog"
                value={jsonInputText}
                onChange={(e) => setJsonInputText(e.target.value)}
                placeholder='{
  "mcpServers": {
    "server-name": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-name"]
    }
  }
}'
                rows={12}
                className="font-mono text-sm whitespace-pre"
              />
              <p className="text-xs text-muted-foreground">
                Paste valid JSON configuration. New servers will be merged. Duplicate names will be replaced by imported versions.
              </p>
            </div>
            <Button
              onClick={async () => {
                setIsValidatingJson(true)
                try {
                  const success = await onImportFromText(jsonInputText)
                  // Only clear input on successful import to preserve user input on errors
                  if (success) {
                    setJsonInputText("")
                  }
                } finally {
                  setIsValidatingJson(false)
                }
              }}
              disabled={isValidatingJson || !jsonInputText.trim()}
              className="w-full gap-2"
            >
              {isValidatingJson ? (
                <>
                  <Spinner className="h-4 w-4" />
                  Validating...
                </>
              ) : (
                "Import Configuration"
              )}
            </Button>
          </div>
        )}

        {/* Examples Tab */}
        {activeTab === 'examples' && (
          <div className="space-y-4">
            <div className="text-sm text-muted-foreground mb-4">
              Choose from popular MCP server configurations to get started quickly.
            </div>

            <div className="space-y-3 max-h-96 overflow-y-auto">
              {/* Standard MCP Examples */}
              <div className="space-y-2">
                <h4 className="font-medium text-sm">Standard MCP Servers</h4>
                {Object.entries(MCP_EXAMPLES).map(([key, example]) => (
                  <Card key={key} className="p-3">
                    <div className="flex items-start justify-between">
                      <div className="flex-1">
                        <h5 className="font-medium text-sm">{example.name}</h5>
                        <p className="text-xs text-muted-foreground mt-1">
                          {example.config.transport === "stdio"
                            ? `Command: ${example.config.command} ${example.config.args?.join(" ") || ""}`
                            : `URL: ${example.config.url}`
                          }
                        </p>
                        {example.config.env && Object.keys(example.config.env).length > 0 && (
                          <p className="text-xs text-muted-foreground mt-1">
                            Environment: {Object.keys(example.config.env).join(", ")}
                          </p>
                        )}
                        {example.note && (
                          <p className="text-xs text-amber-600 dark:text-amber-400 mt-1">
                            ⚠️ {example.note}
                          </p>
                        )}
                      </div>
                      <Button
                        size="sm"
                        variant="outline"
                        onClick={() => {
                          setName(example.name)
                          setTransport(example.config.transport)
                          // Combine command and args into fullCommand
                          const cmd = example.config.command || ""
                          const args = example.config.args?.join(" ") || ""
                          setFullCommand(args ? `${cmd} ${args}` : cmd)
                          setUrl(example.config.url || "")
                          setEnv(
                            example.config.env
                              ? Object.entries(example.config.env)
                                  .map(([k, v]) => `${k}=${v}`)
                                  .join("\n")
                              : ""
                          )
                          setTimeout(example.config.timeout?.toString() || "")
                          setDisabled(example.config.disabled || false)
                          // Set headers if the example has them
                          setHeaders(
                            example.config.headers
                              ? Object.entries(example.config.headers)
                                  .map(([k, v]) => `${k}=${v}`)
                                  .join("\n")
                              : ""
                          )
                          // Reset OAuth config when switching examples to prevent stale fields
                          setOAuthConfig({})
                          setActiveTab('manual')
                        }}
                      >
                        Use
                      </Button>
                    </div>
                  </Card>
                ))}
              </div>

              {/* OAuth MCP Examples */}
              {Object.keys(OAUTH_MCP_EXAMPLES).length > 0 && (
                <div className="space-y-2">
                  <h4 className="font-medium text-sm">OAuth-Enabled MCP Servers</h4>
                  {Object.entries(OAUTH_MCP_EXAMPLES).map(([key, example]) => (
                    <Card key={key} className="p-3">
                      <div className="flex items-start justify-between">
                        <div className="flex-1">
                          <h5 className="font-medium text-sm">{example.name}</h5>
                          <p className="text-xs text-muted-foreground mt-1">
                            {example.description}
                          </p>
                          <p className="text-xs text-muted-foreground mt-1">
                            URL: {example.config.url}
                          </p>
                          {example.requiredScopes && (
                            <p className="text-xs text-muted-foreground mt-1">
                              Scopes: {example.requiredScopes.join(", ")}
                            </p>
                          )}
                        </div>
                        <Button
                          size="sm"
                          variant="outline"
                          onClick={() => {
                            setName(example.name)
                            setTransport(example.config.transport)
                            // Combine command and args into fullCommand
                            const cmd = example.config.command || ""
                            const args = example.config.args?.join(" ") || ""
                            setFullCommand(args ? `${cmd} ${args}` : cmd)
                            setUrl(example.config.url || "")
                            setEnv(
                              example.config.env
                                ? Object.entries(example.config.env)
                                    .map(([k, v]) => `${k}=${v}`)
                                    .join("\n")
                                : ""
                            )
                            setTimeout(example.config.timeout?.toString() || "")
                            setDisabled(example.config.disabled || false)
                            setOAuthConfig(example.config.oauth || {})
                            setActiveTab('manual')
                          }}
                        >
                          Use
                        </Button>
                      </div>
                    </Card>
                  ))}
                </div>
              )}
            </div>
          </div>
        )}
      </div>

      <DialogFooter>
        <Button variant="outline" onClick={onCancel}>
          Cancel
        </Button>
        {/* Only show Add/Update Server button on manual and examples tabs */}
        {/* File and paste tabs have their own action buttons */}
        {(activeTab === 'manual' || activeTab === 'examples') && (
          <Button onClick={handleSave}>{server ? "Update" : "Add"} Server</Button>
        )}
      </DialogFooter>
    </DialogContent>
  )
}

// Example MCP server configurations
const MCP_EXAMPLES: Record<string, { name: string; config: MCPServerConfig; note?: string }> = {
  github: {
    name: "github",
    config: {
      transport: "stdio" as MCPTransportType,
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: {
        GITHUB_PERSONAL_ACCESS_TOKEN: "your-github-token-here",
      },
    },
  },
  exa: {
    name: "exa",
    config: {
      transport: "streamableHttp" as MCPTransportType,
      url: "https://mcp.exa.ai/mcp",
    },
  },
  memory: {
    name: "memory",
    config: {
      transport: "stdio" as MCPTransportType,
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-memory"],
      env: {},
    },
  },
  "sequential-thinking": {
    name: "sequential-thinking",
    config: {
      transport: "stdio" as MCPTransportType,
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-sequential-thinking"],
      env: {},
    },
  },
  "desktop-commander": {
    name: "desktop-commander",
    config: {
      transport: "stdio" as MCPTransportType,
      command: "npx",
      args: ["-y", "@wonderwhy-er/desktop-commander@latest"],
      env: {},
    },
  },
  filesystem: {
    name: "filesystem",
    config: {
      transport: "stdio" as MCPTransportType,
      command: "npx",
      args: [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/path/to/allowed/directory",
      ],
      env: {},
    },
  },
  playwright: {
    name: "playwright",
    config: {
      transport: "stdio" as MCPTransportType,
      command: "npx",
      args: ["-y", "@playwright/mcp@latest"],
      env: {},
    },
  },
  "headless-terminal": {
    name: "headless-terminal",
    config: {
      transport: "stdio" as MCPTransportType,
      command: "ht-mcp",
      args: [],
      env: {},
    },
  },
}

export function MCPConfigManager({
  config,
  onConfigChange,
  collapsedToolServers,
  collapsedServers,
  onCollapsedToolServersChange,
  onCollapsedServersChange,
}: MCPConfigManagerProps) {
  const [editingServer, setEditingServer] = useState<{
    name: string
    config: MCPServerConfig
  } | null>(null)
  const [showAddDialog, setShowAddDialog] = useState(false)
  const [showExamples, setShowExamples] = useState(false)
  const [serverStatus, setServerStatus] = useState<
    Record<
      string,
      {
        connected: boolean
        toolCount: number
        error?: string
        runtimeEnabled?: boolean
        configDisabled?: boolean
      }
    >
  >({})
  const [initializationStatus, setInitializationStatus] = useState<{
    isInitializing: boolean
    progress: { current: number; total: number; currentServer?: string }
  }>({ isInitializing: false, progress: { current: 0, total: 0 } })
  const [oauthStatus, setOAuthStatus] = useState<Record<string, { configured: boolean; authenticated: boolean; tokenExpiry?: number; error?: string }>>({})
  const [serverLogs, setServerLogs] = useState<Record<string, ServerLogEntry[]>>({})
  const [expandedLogs, setExpandedLogs] = useState<Set<string>>(new Set())
  // Initialize expandedServers from persisted expanded state
  // All servers are collapsed by default - only expand those explicitly persisted as expanded
  const [expandedServers, setExpandedServers] = useState<Set<string>>(() => {
    // collapsedServers stores which servers are collapsed
    // - undefined: never persisted before (first time) → all collapsed by default
    // - []: explicitly persisted as "no servers collapsed" (e.g., user clicked "expand all") → all expanded
    // - [...names]: specific servers are collapsed → expand all except those
    const allServerNames = Object.keys(config.mcpServers || {})

    // If collapsedServers is undefined, we haven't persisted yet - default to all collapsed
    if (collapsedServers === undefined) {
      return new Set<string>() // All collapsed by default
    }

    // If collapsedServers is an empty array, user explicitly set "no servers collapsed" (all expanded)
    // Otherwise, expand servers not in the collapsed list
    const collapsedSet = new Set(collapsedServers)
    return new Set(allServerNames.filter(name => !collapsedSet.has(name)))
  })
  // Tool management state
  const [tools, setTools] = useState<DetailedTool[]>([])
  const [toolSearchQuery, setToolSearchQuery] = useState("")
  const [showDisabledTools, setShowDisabledTools] = useState(true)
  // Initialize expandedTools (servers in Tools section) - all expanded by default except those persisted as collapsed
  const [expandedToolServers, setExpandedToolServers] = useState<Set<string>>(() => {
    // We don't know server names yet, so start with empty set meaning "all expanded"
    // When collapsedToolServers is provided, those will be collapsed
    return new Set<string>() // Will be populated when tools load
  })
  const [toolServersInitialized, setToolServersInitialized] = useState(false)


  // Define servers early so it can be used in hooks below
  const servers = config.mcpServers || {}

  // Track which reserved server names we've already warned about (to avoid repeated warnings)
  const warnedReservedServersRef = useRef<Set<string>>(new Set())

  // Track known server names to detect new servers
  const [knownServers, setKnownServers] = useState<Set<string>>(() => new Set([...Object.keys(config.mcpServers || {}), ...RESERVED_SERVER_NAMES]))

  // Track if we've completed the initial config hydration
  // This prevents treating all servers as "new" when settings-mcp-tools initially renders
  // with an empty config before useConfigQuery resolves
  const initialHydrationCompleteRef = useRef(
    // If config already has servers on mount, we're hydrated.
    // Also treat persisted collapse state as a signal that config is hydrated,
    // even when the config legitimately has zero servers.
    collapsedServers !== undefined || Object.keys(config.mcpServers || {}).length > 0
  )

  // Handle server changes: prune stale entries (new servers stay collapsed by default)
  // Include reserved runtime-tool server names so they don't get pruned
  useEffect(() => {
    const currentServerNames = new Set([...Object.keys(servers), ...RESERVED_SERVER_NAMES])

    // Find new servers (not in knownServers)
    const newServers = [...currentServerNames].filter(name => !knownServers.has(name))

    // Prune stale entries (remove servers that no longer exist)
    const prunedSet = new Set([...expandedServers].filter(name => currentServerNames.has(name)))

    // New servers stay collapsed by default - don't add them to expanded set

    if (prunedSet.size !== expandedServers.size) {
      setExpandedServers(prunedSet)
    }

    // Check if we're still in initial hydration phase
    // If knownServers only had RESERVED_SERVER_NAMES and now we're seeing user servers,
    // this is the initial config load, not new servers being added
    const wasEmptyOnMount = knownServers.size <= RESERVED_SERVER_NAMES.length &&
      [...knownServers].every(name => RESERVED_SERVER_NAMES.includes(name))

    if (wasEmptyOnMount && newServers.length > 0 && !initialHydrationCompleteRef.current) {
      // This is the initial config load - don't persist, just update knownServers
      initialHydrationCompleteRef.current = true
      setKnownServers(currentServerNames)
      return
    }

    // Mark hydration complete once we have any persisted collapse state, even if
    // the config legitimately has zero servers.
    if (collapsedServers !== undefined || Object.keys(servers).length > 0) {
      initialHydrationCompleteRef.current = true
    }

    // Persist new servers as collapsed to ensure consistency after Settings reopen
    // Only do this if we have already persisted (collapsedServers is not undefined)
    // and we're past the initial hydration phase
    // This ensures that when a new server is added and we want it collapsed,
    // it's added to the persisted collapsed list so it stays collapsed after reopening
    if (newServers.length > 0 && collapsedServers !== undefined && onCollapsedServersChange && initialHydrationCompleteRef.current) {
      const updatedCollapsed = [...new Set([...collapsedServers, ...newServers])]
      onCollapsedServersChange(updatedCollapsed)
    }

    // Update known servers
    if (newServers.length > 0 || [...knownServers].some(name => !currentServerNames.has(name))) {
      setKnownServers(currentServerNames)
    }
  }, [servers, collapsedServers])

  // Warn about servers with reserved names that are being filtered out
  useEffect(() => {
    const hiddenServers = Object.keys(servers).filter(
      (name) => RESERVED_SERVER_NAMES.some(
        (reserved) => name.trim().toLowerCase() === reserved.toLowerCase()
      )
    )
    for (const serverName of hiddenServers) {
      if (!warnedReservedServersRef.current.has(serverName)) {
        warnedReservedServersRef.current.add(serverName)
        toast.warning(`Server "${serverName}" uses a reserved name and has been hidden. Please rename or remove it from your MCP configuration.`)
      }
    }
  }, [servers])

  // Sync expandedServers when collapsedServers prop changes (e.g., after async config load)
  // This tracks the previous collapsedServers to detect external changes
  const prevCollapsedServersRef = useRef<string[] | undefined>(collapsedServers)
  useEffect(() => {
    // Check if collapsedServers prop actually changed
    const prevCollapsed = prevCollapsedServersRef.current
    const prevSet = new Set<string>(prevCollapsed ?? [])
    const currentSet = new Set<string>(collapsedServers ?? [])
    // Also detect undefined → array transitions
    const wasUndefined = prevCollapsed === undefined
    const isUndefined = collapsedServers === undefined
    const collapsedChanged =
      wasUndefined !== isUndefined ||
      prevSet.size !== currentSet.size ||
      [...prevSet].some(s => !currentSet.has(s))

    if (collapsedChanged) {
      prevCollapsedServersRef.current = collapsedServers
      // Re-sync expandedServers from the new collapsed list
      const currentServerNames = new Set([...Object.keys(servers), ...RESERVED_SERVER_NAMES])

      // undefined = never persisted (first time) → all collapsed
      if (collapsedServers === undefined) {
        setExpandedServers(new Set<string>())
      } else {
        // [] = explicitly "no servers collapsed" (all expanded)
        // [...names] = specific servers are collapsed
        const collapsedSet = new Set<string>(collapsedServers)
        const newExpanded = new Set<string>([...currentServerNames].filter(name => !collapsedSet.has(name)))
        setExpandedServers(newExpanded)
      }
    }
  }, [collapsedServers, servers])

  // Load OAuth status for all servers
  const refreshOAuthStatus = async (serverName?: string) => {
    try {
      if (serverName) {
        const status = await window.electronAPI.getOAuthStatus(serverName)
        setOAuthStatus(prev => ({ ...prev, [serverName]: status }))
      } else {
        // Load status for all servers
        const newStatus: Record<string, any> = {}
        for (const [name, config] of Object.entries(servers)) {
          if (config.transport === "streamableHttp" && config.url) {
            const status = await window.electronAPI.getOAuthStatus(name)
            newStatus[name] = status
          }
        }
        setOAuthStatus(newStatus)
      }
    } catch (error) {
      console.error('Failed to load OAuth status:', error)
    }
  }

  // Fetch logs for expanded servers
  const fetchLogsForServer = async (serverName: string) => {
    try {
      const logs = await tipcClient.getMcpServerLogs({ serverName })
      setServerLogs(prev => ({ ...prev, [serverName]: logs as ServerLogEntry[] }))
    } catch (error) {
      console.error(`Failed to fetch logs for ${serverName}:`, error)
    }
  }

  // Fetch server status and initialization status periodically
  useEffect(() => {
    const fetchStatus = async () => {
      try {
        const [status, initStatus] = await Promise.all([
          tipcClient.getMcpServerStatus({}),
          tipcClient.getMcpInitializationStatus({}),
        ])
        setServerStatus(status as any)
        setInitializationStatus(initStatus as any)
        await refreshOAuthStatus()

        // Fetch logs for expanded servers
        for (const serverName of expandedLogs) {
          await fetchLogsForServer(serverName)
        }
      } catch (error) {}
    }

    fetchStatus()
    const interval = setInterval(fetchStatus, 1000) // Update every second during initialization

    return () => clearInterval(interval)
  }, [servers, expandedLogs])

  // Fetch tools function - defined as useCallback so it can be reused
  const fetchTools = useCallback(async () => {
    try {
      const toolList = await tipcClient.getMcpDetailedToolList({})
      setTools(toolList as DetailedTool[])
    } catch (error) {}
  }, [])

  // Fetch tools periodically
  useEffect(() => {
    fetchTools()
    const interval = setInterval(fetchTools, 5000) // Update every 5 seconds

    return () => clearInterval(interval)
  }, [fetchTools])

  // Track known tool source names to detect new sources
  const [knownToolServers, setKnownToolServers] = useState<Set<string>>(new Set())

  // Initialize expanded tool groups when tools are first loaded.
  // All sources are expanded by default; only persisted collapsed groups stay collapsed.
  useEffect(() => {
    if (tools.length > 0) {
      const allToolServerNames = [...new Set<string>(tools.map(t => t.sourceName))]
      const collapsedSet = new Set<string>(collapsedToolServers ?? [])

      if (!toolServersInitialized) {
        // Initial setup: all sources expanded by default, except those persisted as collapsed
        const expanded = new Set<string>(allToolServerNames.filter(name => !collapsedSet.has(name)))
        setExpandedToolServers(expanded)
        setKnownToolServers(new Set<string>(allToolServerNames))
        setToolServersInitialized(true)
      } else {
        // After initialization: detect new sources and expand them by default
        const newServers = allToolServerNames.filter(name => !knownToolServers.has(name))
        if (newServers.length > 0) {
          setExpandedToolServers(prev => {
            const updated = new Set<string>(prev)
            newServers.forEach(name => updated.add(name))
            return updated
          })
          setKnownToolServers(prev => {
            const updated = new Set<string>(prev)
            newServers.forEach(name => updated.add(name))
            return updated
          })
        }
      }
    }
  }, [tools, collapsedToolServers, toolServersInitialized, knownToolServers])

  // Sync expandedToolServers when collapsedToolServers prop changes (e.g., after async config load)
  const prevCollapsedToolServersRef = useRef<string[] | undefined>(collapsedToolServers)
  useEffect(() => {
    // Check if collapsedToolServers prop actually changed (use set comparison for robustness)
    const prevCollapsed = prevCollapsedToolServersRef.current
    const prevSet = new Set<string>(prevCollapsed ?? [])
    const currentSet = new Set<string>(collapsedToolServers ?? [])
    const collapsedChanged =
      prevSet.size !== currentSet.size ||
      [...prevSet].some(s => !currentSet.has(s))

    if (collapsedChanged && toolServersInitialized) {
      prevCollapsedToolServersRef.current = collapsedToolServers
      // Re-sync expandedToolServers from the new collapsed list
      const allToolServerNames = [...new Set<string>(tools.map(t => t.sourceName))]
      const collapsedSet = new Set<string>(collapsedToolServers ?? [])
      const newExpanded = new Set<string>(allToolServerNames.filter(name => !collapsedSet.has(name)))
      setExpandedToolServers(newExpanded)
    }
  }, [collapsedToolServers, tools, toolServersInitialized])



  // Group tools by source
  const toolsByServer = tools.reduce(
    (acc, tool) => {
      if (!acc[tool.sourceName]) {
        acc[tool.sourceName] = []
      }
      acc[tool.sourceName].push(tool)
      return acc
    },
    {} as Record<string, DetailedTool[]>,
  )

  // Filter tools for a specific source
  // Only include tools from enabled sources
  const getFilteredToolsForServer = (serverName: string) => {
    const serverTools = toolsByServer[serverName] || []
    return serverTools.filter((tool) => {
      // Hide tools from disabled servers
      if (!tool.serverEnabled) return false
      const matchesSearch =
        tool.name.toLowerCase().includes(toolSearchQuery.toLowerCase()) ||
        tool.description.toLowerCase().includes(toolSearchQuery.toLowerCase())
      const matchesVisibility = showDisabledTools || tool.enabled
      return matchesSearch && matchesVisibility
    })
  }

  const handleToolToggle = async (toolName: string, enabled: boolean) => {
    try {
      // Update local state immediately for better UX
      setTools((prevTools) =>
        prevTools.map((tool) =>
          tool.name === toolName ? { ...tool, enabled } : tool,
        ),
      )

      // Call the backend API
      const result = await tipcClient.setMcpToolEnabled({ toolName, enabled })

      if ((result as any).success) {
        toast.success(`Tool ${toolName} ${enabled ? "enabled" : "disabled"}`)
      } else {
        // Revert local state if backend call failed
        setTools((prevTools) =>
          prevTools.map((tool) =>
            tool.name === toolName ? { ...tool, enabled: !enabled } : tool,
          ),
        )
        toast.error(
          `Failed to ${enabled ? "enable" : "disable"} tool ${toolName}`,
        )
      }
    } catch (error: any) {
      // Revert local state on error
      setTools((prevTools) =>
        prevTools.map((tool) =>
          tool.name === toolName ? { ...tool, enabled: !enabled } : tool,
        ),
      )
      toast.error(`Error toggling tool: ${error.message}`)
    }
  }

  const handleToggleAllToolsForServer = async (serverName: string, enable: boolean) => {
    const serverTools = tools.filter((tool) => tool.sourceName === serverName)
    if (serverTools.length === 0) return
    const sourceLabel = serverTools[0]?.sourceLabel || serverName

    // Update local state immediately for better UX
    const updatedTools = tools.map((tool) => {
      if (tool.sourceName === serverName) {
        return { ...tool, enabled: enable }
      }
      return tool
    })
    setTools(updatedTools)

    // Track promises for all backend calls
    const promises = serverTools.map((tool) =>
      tipcClient.setMcpToolEnabled({ toolName: tool.name, enabled: enable }),
    )

    try {
      const results = await Promise.allSettled(promises)
      // A fulfilled promise with { success: false } (e.g. essential tool that
      // cannot be disabled) should also be treated as a failure.
      const successful = results.filter(
        (r) => r.status === "fulfilled" && (r.value as any)?.success,
      ).length
      const failed = results.length - successful

      if (failed === 0) {
        toast.success(
          `All ${serverTools.length} tools for ${sourceLabel} ${enable ? "enabled" : "disabled"}`,
        )
      } else {
        // Revert local state for failed calls (rejected OR success:false)
        const failedTools = serverTools.filter(
          (_, index) => {
            const r = results[index]
            return r.status === "rejected" || !(r.value as any)?.success
          },
        )
        const revertedTools = tools.map((tool) => {
          if (tool.sourceName === serverName && failedTools.includes(tool)) {
            return { ...tool, enabled: !enable }
          }
          return tool
        })
        setTools(revertedTools)

        toast.warning(
          `${successful}/${serverTools.length} tools ${enable ? "enabled" : "disabled"} for ${sourceLabel} (${failed} failed)`,
        )
      }
    } catch (error: any) {
      // Revert all tools on error
      const revertedTools = tools.map((tool) => {
        if (tool.sourceName === serverName) {
          return { ...tool, enabled: !enable }
        }
        return tool
      })
      setTools(revertedTools)
      toast.error(`Error toggling tools for ${sourceLabel}: ${error.message}`)
    }
  }

  const toggleToolsExpansion = (serverName: string) => {
    setExpandedToolServers(prev => {
      const allToolServerNames = [...new Set<string>(tools.map(t => t.sourceName))]
      const collapsedSet = new Set<string>(collapsedToolServers ?? [])

      // If not yet initialized, start with all sources expanded (minus persisted collapsed ones)
      // This ensures first toggle behaves correctly even before useEffect runs
      let newSet: Set<string>
      if (!toolServersInitialized && prev.size === 0) {
        newSet = new Set<string>(allToolServerNames.filter(name => !collapsedSet.has(name)))
      } else {
        newSet = new Set<string>(prev)
      }

      if (newSet.has(serverName)) {
        newSet.delete(serverName)
      } else {
        newSet.add(serverName)
      }
      // Persist the collapsed state (servers NOT in expanded set are collapsed)
      if (onCollapsedToolServersChange) {
        const collapsed = allToolServerNames.filter(name => !newSet.has(name))
        onCollapsedToolServersChange(collapsed)
      }
      return newSet
    })
  }

  const handleAddServer = async (name: string, serverConfig: MCPServerConfig) => {
    const newConfig = {
      ...config,
      mcpServers: {
        ...servers,
        [name]: serverConfig,
      },
    }
    onConfigChange(newConfig)
    setShowAddDialog(false)

    // Auto-start the server after adding it (unless it's disabled)
    if (!serverConfig.disabled) {
      // Wait a bit for the config to be saved
      setTimeout(async () => {
        try {
          // Mark the server as runtime-enabled
          const runtimeResult = await tipcClient.setMcpServerRuntimeEnabled({
            serverName: name,
            enabled: true,
          })
          if (!(runtimeResult as any).success) {
            toast.error(`Failed to enable server: Server not found`)
            return
          }

          // Start the server
          const result = await tipcClient.restartMcpServer({ serverName: name })
          if ((result as any).success) {
            toast.success(`Server ${name} connected successfully`)
          } else {
            toast.error(`Failed to connect server: ${(result as any).error}`)
          }
        } catch (error) {
          toast.error(`Failed to connect server: ${error instanceof Error ? error.message : String(error)}`)
        }
      }, 500)
    }
  }

  const handleEditServer = (
    oldName: string,
    newName: string,
    serverConfig: MCPServerConfig,
  ) => {
    const newServers = { ...servers }
    if (oldName !== newName) {
      delete newServers[oldName]
    }
    newServers[newName] = serverConfig

    const newConfig = {
      ...config,
      mcpServers: newServers,
    }
    onConfigChange(newConfig)
    setEditingServer(null)
  }

  const handleDeleteServer = (name: string) => {
    const newServers = { ...servers }
    delete newServers[name]

    const newConfig = {
      ...config,
      mcpServers: newServers,
    }
    onConfigChange(newConfig)
  }

  const handleImportConfigFromFile = async () => {
    try {
      const importedConfig = await tipcClient.loadMcpConfigFile({})
      if (importedConfig) {
        // Filter out reserved server names (case-insensitive to match ServerDialog validation)
        const filteredServers: Record<string, any> = {}
        const skippedNames: string[] = []
        for (const [serverName, serverConfig] of Object.entries(importedConfig.mcpServers)) {
          const normalizedName = serverName.trim().toLowerCase()
          if (RESERVED_SERVER_NAMES.some(reserved => reserved.toLowerCase() === normalizedName)) {
            skippedNames.push(serverName)
          } else {
            filteredServers[serverName] = serverConfig
          }
        }

        // Warn about skipped reserved names
        for (const skippedName of skippedNames) {
          toast.warning(`Skipped importing reserved server name: ${skippedName}`)
        }

        const importedCount = Object.keys(filteredServers).length
        if (importedCount === 0 && skippedNames.length > 0) {
          toast.error("No servers to import - all server names were reserved")
          return
        }

        // Add imported servers to config (duplicates will be replaced by imported versions)
        const newConfig = {
          ...config,
          mcpServers: {
            ...config.mcpServers,
            ...filteredServers,
          },
        }
        onConfigChange(newConfig)
        setShowAddDialog(false)
        toast.success(`Successfully imported ${importedCount} server(s)`)
      }
    } catch (error) {
      toast.error(`Failed to import config: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  const handleExportConfig = async () => {
    try {
      const success = await tipcClient.saveMcpConfigFile({ config })
      if (success) {
        toast.success("MCP configuration exported successfully")
      }
    } catch (error) {
      toast.error(`Failed to export config: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  const formatJsonPreview = (jsonText: string): string => {
    try {
      if (!jsonText.trim()) return jsonText
      const parsed = JSON.parse(jsonText)
      return JSON.stringify(parsed, null, 2)
    } catch {
      return jsonText
    }
  }

  const handleImportFromText = async (text: string): Promise<boolean> => {
    try {
      // Format JSON for consistency before validation (falls back to original text if parsing fails)
      // Note: formatJsonPreview returns the original text on parse errors, actual validation
      // is performed by validateMcpConfigText which will catch any JSON syntax errors
      const formattedJson = formatJsonPreview(text)

      const importedConfig = await tipcClient.validateMcpConfigText({ text: formattedJson })

      if (importedConfig) {
        // Filter out reserved server names (case-insensitive to match ServerDialog validation)
        const filteredServers: Record<string, any> = {}
        const skippedNames: string[] = []
        for (const [serverName, serverConfig] of Object.entries(importedConfig.mcpServers)) {
          const normalizedName = serverName.trim().toLowerCase()
          if (RESERVED_SERVER_NAMES.some(reserved => reserved.toLowerCase() === normalizedName)) {
            skippedNames.push(serverName)
          } else {
            filteredServers[serverName] = serverConfig
          }
        }

        // Warn about skipped reserved names
        for (const skippedName of skippedNames) {
          toast.warning(`Skipped importing reserved server name: ${skippedName}`)
        }

        const importedCount = Object.keys(filteredServers).length
        if (importedCount === 0 && skippedNames.length > 0) {
          toast.error("No servers to import - all server names were reserved")
          return false
        }

        // Add imported servers to config (duplicates will be replaced by imported versions)
        const newConfig = {
          ...config,
          mcpServers: {
            ...config.mcpServers,
            ...filteredServers,
          },
        }
        onConfigChange(newConfig)
        setShowAddDialog(false)
        toast.success(`Successfully imported ${importedCount} server(s)`)
        return true
      }
      return false
    } catch (error) {
      toast.error(`Invalid JSON: ${error instanceof Error ? error.message : String(error)}`)
      return false
    }
  }

  const handleAddExample = (exampleKey: string) => {
    const example = MCP_EXAMPLES[exampleKey]
    if (example) {
      handleAddServer(example.name, example.config)
      setShowExamples(false)
      toast.success(`Added ${example.name} server configuration`)
    }
  }

  const handleAddOAuthExample = (exampleKey: string) => {
    const example = OAUTH_MCP_EXAMPLES[exampleKey]
    if (example) {
      handleAddServer(example.name, example.config)
      setShowExamples(false)
      toast.success(`Added ${example.name} OAuth server configuration`)

      // Show setup instructions
      if (example.setupInstructions.length > 0) {
        toast.info(`Setup required: ${example.setupInstructions[0]}`, {
          duration: 5000,
        })
      }
    }
  }

  const handleRestartServer = async (serverName: string) => {
    try {
      const result = await tipcClient.restartMcpServer({ serverName })
      if ((result as any).success) {
        toast.success(`Server ${serverName} restarted successfully`)
      } else {
        toast.error(`Failed to restart server: ${(result as any).error}`)
      }
    } catch (error) {
      toast.error(`Failed to restart server: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  const handleStopServer = async (serverName: string) => {
    try {
      // First mark the server as runtime-disabled so it stays stopped
      const runtimeResult = await tipcClient.setMcpServerRuntimeEnabled({
        serverName,
        enabled: false,
      })
      if (!(runtimeResult as any).success) {
        toast.error(`Failed to disable server: Server not found`)
        return
      }

      // Then stop the server
      const result = await tipcClient.stopMcpServer({ serverName })
      if ((result as any).success) {
        toast.success(`Server ${serverName} stopped successfully`)
        // Immediately fetch tools to update the UI
        await fetchTools()
      } else {
        toast.error(`Failed to stop server: ${(result as any).error}`)
      }
    } catch (error) {
      toast.error(`Failed to stop server: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  const handleStartServer = async (serverName: string) => {
    try {
      // Mark the server as runtime-enabled so it can be initialized
      const runtimeResult = await tipcClient.setMcpServerRuntimeEnabled({
        serverName,
        enabled: true,
      })
      if (!(runtimeResult as any).success) {
        toast.error(`Failed to enable server: Server not found`)
        return
      }

      // Restart the server to initialize it
      const result = await tipcClient.restartMcpServer({ serverName })
      if ((result as any).success) {
        toast.success(`Server ${serverName} started successfully`)
        // Immediately fetch tools so they appear without waiting for the 5-second interval
        await fetchTools()
      } else {
        toast.error(`Failed to start server: ${(result as any).error}`)
      }
    } catch (error) {
      toast.error(`Failed to start server: ${error.message}`)
    }
  }

  const handleRevokeOAuth = async (serverName: string) => {
    try {
      await window.electronAPI.revokeOAuthTokens(serverName)
      toast.success("OAuth authentication revoked")
      refreshOAuthStatus(serverName)
    } catch (error) {
      toast.error(`Failed to revoke authentication: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  const handleInitiateOAuth = async (serverName: string) => {
    try {
      await window.electronAPI.initiateOAuthFlow(serverName)
      toast.success("OAuth authentication started")
      const checkCompletion = setInterval(async () => {
        const statusResult = await window.electronAPI.getOAuthStatus(serverName)
        if (statusResult.authenticated) {
          clearInterval(checkCompletion)
          refreshOAuthStatus(serverName)
          toast.success("OAuth authentication completed")
        }
      }, 2000)
      setTimeout(() => clearInterval(checkCompletion), 60000)
    } catch (error) {
      toast.error(`Failed to start OAuth flow: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  const toggleLogs = (serverName: string) => {
    setExpandedLogs(prev => {
      const newSet = new Set(prev)
      if (newSet.has(serverName)) {
        newSet.delete(serverName)
      } else {
        newSet.add(serverName)
        // Fetch logs immediately when expanding
        fetchLogsForServer(serverName)
      }
      return newSet
    })
  }

  // Build the user-configurable server list only.
  // Filter out any user servers with reserved names to prevent collisions
  // Defined before toggleServerExpansion so it can use allServers for persistence
  const filteredUserServers: Record<string, MCPServerConfig> = Object.fromEntries(
    Object.entries(servers).filter(
      ([name]) => !RESERVED_SERVER_NAMES.some(
        (reserved) => name.trim().toLowerCase() === reserved.toLowerCase()
      )
    )
  ) as Record<string, MCPServerConfig>
  const allServers: Record<string, MCPServerConfig> = filteredUserServers

  const toggleServerExpansion = (serverName: string) => {
    setExpandedServers(prev => {
      const newSet = new Set(prev)
      if (newSet.has(serverName)) {
        newSet.delete(serverName)
      } else {
        newSet.add(serverName)
      }
      // Persist the collapsed state (servers NOT in expanded set are collapsed)
      if (onCollapsedServersChange) {
        const allServerNames = Object.keys(allServers)
        const collapsed = allServerNames.filter(name => !newSet.has(name))
        onCollapsedServersChange(collapsed)
      }
      return newSet
    })
  }

  const toggleAllServers = (expand: boolean) => {
    const allServerNames = Object.keys(allServers)
    if (expand) {
      setExpandedServers(new Set(allServerNames))
      // Persist: when all expanded, no servers are collapsed
      if (onCollapsedServersChange) {
        onCollapsedServersChange([])
      }
    } else {
      setExpandedServers(new Set())
      // Persist: when all collapsed, all servers are in collapsed list
      if (onCollapsedServersChange) {
        onCollapsedServersChange(allServerNames)
      }
    }
  }

  const handleClearLogs = async (serverName: string) => {
    try {
      await tipcClient.clearMcpServerLogs({ serverName })
      setServerLogs(prev => ({ ...prev, [serverName]: [] }))
      toast.success(`Logs cleared for ${serverName}`)
    } catch (error) {
      toast.error(`Failed to clear logs: ${error instanceof Error ? error.message : String(error)}`)
    }
  }

  // Calculate total tools count (only from enabled servers)
  const toolsFromEnabledServers = tools.filter((t) => t.serverEnabled)
  const totalToolsCount = toolsFromEnabledServers.length
  const enabledToolsCount = toolsFromEnabledServers.filter((t) => t.enabled).length
  const disabledToolsCount = totalToolsCount - enabledToolsCount

  // State for collapsible sections
  const [toolsSectionExpanded, setToolsSectionExpanded] = useState(true)
  const [serversSectionExpanded, setServersSectionExpanded] = useState(true)

  // Get all filtered tools (global, across all servers)
  // Only include tools from enabled servers
  const getAllFilteredTools = () => {
    return tools.filter((tool) => {
      // Hide tools from disabled servers
      if (!tool.serverEnabled) return false
      const matchesSearch =
        tool.name.toLowerCase().includes(toolSearchQuery.toLowerCase()) ||
        tool.description.toLowerCase().includes(toolSearchQuery.toLowerCase())
      const matchesVisibility = showDisabledTools || tool.enabled
      return matchesSearch && matchesVisibility
    })
  }

  // Handle toggle all tools (global)
  const handleToggleAllTools = async (enable: boolean) => {
    const filteredTools = getAllFilteredTools()
    if (filteredTools.length === 0) return

    // Capture original enabled states before any changes
    const originalStates = new Map<string, boolean>()
    filteredTools.forEach(tool => {
      originalStates.set(tool.name, tool.enabled)
    })

    // Update local state immediately for better UX
    const updatedTools = tools.map((tool) => {
      if (filteredTools.some(ft => ft.name === tool.name)) {
        return { ...tool, enabled: enable }
      }
      return tool
    })
    setTools(updatedTools)

    // Track promises for all backend calls
    const promises = filteredTools.map((tool) =>
      tipcClient.setMcpToolEnabled({ toolName: tool.name, enabled: enable }),
    )

    try {
      const results = await Promise.allSettled(promises)
      // Check both if the promise was fulfilled AND if the success field is true
      const successful = results.filter(
        (r) => r.status === "fulfilled" && (r.value as any).success === true,
      ).length
      const failed = results.length - successful

      if (failed === 0) {
        toast.success(`All ${filteredTools.length} tools ${enable ? "enabled" : "disabled"}`)
      } else {
        // Revert local state for failed calls (rejected OR success: false)
        const failedTools = filteredTools.filter(
          (_, index) =>
            results[index].status === "rejected" ||
            (results[index].status === "fulfilled" &&
              (results[index] as PromiseFulfilledResult<any>).value.success !== true),
        )
        const revertedTools = updatedTools.map((tool) => {
          if (failedTools.some(ft => ft.name === tool.name)) {
            return { ...tool, enabled: originalStates.get(tool.name) ?? tool.enabled }
          }
          return tool
        })
        setTools(revertedTools)

        toast.warning(
          `${successful}/${filteredTools.length} tools ${enable ? "enabled" : "disabled"} (${failed} failed)`,
        )
      }
    } catch (error: any) {
      // Revert all tools on error
      const revertedTools = updatedTools.map((tool) => {
        if (filteredTools.some(ft => ft.name === tool.name)) {
          return { ...tool, enabled: originalStates.get(tool.name) ?? tool.enabled }
        }
        return tool
      })
      setTools(revertedTools)
      toast.error(`Error toggling tools: ${error.message}`)
    }
  }

  return (
    <div className="min-w-0 space-y-6">
      <div className="flex min-w-0 flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-center gap-3">
          <h3 className="text-lg font-medium">MCP Tools & Servers</h3>
          {totalToolsCount > 0 && (
            <Badge variant="secondary" className="text-sm">
              {enabledToolsCount}/{totalToolsCount} tools enabled
            </Badge>
          )}
        </div>
      </div>

      {/* Loading spinner during initialization */}
      {initializationStatus.isInitializing && (
        <Card className="border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-950">
          <CardContent className="flex items-center justify-center py-6">
            <div className="flex items-center gap-3">
              <Spinner className="h-5 w-5" />
              <div className="text-sm">
                <div className="font-medium">Initializing MCP servers...</div>
                <div className="text-muted-foreground">
                  {initializationStatus.progress.currentServer && (
                    <>
                      Connecting to{" "}
                      {initializationStatus.progress.currentServer}
                    </>
                  )}
                  {initializationStatus.progress.total > 0 && (
                    <>
                      {" "}
                      ({initializationStatus.progress.current}/
                      {initializationStatus.progress.total})
                    </>
                  )}
                </div>
              </div>
            </div>
          </CardContent>
        </Card>
      )}

      {/* ==================== TOOLS SECTION ==================== */}
      <Card>
        <div
          role="button"
          tabIndex={0}
          aria-expanded={toolsSectionExpanded}
          aria-label="Toggle tools section"
          className="flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-accent/50 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
          onClick={() => setToolsSectionExpanded(!toolsSectionExpanded)}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault()
              setToolsSectionExpanded(!toolsSectionExpanded)
            }
          }}
        >
          <div className="flex items-center gap-2">
            {toolsSectionExpanded ? (
              <ChevronDown className="h-4 w-4 text-muted-foreground" />
            ) : (
              <ChevronRight className="h-4 w-4 text-muted-foreground" />
            )}
            <Wrench className="h-4 w-4" />
            <span className="font-medium">Tools</span>
            <Badge variant="secondary" className="text-xs">
              {enabledToolsCount}/{totalToolsCount} enabled
            </Badge>
          </div>
        </div>

        {toolsSectionExpanded && (
          <CardContent className="border-t pt-4">
            {/* Tool Search and Filter Controls */}
            <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between mb-4">
              <div className="flex flex-1 items-center gap-3">
                <div className="relative flex-1 max-w-sm">
                  <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                  <Input
                    placeholder="Search tools..."
                    value={toolSearchQuery}
                    onChange={(e) => setToolSearchQuery(e.target.value)}
                    className="pl-9"
                  />
                </div>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => setShowDisabledTools(!showDisabledTools)}
                  className="shrink-0 gap-2"
                >
                  {showDisabledTools ? (
                    <EyeOff className="h-4 w-4" />
                  ) : (
                    <Eye className="h-4 w-4" />
                  )}
                  {showDisabledTools ? "Hide Disabled" : "Show All"}
                </Button>
              </div>
              <div className="flex items-center gap-1">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handleToggleAllTools(true)}
                  className="shrink-0 gap-1"
                >
                  <Power className="h-3 w-3" />
                  All ON
                </Button>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handleToggleAllTools(false)}
                  className="shrink-0 gap-1"
                >
                  <PowerOff className="h-3 w-3" />
                  All OFF
                </Button>
              </div>
            </div>

            {/* Tools List - Grouped by Server with Collapsible Groups */}
            <div className="space-y-2 flex-1 min-h-0 overflow-y-auto">
              {getAllFilteredTools().length === 0 ? (
                <div className="text-sm text-muted-foreground text-center py-4">
                  {totalToolsCount === 0
                    ? "No tools available. Connect a server to see its tools."
                    : "No tools match your search"}
                </div>
              ) : (
                // Group filtered tools by source
                (Object.entries(
                  getAllFilteredTools().reduce((acc, tool) => {
                    if (!acc[tool.sourceName]) {
                      acc[tool.sourceName] = []
                    }
                    acc[tool.sourceName].push(tool)
                    return acc
                  }, {} as Record<string, DetailedTool[]>)
                ) as Array<[string, DetailedTool[]]>).map(([serverName, serverTools]) => {
                  const sourceLabel = serverTools[0]?.sourceLabel || serverName
                  const isRuntimeBuiltinSource = serverTools[0]?.sourceKind === "runtime"
                  // Before initialization: expanded unless in collapsedToolServers (respects persisted state)
                  // After initialization: use the expandedToolServers set
                  const isExpanded = !toolServersInitialized
                    ? !(collapsedToolServers ?? []).includes(serverName)
                    : expandedToolServers.has(serverName)
                  return (
                  <div key={serverName} className="space-y-2">
                    {/* Server Header - Clickable for collapse/expand */}
                    <div
                      role="button"
                      tabIndex={0}
                      aria-expanded={isExpanded}
                      aria-label={`Toggle ${sourceLabel} tools`}
                      className="flex items-center justify-between bg-muted/50 rounded-lg px-3 py-2 cursor-pointer hover:bg-muted/70 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1"
                      onClick={() => toggleToolsExpansion(serverName)}
                      onKeyDown={(e) => {
                        if (e.key === 'Enter' || e.key === ' ') {
                          e.preventDefault()
                          toggleToolsExpansion(serverName)
                        }
                      }}
                    >
                      <div className="flex items-center gap-2">
                        {isExpanded ? (
                          <ChevronDown className="h-4 w-4 text-muted-foreground transition-transform" />
                        ) : (
                          <ChevronRight className="h-4 w-4 text-muted-foreground transition-transform" />
                        )}
                        {isRuntimeBuiltinSource
                          ? <Wrench className="h-4 w-4 text-muted-foreground" />
                          : <Server className="h-4 w-4 text-muted-foreground" />}
                        <span className="text-sm font-medium">{sourceLabel}</span>
                        <Badge variant="secondary" className="text-xs">
                          {serverTools.filter(t => t.enabled).length}/{serverTools.length} enabled
                        </Badge>

                      </div>
                      <div className="flex items-center gap-1" onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()}>
                        <Button
                          variant="ghost"
                          size="sm"
                          onClick={() => handleToggleAllToolsForServer(serverName, true)}
                          className="h-6 gap-1 px-2 text-xs"
                        >
                          <Power className="h-3 w-3" />
                          ON
                        </Button>
                        <Button
                          variant="ghost"
                          size="sm"
                          onClick={() => handleToggleAllToolsForServer(serverName, false)}
                          className="h-6 gap-1 px-2 text-xs"
                        >
                          <PowerOff className="h-3 w-3" />
                          OFF
                        </Button>
                      </div>
                    </div>
                    {/* Tools for this server - Collapsible with animation */}
                    {isExpanded && (
                      <div className="space-y-2 pl-6 animate-in fade-in slide-in-from-top-1 duration-200">
                        {serverTools.map((tool) => (
                          <div
                            key={tool.name}
                            className="flex items-center justify-between rounded-lg border p-3"
                          >
                            <div className="min-w-0 flex-1">
                              <div className="mb-1 flex items-center gap-2">
                                <h4 className="truncate text-sm font-medium">
                                  {tool.name.includes(":")
                                    ? tool.name.split(":").slice(1).join(":")
                                    : tool.name}
                                </h4>
                                {!tool.enabled && (
                                  <Badge variant="secondary" className="text-xs shrink-0">
                                    Disabled
                                  </Badge>
                                )}

	                              </div>
                            </div>
                            <div className="ml-4 flex items-center gap-2">
                              <Dialog>
                                <DialogTrigger asChild>
                                  <Button variant="ghost" size="sm">
                                    <Eye className="h-4 w-4" />
                                  </Button>
                                </DialogTrigger>
                                <DialogContent className="max-w-2xl w-[90vw] max-h-[85vh] overflow-y-auto">
                                  <DialogHeader className="min-w-0">
                                    <DialogTitle className="break-words">{tool.name}</DialogTitle>
                                    <DialogDescription className="break-words">
                                      {tool.description}
                                    </DialogDescription>
                                  </DialogHeader>
                                  <div className="space-y-4 min-w-0">
                                    <div className="min-w-0">
                                      <Label className="text-sm font-medium">
                                        Source
                                      </Label>
                                      <p className="text-sm text-muted-foreground mt-1 break-words">
                                        {tool.sourceLabel}
                                      </p>
                                    </div>
                                    <div className="min-w-0">
                                      <Label className="text-sm font-medium">
                                        Input Schema
                                      </Label>
                                      <pre className="mt-2 max-h-80 overflow-auto rounded-md bg-muted p-3 text-xs whitespace-pre-wrap break-words">
                                        {JSON.stringify(tool.inputSchema, null, 2)}
                                      </pre>
                                    </div>
                                  </div>

                              </DialogContent>
                            </Dialog>
                            <Switch
                              checked={tool.enabled}
                              onCheckedChange={(enabled) =>
                                handleToolToggle(tool.name, enabled)
                              }
                            />
                          </div>
	                        </div>
                        ))}
                      </div>
                    )}
                  </div>
                )})
              )}
            </div>
          </CardContent>
        )}
      </Card>

      {/* ==================== SERVERS SECTION ==================== */}
      <Card>
        <div
          role="button"
          tabIndex={0}
          aria-expanded={serversSectionExpanded}
          aria-label="Toggle servers section"
          className="flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-accent/50 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
          onClick={() => setServersSectionExpanded(!serversSectionExpanded)}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault()
              setServersSectionExpanded(!serversSectionExpanded)
            }
          }}
        >
          <div className="flex items-center gap-2">
            {serversSectionExpanded ? (
              <ChevronDown className="h-4 w-4 text-muted-foreground" />
            ) : (
              <ChevronRight className="h-4 w-4 text-muted-foreground" />
            )}
            <Server className="h-4 w-4" />
            <span className="font-medium">Servers</span>
            <Badge variant="secondary" className="text-xs">
              {Object.keys(allServers).length}
            </Badge>
          </div>
          <div
            className="flex items-center gap-2"
            onClick={(e) => e.stopPropagation()}
            onKeyDown={(e) => e.stopPropagation()}
          >
            <Button variant="outline" size="sm" className="gap-2" onClick={handleExportConfig}>
              <Download className="h-4 w-4" />
              Export
            </Button>
            <Dialog open={showAddDialog} onOpenChange={setShowAddDialog}>
              <DialogTrigger asChild>
                <Button size="sm" className="gap-2">
                  <Plus className="h-4 w-4" />
                  Add Server
                </Button>
              </DialogTrigger>
              <ServerDialog
                onSave={handleAddServer}
                onCancel={() => setShowAddDialog(false)}
                onImportFromFile={handleImportConfigFromFile}
                onImportFromText={handleImportFromText}
                isOpen={showAddDialog}
              />
            </Dialog>
          </div>
        </div>

        {serversSectionExpanded && (
          <CardContent className="border-t pt-4">
            <div className="grid gap-2">
              {Object.entries(allServers).map(([name, serverConfig]) => {
                const status = serverStatus[name]
                const serverTools = toolsByServer[name] || []
                const enabledToolCount = serverTools.filter((t) => t.enabled).length

                return (
                  <Card key={name} className="overflow-hidden">
                    {/* Collapsed Header Row - Always Visible */}
                    <div
                      role="button"
                      tabIndex={0}
                      aria-expanded={expandedServers.has(name)}
                      aria-label={`Toggle ${name} server details`}
                      className="flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-accent/50 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
                      onClick={() => toggleServerExpansion(name)}
                      onKeyDown={(e) => {
                        if (e.key === 'Enter' || e.key === ' ') {
                          e.preventDefault()
                          toggleServerExpansion(name)
                        }
                      }}
                    >
                      <div className="flex min-w-0 flex-1 items-center gap-2">
                        {expandedServers.has(name) ? (
                          <ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground" />
                        ) : (
                          <ChevronRight className="h-4 w-4 shrink-0 text-muted-foreground" />
                        )}
                        <span className="font-medium truncate">{name}</span>
                        {serverConfig?.disabled ? (
                          <Badge variant="secondary" className="shrink-0">Disabled</Badge>
                        ) : status?.runtimeEnabled === false ? (
                          <div className="flex shrink-0 items-center gap-1">
                            <Square className="h-3 w-3 text-orange-500" />
                            <Badge
                              variant="outline"
                              className="border-orange-300 text-orange-600 text-xs"
                            >
                              Stopped
                            </Badge>
                          </div>
                        ) : (
                          <>
                            {status?.connected ? (
                              <div className="flex shrink-0 items-center gap-1">
                                <CheckCircle className="h-3 w-3 text-green-500" />
                                <Badge variant="default" className="text-xs">
                                  {serverTools.length > 0
                                    ? `${enabledToolCount}/${serverTools.length} tools`
                                    : `${status.toolCount} tools`}
                                </Badge>
                              </div>
                            ) : status?.error ? (
                              <div className="flex shrink-0 items-center gap-1">
                                <XCircle className="h-3 w-3 text-red-500" />
                                <Badge variant="destructive" className="text-xs">Error</Badge>
                              </div>
                            ) : (
                              <div className="flex shrink-0 items-center gap-1">
                                <AlertCircle className="h-3 w-3 text-yellow-500" />
                                <Badge variant="outline" className="text-xs">Disconnected</Badge>
                              </div>
                            )}
                          </>
                        )}
                      </div>
                      {/* Action buttons - stop propagation so clicks/keys don't toggle expansion */}
                      {serverConfig && (
                        <div
                          className="flex shrink-0 items-center gap-1"
                          onClick={(e) => e.stopPropagation()}
                          onKeyDown={(e) => e.stopPropagation()}
                        >
                          <DropdownMenu>
                            <DropdownMenuTrigger asChild>
                              <Button
                                variant="ghost"
                                size="sm"
                                className="h-7 gap-1 px-2 text-[11px] text-muted-foreground hover:text-foreground"
                                aria-label={`Actions for ${name} server`}
                              >
                                <MoreHorizontal className="h-3.5 w-3.5" />
                                <span>Actions</span>
                              </Button>
                            </DropdownMenuTrigger>
                            <DropdownMenuContent align="end">
                              {!serverConfig.disabled && (
                                <>
                                  {status?.runtimeEnabled === false ? (
                                    <DropdownMenuItem onClick={() => handleStartServer(name)}>
                                      <Play className="h-3.5 w-3.5" />
                                      Start server
                                    </DropdownMenuItem>
                                  ) : (
                                    <>
                                      <DropdownMenuItem onClick={() => handleRestartServer(name)}>
                                        <RotateCcw className="h-3.5 w-3.5" />
                                        Restart server
                                      </DropdownMenuItem>
                                      <DropdownMenuItem onClick={() => handleStopServer(name)}>
                                        <Square className="h-3.5 w-3.5" />
                                        Stop server
                                      </DropdownMenuItem>
                                    </>
                                  )}
                                  <DropdownMenuSeparator />
                                </>
                              )}
                              <DropdownMenuItem onClick={() => setEditingServer({ name, config: serverConfig })}>
                                <Edit className="h-3.5 w-3.5" />
                                Edit server
                              </DropdownMenuItem>
                              {serverConfig.transport === "streamableHttp" && serverConfig.url && (
                                <>
                                  {oauthStatus[name]?.authenticated ? (
                                    <DropdownMenuItem
                                      onClick={() => handleRevokeOAuth(name)}
                                      className="text-destructive focus:text-destructive"
                                    >
                                      <XCircle className="h-3.5 w-3.5" />
                                      Revoke OAuth
                                    </DropdownMenuItem>
                                  ) : oauthStatus[name]?.configured ? (
                                    <DropdownMenuItem onClick={() => handleInitiateOAuth(name)}>
                                      <ExternalLink className="h-3.5 w-3.5" />
                                      Start OAuth
                                    </DropdownMenuItem>
                                  ) : null}
                                </>
                              )}
                              <DropdownMenuSeparator />
                              <DropdownMenuItem
                                onClick={() => handleDeleteServer(name)}
                                className="text-destructive focus:text-destructive"
                              >
                                <Trash2 className="h-3.5 w-3.5" />
                                Delete server
                              </DropdownMenuItem>
                            </DropdownMenuContent>
                          </DropdownMenu>
                        </div>
                      )}
                    </div>

                    {/* Expanded Details Section */}
                    {expandedServers.has(name) && (
                      <>
                        <CardContent className="pt-0 border-t">
                          <div className="space-y-3 py-3">
                            {serverConfig && (
                              <>
                                {/* Command/Transport Info */}
                                <div className="text-sm">
                                  <span className="font-medium text-muted-foreground">
                                    {serverConfig.transport === "stdio" || !serverConfig.transport ? "Command:" : "Transport:"}
                                  </span>{" "}
                                  <code className="text-xs bg-muted px-1.5 py-0.5 rounded">
                                    {serverConfig.transport === "stdio" || !serverConfig.transport
                                      ? `${serverConfig.command || ""} ${serverConfig.args ? serverConfig.args.join(" ") : ""}`
                                      : `${serverConfig.transport}: ${serverConfig.url || ""}`}
                                  </code>
                                </div>

                                {/* Environment Variables */}
                                {serverConfig.env && Object.keys(serverConfig.env).length > 0 && (
                                  <div className="text-sm">
                                    <span className="font-medium text-muted-foreground">Environment:</span>{" "}
                                    <span className="text-xs text-muted-foreground">
                                      {Object.keys(serverConfig.env).join(", ")}
                                    </span>
                                  </div>
                                )}

                                {/* Timeout */}
                                {serverConfig.timeout && (
                                  <div className="text-sm">
                                    <span className="font-medium text-muted-foreground">Timeout:</span>{" "}
                                    <span className="text-xs text-muted-foreground">{serverConfig.timeout}ms</span>
                                  </div>
                                )}

                                {/* Error (if any) */}
                                {status?.error && (
                                  <div className="text-sm text-red-500">
                                    <span className="font-medium">Error:</span> {status.error}
                                  </div>
                                )}
                              </>
                            )}
                          </div>
                        </CardContent>

                        {/* Server Logs Section - only show for stdio servers */}
                        {serverConfig && (serverConfig.transport === "stdio" || !serverConfig.transport) && (
                          <CardContent className="pt-0 border-t">
                            <div className="space-y-2 py-2">
                              <div className="flex items-center justify-between">
                                <Button
                                  variant="ghost"
                                  size="sm"
                                  onClick={() => toggleLogs(name)}
                                  className="flex items-center gap-2 -ml-2"
                                >
                                  <Terminal className="h-4 w-4" />
                                  <span>Server Logs</span>
                                  {expandedLogs.has(name) ? (
                                    <ChevronUp className="h-4 w-4" />
                                  ) : (
                                    <ChevronDown className="h-4 w-4" />
                                  )}
                                </Button>
                                {expandedLogs.has(name) && (
                                  <Button
                                    variant="ghost"
                                    size="sm"
                                    onClick={() => handleClearLogs(name)}
                                    title="Clear logs"
                                  >
                                    <Trash className="h-4 w-4" />
                                  </Button>
                                )}
                              </div>

                              {expandedLogs.has(name) && (
                                <div className="bg-black/90 rounded-md p-3 max-h-64 overflow-y-auto font-mono text-xs">
                                  {serverLogs[name]?.length > 0 ? (
                                    <div className="space-y-1">
                                      {serverLogs[name].map((log, idx) => (
                                        <div key={idx} className="text-green-400">
                                          <span className="text-gray-500">
                                            [{new Date(log.timestamp).toLocaleTimeString()}]
                                          </span>{' '}
                                          {log.message}
                                        </div>
                                      ))}
                                    </div>
                                  ) : (
                                    <div className="text-gray-500 text-center py-4">
                                      No logs available
                                    </div>
                                  )}
                                </div>
                              )}
                            </div>
                          </CardContent>
                        )}
                      </>
                    )}
                  </Card>
                )
              })}
            </div>
          </CardContent>
        )}
      </Card>

      {editingServer && (
        <Dialog open={true} onOpenChange={() => setEditingServer(null)}>
          <ServerDialog
            server={editingServer}
            onSave={(newName, config) =>
              handleEditServer(editingServer.name, newName, config)
            }
            onCancel={() => setEditingServer(null)}
          />
        </Dialog>
      )}
    </div>
  )
}
