#!/usr/bin/env node
// ============================================
// GOOGLE ADS MCP SERVER
// The definitive Google Ads MCP — 49 tools, 7 apps
// ============================================

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

import { GoogleAdsRestClient } from "./client.js";
import type { ToolDefinition, ToolCategory } from "./types.js";
import {
  registerTools,
  getAllLoadedTools,
  getTool,
  loadCategory,
  getCoreTools,
  loadToolsCategoryTool,
} from "./tools/index.js";

// ============================================
// BOOT: Load core tool categories eagerly
// ============================================
async function loadCoreTools(): Promise<void> {
  // These categories contain the "always available" core tools
  await Promise.all([
    loadCategory("accounts"),
    loadCategory("campaigns"),
    loadCategory("reporting"),
    loadCategory("advanced"),
  ]);
}

// ============================================
// SERVER SETUP
// ============================================
const server = new Server(
  {
    name: "google-ads-mcp",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

let client: GoogleAdsRestClient;

// ============================================
// LIST TOOLS — returns currently loaded tools
// ============================================
server.setRequestHandler(ListToolsRequestSchema, async () => {
  const tools = getAllLoadedTools();

  return {
    tools: tools.map((t) => ({
      name: t.name,
      description: t.description,
      inputSchema: t.inputSchema,
      _meta: t._meta,
      annotations: {
        title: t.annotations.title,
        readOnlyHint: t.annotations.readOnlyHint,
        destructiveHint: t.annotations.destructiveHint,
        idempotentHint: t.annotations.idempotentHint,
        openWorldHint: t.annotations.openWorldHint,
      },
    })),
  };
});

// ============================================
// CALL TOOL — dispatch to handler
// ============================================
server.setRequestHandler(CallToolRequestSchema, async (request): Promise<any> => {
  const { name, arguments: args = {} } = request.params;

  // Check loaded tools first
  let tool = getTool(name);

  // If not found, try lazy-loading all remaining categories
  if (!tool) {
    const lazyCategories: ToolCategory[] = [
      "ad_groups",
      "ads",
      "keywords",
      "bidding",
      "conversions",
    ];

    for (const cat of lazyCategories) {
      try {
        await loadCategory(cat);
      } catch {
        // Category may already be loaded
      }
    }
    tool = getTool(name);
  }

  if (!tool) {
    return {
      content: [
        {
          type: "text" as const,
          text: `Unknown tool: ${name}. Use \`load_tools_category\` to see available tools and categories.`,
        },
      ],
      isError: true,
    };
  }

  try {
    const result = await tool.handler(args, client);
    return result;
  } catch (error: any) {
    const message = error?.message || String(error);
    return {
      content: [
        {
          type: "text" as const,
          text: `Error executing ${name}: ${message}`,
        },
      ],
      isError: true,
    };
  }
});

// ============================================
// MAIN
// ============================================
async function main() {
  // Initialize API client
  try {
    client = GoogleAdsRestClient.fromEnv();
  } catch (error: any) {
    console.error(`[google-ads-mcp] Auth error: ${error.message}`);
    console.error(
      "[google-ads-mcp] Set GOOGLE_ADS_CONFIG (JSON) or individual env vars:\n" +
        "  GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET,\n" +
        "  GOOGLE_ADS_DEVELOPER_TOKEN, GOOGLE_ADS_REFRESH_TOKEN,\n" +
        "  GOOGLE_ADS_CUSTOMER_ID (optional default)"
    );
    process.exit(1);
  }

  // Load core tool categories
  await loadCoreTools();

  const coreCount = getAllLoadedTools().length;
  console.error(`[google-ads-mcp] Loaded ${coreCount} core tools (${5 + 8 + 7 + 4} from accounts, campaigns, reporting, advanced)`);
  console.error("[google-ads-mcp] Additional categories available via load_tools_category: ad_groups, ads, keywords, bidding, conversions");

  // Start MCP server on stdio
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("[google-ads-mcp] Server running on stdio");
}

main().catch((error) => {
  console.error("[google-ads-mcp] Fatal:", error);
  process.exit(1);
});
