import type { Hono } from "hono";
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
import { join } from "node:path";
import { homedir } from "node:os";
import { posthog, DISTINCT_ID } from "./posthog";

const KNITOR_DIR = join(homedir(), ".knitor");
export const MCP_CONFIG_PATH = join(KNITOR_DIR, "mcp.json");

export interface MCPDefinition {
  id: string;
  label: string;
  command: string;
  args: string[];
  requiredEnvVars: string[];
  envVarsLabels: Record<string, string>;
}

export const SUPPORTED_MCPS: MCPDefinition[] = [
  {
    id: "linear",
    label: "Linear",
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-linear"],
    requiredEnvVars: ["LINEAR_API_KEY"],
    envVarsLabels: { LINEAR_API_KEY: "Linear API Key" },
  },
  {
    id: "notion",
    label: "Notion",
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-notion"],
    requiredEnvVars: ["NOTION_API_TOKEN"],
    envVarsLabels: { NOTION_API_TOKEN: "Notion Integration Token" },
  },
  {
    id: "posthog",
    label: "PostHog",
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-posthog"],
    requiredEnvVars: ["POSTHOG_API_KEY", "POSTHOG_PROJECT_ID"],
    envVarsLabels: { 
      POSTHOG_API_KEY: "PostHog Personal API Key",
      POSTHOG_PROJECT_ID: "PostHog Project ID"
    },
  },
];

export interface MCPServerConfig {
  command: string;
  args: string[];
  env: Record<string, string>;
}

export interface MCPFile {
  mcpServers: Record<string, MCPServerConfig>;
}

export function loadMCPConfig(): MCPFile {
  if (!existsSync(MCP_CONFIG_PATH)) {
    return { mcpServers: {} };
  }
  try {
    return JSON.parse(readFileSync(MCP_CONFIG_PATH, "utf8"));
  } catch (e) {
    return { mcpServers: {} };
  }
}

export function saveMCPConfig(config: MCPFile) {
  if (!existsSync(KNITOR_DIR)) {
    mkdirSync(KNITOR_DIR, { recursive: true });
  }
  writeFileSync(MCP_CONFIG_PATH, JSON.stringify(config, null, 2), "utf8");
}

export function getMCPSettings() {
  const config = loadMCPConfig();
  
  return SUPPORTED_MCPS.map(def => {
    const server = config.mcpServers[def.id];
    const isEnabled = !!server;
    const configuredEnv = server?.env || {};
    
    // Check if all required vars exist and are not empty
    const isConfigured = def.requiredEnvVars.every(v => !!configuredEnv[v] && configuredEnv[v].trim().length > 0);
    
    return {
      id: def.id,
      label: def.label,
      enabled: isEnabled,
      isConfigured: isEnabled ? isConfigured : false, // only true if enabled AND configured
      requiredEnvVars: def.requiredEnvVars,
      envVarsLabels: def.envVarsLabels,
      currentEnv: configuredEnv,
    };
  });
}

export function toggleMCPServer(id: string, enabled: boolean) {
  const config = loadMCPConfig();
  if (!enabled) {
    delete config.mcpServers[id];
  } else {
    const def = SUPPORTED_MCPS.find(d => d.id === id);
    if (def) {
      config.mcpServers[id] = {
        command: def.command,
        args: def.args,
        env: config.mcpServers[id]?.env || {} // preserve existing env if any
      };
    }
  }
  saveMCPConfig(config);
}

export function updateMCPServerEnv(id: string, env: Record<string, string>) {
  const config = loadMCPConfig();
  if (config.mcpServers[id]) {
    config.mcpServers[id].env = { ...config.mcpServers[id].env, ...env };
    saveMCPConfig(config);
  } else {
    // If updating env for a disabled server, enable it first
    const def = SUPPORTED_MCPS.find(d => d.id === id);
    if (def) {
      config.mcpServers[id] = {
        command: def.command,
        args: def.args,
        env,
      };
      saveMCPConfig(config);
    }
  }
}

export function registerMCPRoutes(app: Hono) {
  app.get("/api/mcp", (c) => {
    return c.json(getMCPSettings());
  });

  app.put("/api/mcp/:id/toggle", async (c) => {
    const id = c.req.param("id");
    const { enabled } = await c.req.json();
    toggleMCPServer(id, enabled);
    posthog.capture({
      distinctId: DISTINCT_ID,
      event: "mcp server toggled",
      properties: { mcp_id: id, enabled },
    });
    return c.json({ success: true });
  });

  app.put("/api/mcp/:id/env", async (c) => {
    const id = c.req.param("id");
    const env = await c.req.json();
    updateMCPServerEnv(id, env);
    posthog.capture({
      distinctId: DISTINCT_ID,
      event: "mcp server env saved",
      properties: { mcp_id: id, var_count: Object.keys(env).length },
    });
    return c.json({ success: true });
  });
}
