import type { McpServer } from "mcp-use/react";
import {
  buildOAuthStaticConfig,
  type OAuthStaticConfig,
} from "@/client/utils/connectionUpdates";

// Type alias for backward compatibility
type MCPConnection = McpServer;
type MCPConnectionWithConfig = MCPConnection & {
  proxyConfig?: {
    proxyAddress?: string;
    headers?: Record<string, string>;
    customHeaders?: Record<string, string>;
  };
  headers?: Record<string, string>;
  customHeaders?: Record<string, string>;
  oauth?: OAuthStaticConfig;
};
import type { CustomHeader } from "./CustomHeadersEditor";
import { useEffect, useState } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/client/components/ui/dialog";
import { getConfiguredServerAlias } from "@/client/utils/serverNames";
import { ConnectionSettingsForm } from "./ConnectionSettingsForm";
import { toast } from "sonner";

interface ServerConnectionModalProps {
  connection: MCPConnection | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onConnect: (config: {
    url: string;
    name?: string;
    transportType: "http" | "sse";
    proxyConfig?: {
      proxyAddress?: string;
      headers?: Record<string, string>;
    };
    oauth?: OAuthStaticConfig;
  }) => void;
}

/**
 * Renders a modal for viewing and editing a server connection's settings.
 *
 * @param connection - Existing connection to prefill the form, or `null` to start empty
 * @param open - Whether the modal is visible
 * @param onOpenChange - Callback invoked with the new open state when the modal is opened or closed
 * @param onConnect - Callback invoked with the connection configuration when the user submits the form
 * @returns The modal's JSX element
 */
