import React, { useState, useEffect } from "react";

const api = window.api;

type McpServerType = "stdio" | "sse" | "http";

interface McpServerConfig {
  type: McpServerType;
  command?: string;
  args?: string[];
  env?: Record<string, string>;
  url?: string;
  headers?: Record<string, string>;
}

type McpServersConfig = Record<string, McpServerConfig>;

interface EditingServer {
  originalName: string | null; // null = new server
  name: string;
  config: McpServerConfig;
}

const emptyConfig = (): McpServerConfig => ({
  type: "stdio",
  command: "",
  args: [],
  env: {},
});

export function McpSettings() {
  const [servers, setServers] = useState<McpServersConfig | null>(null);
  const [editing, setEditing] = useState<EditingServer | null>(null);
  const [saveStatus, setSaveStatus] = useState<"idle" | "saved" | "error">("idle");
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    api.getSettings(["mcpServers"]).then((settings) => {
      try {
        const parsed = settings["mcpServers"]
          ? JSON.parse(settings["mcpServers"])
          : {};
        setServers(parsed);
      } catch {
        setServers({});
        setError("Failed to parse saved MCP config");
      }
    });
  }, []);

  const saveServers = async (newServers: McpServersConfig) => {
    try {
      if (Object.keys(newServers).length === 0) {
        await api.deleteSetting("mcpServers");
      } else {
        await api.setSetting("mcpServers", JSON.stringify(newServers));
      }
      setServers(newServers);
      setSaveStatus("saved");
      setTimeout(() => setSaveStatus("idle"), 1500);
    } catch (e) {
      setSaveStatus("error");
      setError(String(e));
    }
  };

  const handleDelete = async (name: string) => {
    if (!servers) return;
    const { [name]: _, ...rest } = servers;
    await saveServers(rest);
  };

  const handleSaveEdit = async () => {
    if (!editing || !servers) return;
    const { originalName, name, config } = editing;

    if (!name.trim()) {
      setError("Server name is required");
      return;
    }

    // Validate based on type
    if (config.type === "stdio" && !config.command?.trim()) {
      setError("Command is required for stdio servers");
      return;
    }
    if ((config.type === "sse" || config.type === "http") && !config.url?.trim()) {
      setError("URL is required for SSE/HTTP servers");
      return;
    }

    const newServers = { ...servers };

    // If renaming, remove old entry
    if (originalName && originalName !== name) {
      delete newServers[originalName];
    }

    // Clean up config based on type
    const cleanConfig: McpServerConfig = { type: config.type };
    if (config.type === "stdio") {
      cleanConfig.command = config.command;
      if (config.args && config.args.length > 0) {
        cleanConfig.args = config.args.filter((a) => a.trim());
      }
      if (config.env && Object.keys(config.env).length > 0) {
        cleanConfig.env = config.env;
      }
    } else {
      cleanConfig.url = config.url;
      if (config.headers && Object.keys(config.headers).length > 0) {
        cleanConfig.headers = config.headers;
      }
    }

    newServers[name.trim()] = cleanConfig;
    await saveServers(newServers);
    setEditing(null);
    setError(null);
  };

  const handleCancelEdit = () => {
    setEditing(null);
    setError(null);
  };

  if (servers === null) {
    return (
      <div style={{ color: "var(--text-secondary)", fontSize: 12 }}>
        Loading...
      </div>
    );
  }

  const serverNames = Object.keys(servers);

  return (
    <div>
      <div className="settings-section-title">MCP Servers</div>
      <div className="settings-section-desc">
        Configure Model Context Protocol servers to give Claude access to
        external data sources like Jira, documentation, or databases. Servers
        are available in all phases.
      </div>

      {error && (
        <div className="mcp-error">{error}</div>
      )}

      {/* Server List */}
      {!editing && (
        <>
          <div className="mcp-server-list">
            {serverNames.length === 0 ? (
              <div className="mcp-empty">No MCP servers configured</div>
            ) : (
              serverNames.map((name) => (
                <div key={name} className="mcp-server-card">
                  <div className="mcp-server-info">
                    <span className="mcp-server-name">{name}</span>
                    <span className="mcp-server-type">{servers[name].type}</span>
                    <span className="mcp-server-detail">
                      {servers[name].type === "stdio"
                        ? servers[name].command
                        : servers[name].url}
                    </span>
                  </div>
                  <div className="mcp-server-actions">
                    <button
                      className="btn-secondary btn-small"
                      onClick={() =>
                        setEditing({
                          originalName: name,
                          name,
                          config: { ...servers[name] },
                        })
                      }
                    >
                      Edit
                    </button>
                    <button
                      className="btn-secondary btn-small btn-danger"
                      onClick={() => handleDelete(name)}
                    >
                      Delete
                    </button>
                  </div>
                </div>
              ))
            )}
          </div>

          <div className="settings-actions">
            <button
              className="btn-primary"
              onClick={() =>
                setEditing({
                  originalName: null,
                  name: "",
                  config: emptyConfig(),
                })
              }
            >
              Add Server
            </button>
            {saveStatus === "saved" && (
              <span className="settings-custom-badge">saved ✓</span>
            )}
          </div>
        </>
      )}

      {/* Edit Form */}
      {editing && (
        <ServerForm
          editing={editing}
          setEditing={setEditing}
          onSave={handleSaveEdit}
          onCancel={handleCancelEdit}
        />
      )}
    </div>
  );
}

