import React, { useState } from "react";
import { discoverOAuthEndpoints, startOAuthFlow } from "../services/oauth";
import { Plus, Server, Wifi, WifiOff, Trash2, TestTube } from "lucide-react";
import { useMCP } from "../hooks/useMCP";
import type { MCPServerConfig } from "../types/mcp";
import { STORAGE_KEYS, DEFAULTS } from "../config/constants";

interface MCPServerManagerProps {
  isOpen: boolean;
  onClose: () => void;
}

export const MCPServerManager: React.FC<MCPServerManagerProps> = ({
  isOpen,
  onClose,
}) => {
  const {
    mcpState,
    addServer,
    removeServer,
    connectToServer,
    disconnectFromServer,
    testConnection,
  } = useMCP();
  const [showAddForm, setShowAddForm] = useState(false);
  const [testingConnection, setTestingConnection] = useState<string | null>(
    null
  );
  const [notification, setNotification] = useState<{
    message: string;
    type: "success" | "error";
  } | null>(null);

  const [newServer, setNewServer] = useState<Omit<MCPServerConfig, "id">>({
    name: "",
    url: "",
    enabled: true,
    transport: "streamable-http",
    auth: {
      type: "bearer",
    },
  });

  if (!isOpen) return null;

  const handleAddServer = async () => {
    if (!newServer.name || !newServer.url) return;

    const serverConfig: MCPServerConfig = {
      ...newServer,
      id: `server_${Date.now()}`,
    };

    // Persist name and transport for OAuth flow
    localStorage.setItem(STORAGE_KEYS.MCP_SERVER_NAME, newServer.name);
    localStorage.setItem(
      STORAGE_KEYS.MCP_SERVER_TRANSPORT,
      newServer.transport
    );

    try {
      await addServer(serverConfig);
      setNewServer({
        name: "",
        url: "",
        enabled: true,
        transport: "streamable-http",
        auth: {
          type: "bearer",
        },
      });
      setShowAddForm(false);
    } catch (error) {
      setNotification({
        message: `Failed to add server: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        type: "error",
      });
      setTimeout(() => setNotification(null), DEFAULTS.OAUTH_ERROR_TIMEOUT);
    }
  };

  const handleTestConnection = async (config: MCPServerConfig) => {
    setTestingConnection(config.id);
    try {
      const success = await testConnection(config);
      if (success) {
        setNotification({
          message: "Connection test successful!",
          type: "success",
        });
      } else {
        setNotification({
          message: "Connection test failed. Please check your configuration.",
          type: "error",
        });
      }
    } catch (error) {
      setNotification({
        message: `Connection test failed: ${error}`,
        type: "error",
      });
    } finally {
      setTestingConnection(null);
      // Auto-hide notification after 3 seconds
      setTimeout(() => setNotification(null), DEFAULTS.NOTIFICATION_TIMEOUT);
    }
  };

  const handleToggleConnection = async (
    serverId: string,
    isConnected: boolean
  ) => {
    try {
      if (isConnected) {
        await disconnectFromServer(serverId);
      } else {
        await connectToServer(serverId);
      }
    } catch (error) {
      setNotification({
        message: `Failed to toggle connection: ${
          error instanceof Error ? error.message : "Unknown error"
        }`,
        type: "error",
      });
      setTimeout(() => setNotification(null), DEFAULTS.OAUTH_ERROR_TIMEOUT);
    }
  };

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div className="bg-gray-800 rounded-lg p-6 w-full max-w-4xl max-h-[80vh] overflow-y-auto">
        <div className="flex justify-between items-center mb-6">
          <h2 className="text-2xl font-bold text-white flex items-center gap-2">
            <Server className="text-blue-400" />
            MCP Server Manager
          </h2>
          <button onClick={onClose} className="text-gray-400 hover:text-white">
            ✕
          </button>
        </div>

        {/* Add Server Button */}
        <div className="mb-6">
          <button
            onClick={() => setShowAddForm(!showAddForm)}
            className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center gap-2"
          >
            <Plus size={16} />
            Add MCP Server
          </button>
        </div>

        {/* Add Server Form */}
        {showAddForm && (
          <div className="bg-gray-700 rounded-lg p-4 mb-6">
            <h3 className="text-lg font-semibold text-white mb-4">
              Add New MCP Server
            </h3>
            <div className="space-y-4">
              <div>
                <label className="block text-sm font-medium text-gray-300 mb-1">
                  Server Name
                </label>
                <input
                  type="text"
                  value={newServer.name}
                  onChange={(e) =>
                    setNewServer({ ...newServer, name: e.target.value })
                  }
                  className="w-full bg-gray-600 text-white rounded px-3 py-2"
                  placeholder="My MCP Server"
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-300 mb-1">
                  Server URL
                </label>
                <input
                  type="url"
                  value={newServer.url}
                  onChange={(e) =>
                    setNewServer({ ...newServer, url: e.target.value })
                  }
                  className="w-full bg-gray-600 text-white rounded px-3 py-2"
                  placeholder="http://localhost:3000/mcp"
                />
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-300 mb-1">
                  Transport
                </label>
                <select
                  value={newServer.transport}
                  onChange={(e) =>
                    setNewServer({
                      ...newServer,
                      transport: e.target.value as MCPServerConfig["transport"],
                    })
                  }
                  className="w-full bg-gray-600 text-white rounded px-3 py-2"
                >
                  <option value="streamable-http">Streamable HTTP</option>
                  <option value="sse">Server-Sent Events</option>
                </select>
              </div>

              <div>
                <label className="block text-sm font-medium text-gray-300 mb-1">
                  Authentication
                </label>
                <select
                  value={newServer.auth?.type || "none"}
                  onChange={(e) => {
                    const authType = e.target.value;
                    if (authType === "none") {
                      setNewServer({ ...newServer, auth: undefined });
                    } else {
                      setNewServer({
                        ...newServer,
                        auth: {
                          type: authType as "bearer" | "basic" | "oauth",
                          ...(authType === "bearer" ? { token: "" } : {}),
                          ...(authType === "basic"
                            ? { username: "", password: "" }
                            : {}),
                          ...(authType === "oauth" ? { token: "" } : {}),
                        },
                      });
                    }
                  }}
                  className="w-full bg-gray-600 text-white rounded px-3 py-2"
                >
                  <option value="none">No Authentication</option>
                  <option value="bearer">Bearer Token</option>
                  <option value="basic">Basic Auth</option>
                  <option value="oauth">OAuth Token</option>
                </select>
              </div>

              {/* Auth-specific fields */}
              {newServer.auth?.type === "bearer" && (
                <div>
                  <label className="block text-sm font-medium text-gray-300 mb-1">
                    Bearer Token
                  </label>
                  <input
                    type="password"
                    value={newServer.auth.token || ""}
                    onChange={(e) =>
                      setNewServer({
                        ...newServer,
                        auth: { ...newServer.auth!, token: e.target.value },
                      })
                    }
                    className="w-full bg-gray-600 text-white rounded px-3 py-2"
                    placeholder="your-bearer-token"
                  />
                </div>
              )}

              {newServer.auth?.type === "basic" && (
                <>
                  <div>
                    <label className="block text-sm font-medium text-gray-300 mb-1">
                      Username
                    </label>
                    <input
                      type="text"
                      value={newServer.auth.username || ""}
                      onChange={(e) =>
                        setNewServer({
                          ...newServer,
                          auth: {
                            ...newServer.auth!,
                            username: e.target.value,
                          },
                        })
                      }
                      className="w-full bg-gray-600 text-white rounded px-3 py-2"
                      placeholder="username"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-300 mb-1">
                      Password
                    </label>
                    <input
                      type="password"
                      value={newServer.auth.password || ""}
                      onChange={(e) =>
                        setNewServer({
                          ...newServer,
                          auth: {
                            ...newServer.auth!,
                            password: e.target.value,
                          },
                        })
                      }
                      className="w-full bg-gray-600 text-white rounded px-3 py-2"
                      placeholder="password"
                    />
                  </div>
                </>
              )}

              {newServer.auth?.type === "oauth" && (
                <div>
                  <label className="block text-sm font-medium text-gray-300 mb-1">
                    OAuth Authorization
                  </label>
                  <button
                    className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded mb-2"
                    type="button"
                    onClick={async () => {
                      try {
                        // Persist name and transport for OAuthCallback
                        localStorage.setItem(
                          STORAGE_KEYS.MCP_SERVER_NAME,
                          newServer.name
                        );
                        localStorage.setItem(
                          STORAGE_KEYS.MCP_SERVER_TRANSPORT,
                          newServer.transport
                        );
                        const endpoints = await discoverOAuthEndpoints(
                          newServer.url
                        );

                        if (!endpoints.clientId || !endpoints.redirectUri) {
                          throw new Error(
                            "Missing required OAuth configuration (clientId or redirectUri)"
                          );
                        }

                        startOAuthFlow({
                          authorizationEndpoint:
                            endpoints.authorizationEndpoint,
                          clientId: endpoints.clientId as string,
                          redirectUri: endpoints.redirectUri as string,
                          scopes: (endpoints.scopes || []) as string[],
                        });
                      } catch (err) {
                        setNotification({
                          message:
                            "OAuth discovery failed: " +
                            (err instanceof Error ? err.message : String(err)),
                          type: "error",
                        });
                        setTimeout(
                          () => setNotification(null),
                          DEFAULTS.OAUTH_ERROR_TIMEOUT
                        );
                      }
                    }}
                  >
                    Connect with OAuth
                  </button>
                  <p className="text-xs text-gray-400">
                    You will be redirected to authorize this app with the MCP
                    server.
                  </p>
                </div>
              )}

              <div className="flex items-center gap-2">
                <input
                  type="checkbox"
                  id="enabled"
                  checked={newServer.enabled}
                  onChange={(e) =>
                    setNewServer({ ...newServer, enabled: e.target.checked })
                  }
                  className="rounded"
                />
                <label htmlFor="enabled" className="text-sm text-gray-300">
                  Auto-connect when added
                </label>
              </div>

              <div className="flex gap-2">
                <button
                  onClick={handleAddServer}
                  className="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded"
                >
                  Add Server
                </button>
                <button
                  onClick={() => setShowAddForm(false)}
                  className="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded"
                >
                  Cancel
                </button>
              </div>
            </div>
          </div>
        )}

        {/* Server List */}
        <div className="space-y-4">
          <h3 className="text-lg font-semibold text-white">
            Configured Servers
          </h3>

          {Object.values(mcpState.servers).length === 0 ? (
            <div className="text-gray-400 text-center py-8">
              No MCP servers configured. Add one to get started!
            </div>
          ) : (
            Object.values(mcpState.servers).map((connection) => (
              <div
                key={connection.config.id}
                className="bg-gray-700 rounded-lg p-4"
              >
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-3">
                    <div
                      className={`w-3 h-3 rounded-full ${
                        connection.isConnected ? "bg-green-400" : "bg-red-400"
                      }`}
                    />
                    <div>
                      <h4 className="text-white font-medium">
                        {connection.config.name}
                      </h4>
                      <p className="text-gray-400 text-sm">
                        {connection.config.url}
                      </p>
                      <p className="text-gray-500 text-xs">
                        Transport: {connection.config.transport}
                        {connection.config.auth &&
                          ` • Auth: ${connection.config.auth.type}`}
                        {connection.isConnected &&
                          ` • ${connection.tools.length} tools available`}
                      </p>
                    </div>
                  </div>

                  <div className="flex items-center gap-2">
                    {/* Test Connection */}
                    <button
                      onClick={() => handleTestConnection(connection.config)}
                      disabled={testingConnection === connection.config.id}
                      className="p-2 text-yellow-400 hover:text-yellow-300 disabled:opacity-50"
                      title="Test Connection"
                    >
                      <TestTube size={16} />
                    </button>

                    {/* Connect/Disconnect */}
                    <button
                      onClick={() =>
                        handleToggleConnection(
                          connection.config.id,
                          connection.isConnected
                        )
                      }
                      className={`p-2 ${
                        connection.isConnected
                          ? "text-green-400 hover:text-green-300"
                          : "text-gray-400 hover:text-gray-300"
                      }`}
                      title={connection.isConnected ? "Disconnect" : "Connect"}
                    >
                      {connection.isConnected ? (
                        <Wifi size={16} />
                      ) : (
                        <WifiOff size={16} />
                      )}
                    </button>

                    {/* Remove Server */}
                    <button
                      onClick={() => removeServer(connection.config.id)}
                      className="p-2 text-red-400 hover:text-red-300"
                      title="Remove Server"
                    >
                      <Trash2 size={16} />
                    </button>
                  </div>
                </div>

                {connection.lastError && (
                  <div className="mt-2 text-red-400 text-sm">
                    Error: {connection.lastError}
                  </div>
                )}

                {connection.isConnected && connection.tools.length > 0 && (
                  <div className="mt-3">
                    <details className="text-sm">
                      <summary className="text-gray-300 cursor-pointer">
                        Available Tools ({connection.tools.length})
                      </summary>
                      <div className="mt-2 space-y-1">
                        {connection.tools.map((tool) => (
                          <div key={tool.name} className="text-gray-400 pl-4">
                            • {tool.name} -{" "}
                            {tool.description || "No description"}
                          </div>
                        ))}
                      </div>
                    </details>
                  </div>
                )}
              </div>
            ))
          )}
        </div>

        {mcpState.error && (
          <div className="mt-4 p-4 bg-red-900 border border-red-700 rounded-lg text-red-200">
            <strong>Error:</strong> {mcpState.error}
          </div>
        )}

        {notification && (
          <div
            className={`mt-4 p-4 border rounded-lg ${
              notification.type === "success"
                ? "bg-green-900 border-green-700 text-green-200"
                : "bg-red-900 border-red-700 text-red-200"
            }`}
          >
            {notification.message}
          </div>
        )}
      </div>
    </div>
  );
};