export function ServerConnectionModal({
  connection,
  open,
  onOpenChange,
  onConnect,
}: ServerConnectionModalProps) {
  // Form state
  const [alias, setAlias] = useState("");
  const [url, setUrl] = useState("");
  const [connectionType, setConnectionType] = useState("Direct");
  const [customHeaders, setCustomHeaders] = useState<CustomHeader[]>([]);
  const [requestTimeout, setRequestTimeout] = useState("10000");
  const [resetTimeoutOnProgress, setResetTimeoutOnProgress] = useState("True");
  const [maxTotalTimeout, setMaxTotalTimeout] = useState("60000");
  const [proxyAddress, setProxyAddress] = useState(
    `${window.location.origin}/inspector/api/proxy`
  );
  // OAuth fields
  const [clientId, setClientId] = useState("");
  const [clientSecret, setClientSecret] = useState("");
  const [scope, setScope] = useState("");

  // Prefill form when connection changes
  useEffect(() => {
    if (connection && open) {
      const connectionWithConfig = connection as MCPConnectionWithConfig;

      // Try to get the original stored config from localStorage
      // This contains the headers and proxyConfig that were originally saved
      let storedConfig: any = null;
      try {
        const stored = localStorage.getItem("mcp-inspector-connections");
        if (stored) {
          const allServers = JSON.parse(stored);
          storedConfig = allServers[connection.id];
        }
      } catch (e) {
        // If we can't read from localStorage, fall back to connection object
        console.warn(
          "[ServerConnectionModal] Could not read from localStorage:",
          e
        );
      }

      setUrl(connection.url);
      setAlias(getConfiguredServerAlias(storedConfig || connection));

      // Transport type is always HTTP now (SSE is deprecated)
      // No need to set transportType from connection

      // Determine connection type based on proxyConfig
      const proxyAddress =
        storedConfig?.proxyConfig?.proxyAddress ||
        connectionWithConfig.proxyConfig?.proxyAddress;
      if (proxyAddress) {
        setConnectionType("Via Proxy");
        setProxyAddress(proxyAddress);
      } else {
        setConnectionType("Direct");
        setProxyAddress(`${window.location.origin}/inspector/api/proxy`);
      }

      // Convert headers from Record<string, string> to CustomHeader[]
      // Check both 'headers' and 'customHeaders' for backwards compatibility
      // Prioritize stored config over connection object
      const headersToConvert =
        storedConfig?.proxyConfig?.headers ||
        storedConfig?.proxyConfig?.customHeaders ||
        storedConfig?.headers ||
        storedConfig?.customHeaders ||
        connectionWithConfig.proxyConfig?.headers ||
        connectionWithConfig.proxyConfig?.customHeaders ||
        connectionWithConfig.headers ||
        connectionWithConfig.customHeaders ||
        {};
      const headerArray: CustomHeader[] = Object.entries(headersToConvert).map(
        ([name, value], index) => ({
          id: `header-${index}`,
          name,
          value: String(value),
        })
      );
      setCustomHeaders(headerArray);

      const storedOauth = storedConfig?.oauth ?? connectionWithConfig.oauth;
      setClientId(storedOauth?.clientId || "");
      setClientSecret(storedOauth?.clientSecret || "");
      setScope(storedOauth?.scope || "");
    }
  }, [connection, open]);

  const handleConnect = () => {
    if (!url.trim()) return;

    // Validate URL format and auto-add https:// if protocol is missing
    let normalizedUrl = url.trim();
    try {
      const parsedUrl = new URL(normalizedUrl);
      const isValid =
        parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";

      if (!isValid) {
        toast.error("Invalid URL protocol. Please use http:// or https://");
        return;
      }
    } catch (error) {
      // If parsing fails, try adding https:// prefix
      try {
        const urlWithHttps = `https://${normalizedUrl}`;
        const parsedUrl = new URL(urlWithHttps);
        const isValid =
          parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";

        if (!isValid) {
          toast.error("Invalid URL protocol. Please use http:// or https://");
          return;
        }
        // Use the normalized URL with https://
        normalizedUrl = urlWithHttps;
      } catch (retryError) {
        toast.error("Invalid URL format. Please enter a valid URL.");
        return;
      }
    }

    // Prepare proxy configuration if "Via Proxy" is selected
    const proxyConfig =
      connectionType === "Via Proxy" && proxyAddress.trim()
        ? {
            proxyAddress: proxyAddress.trim(),
            headers: customHeaders.reduce(
              (acc, header) => {
                if (header.name && header.value) {
                  acc[header.name] = header.value;
                }
                return acc;
              },
              {} as Record<string, string>
            ),
          }
        : {
            headers: customHeaders.reduce(
              (acc, header) => {
                if (header.name && header.value) {
                  acc[header.name] = header.value;
                }
                return acc;
              },
              {} as Record<string, string>
            ),
          };

    // Always use HTTP transport (SSE is deprecated)
    const actualTransportType = "http";

    const oauth = buildOAuthStaticConfig(clientId, clientSecret, scope);

    onConnect({
      url: normalizedUrl,
      name: alias.trim() || normalizedUrl,
      transportType: actualTransportType,
      proxyConfig,
      ...(oauth ? { oauth } : {}),
    });

    onOpenChange(false);
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="w-[calc(100vw-2rem)] sm:w-full max-w-2xl max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Edit Connection Settings</DialogTitle>
        </DialogHeader>
        <ConnectionSettingsForm
          alias={alias}
          setAlias={setAlias}
          url={url}
          setUrl={setUrl}
          connectionType={connectionType}
          setConnectionType={setConnectionType}
          customHeaders={customHeaders}
          setCustomHeaders={setCustomHeaders}
          requestTimeout={requestTimeout}
          setRequestTimeout={setRequestTimeout}
          resetTimeoutOnProgress={resetTimeoutOnProgress}
          setResetTimeoutOnProgress={setResetTimeoutOnProgress}
          maxTotalTimeout={maxTotalTimeout}
          setMaxTotalTimeout={setMaxTotalTimeout}
          proxyAddress={proxyAddress}
          setProxyAddress={setProxyAddress}
          clientId={clientId}
          setClientId={setClientId}
          clientSecret={clientSecret}
          setClientSecret={setClientSecret}
          scope={scope}
          setScope={setScope}
          onConnect={handleConnect}
          variant="default"
          showConnectButton={true}
          showExportButton={false}
          isConnecting={false}
        />
      </DialogContent>
    </Dialog>
  );
}