interface ServerFormProps {
  editing: EditingServer;
  setEditing: React.Dispatch<React.SetStateAction<EditingServer | null>>;
  onSave: () => void;
  onCancel: () => void;
}

function ServerForm({ editing, setEditing, onSave, onCancel }: ServerFormProps) {
  const { name, config } = editing;

  const updateName = (newName: string) => {
    setEditing({ ...editing, name: newName });
  };

  const updateConfig = (updates: Partial<McpServerConfig>) => {
    setEditing({ ...editing, config: { ...config, ...updates } });
  };

  const updateArg = (index: number, value: string) => {
    const newArgs = [...(config.args || [])];
    newArgs[index] = value;
    updateConfig({ args: newArgs });
  };

  const addArg = () => {
    updateConfig({ args: [...(config.args || []), ""] });
  };

  const removeArg = (index: number) => {
    const newArgs = [...(config.args || [])];
    newArgs.splice(index, 1);
    updateConfig({ args: newArgs });
  };

  const updateEnvKey = (oldKey: string, newKey: string) => {
    const env = { ...config.env };
    const value = env[oldKey] || "";
    delete env[oldKey];
    if (newKey) env[newKey] = value;
    updateConfig({ env });
  };

  const updateEnvValue = (key: string, value: string) => {
    updateConfig({ env: { ...config.env, [key]: value } });
  };

  const addEnvVar = () => {
    const env = { ...config.env, "": "" };
    updateConfig({ env });
  };

  const removeEnvVar = (key: string) => {
    const env = { ...config.env };
    delete env[key];
    updateConfig({ env });
  };

  const updateHeaderKey = (oldKey: string, newKey: string) => {
    const headers = { ...config.headers };
    const value = headers[oldKey] || "";
    delete headers[oldKey];
    if (newKey) headers[newKey] = value;
    updateConfig({ headers });
  };

  const updateHeaderValue = (key: string, value: string) => {
    updateConfig({ headers: { ...config.headers, [key]: value } });
  };

  const addHeader = () => {
    const headers = { ...config.headers, "": "" };
    updateConfig({ headers });
  };

  const removeHeader = (key: string) => {
    const headers = { ...config.headers };
    delete headers[key];
    updateConfig({ headers });
  };

  return (
    <div className="mcp-server-form">
      <div className="mcp-form-title">
        {editing.originalName ? `Edit "${editing.originalName}"` : "Add Server"}
      </div>

      {/* Name */}
      <div className="mcp-form-field">
        <label>Name</label>
        <input
          type="text"
          value={name}
          onChange={(e) => updateName(e.target.value)}
          placeholder="e.g., jira, godoc"
          spellCheck={false}
        />
      </div>

      {/* Type */}
      <div className="mcp-form-field">
        <label>Type</label>
        <select
          value={config.type}
          onChange={(e) =>
            updateConfig({
              type: e.target.value as McpServerType,
              // Reset type-specific fields
              command: undefined,
              args: [],
              env: {},
              url: undefined,
              headers: {},
            })
          }
        >
          <option value="stdio">stdio (local command)</option>
          <option value="sse">sse (Server-Sent Events)</option>
          <option value="http">http (HTTP endpoint)</option>
        </select>
      </div>

      {/* stdio fields */}
      {config.type === "stdio" && (
        <>
          <div className="mcp-form-field">
            <label>Command</label>
            <input
              type="text"
              value={config.command || ""}
              onChange={(e) => updateConfig({ command: e.target.value })}
              placeholder="e.g., npx, node, python"
              spellCheck={false}
            />
          </div>

          <div className="mcp-form-field">
            <label>Arguments</label>
            <div className="mcp-array-builder">
              {(config.args || []).map((arg, i) => (
                <div key={i} className="mcp-array-row">
                  <input
                    type="text"
                    value={arg}
                    onChange={(e) => updateArg(i, e.target.value)}
                    placeholder={`Argument ${i + 1}`}
                    spellCheck={false}
                  />
                  <button
                    type="button"
                    className="btn-icon"
                    onClick={() => removeArg(i)}
                    title="Remove"
                  >
                    ×
                  </button>
                </div>
              ))}
              <button
                type="button"
                className="btn-secondary btn-small"
                onClick={addArg}
              >
                + Add Argument
              </button>
            </div>
          </div>

          <div className="mcp-form-field">
            <label>Environment Variables</label>
            <div className="mcp-kv-builder">
              {Object.entries(config.env || {}).map(([key, value]) => (
                <div key={key} className="mcp-kv-row">
                  <input
                    type="text"
                    value={key}
                    onChange={(e) => updateEnvKey(key, e.target.value)}
                    placeholder="KEY"
                    spellCheck={false}
                  />
                  <span className="mcp-kv-sep">=</span>
                  <input
                    type="text"
                    value={value}
                    onChange={(e) => updateEnvValue(key, e.target.value)}
                    placeholder="value"
                    spellCheck={false}
                  />
                  <button
                    type="button"
                    className="btn-icon"
                    onClick={() => removeEnvVar(key)}
                    title="Remove"
                  >
                    ×
                  </button>
                </div>
              ))}
              <button
                type="button"
                className="btn-secondary btn-small"
                onClick={addEnvVar}
              >
                + Add Variable
              </button>
            </div>
          </div>
        </>
      )}

      {/* sse/http fields */}
      {(config.type === "sse" || config.type === "http") && (
        <>
          <div className="mcp-form-field">
            <label>URL</label>
            <input
              type="text"
              value={config.url || ""}
              onChange={(e) => updateConfig({ url: e.target.value })}
              placeholder="https://..."
              spellCheck={false}
            />
          </div>

          <div className="mcp-form-field">
            <label>Headers</label>
            <div className="mcp-kv-builder">
              {Object.entries(config.headers || {}).map(([key, value]) => (
                <div key={key} className="mcp-kv-row">
                  <input
                    type="text"
                    value={key}
                    onChange={(e) => updateHeaderKey(key, e.target.value)}
                    placeholder="Header-Name"
                    spellCheck={false}
                  />
                  <span className="mcp-kv-sep">:</span>
                  <input
                    type="text"
                    value={value}
                    onChange={(e) => updateHeaderValue(key, e.target.value)}
                    placeholder="value"
                    spellCheck={false}
                  />
                  <button
                    type="button"
                    className="btn-icon"
                    onClick={() => removeHeader(key)}
                    title="Remove"
                  >
                    ×
                  </button>
                </div>
              ))}
              <button
                type="button"
                className="btn-secondary btn-small"
                onClick={addHeader}
              >
                + Add Header
              </button>
            </div>
          </div>
        </>
      )}

      {/* Form Actions */}
      <div className="mcp-form-actions">
        <button className="btn-secondary" onClick={onCancel}>
          Cancel
        </button>
        <button className="btn-primary" onClick={onSave}>
          Save
        </button>
      </div>
    </div>
  );
}
