// ============================================
// TOOL REGISTRY — Lazy Loading Architecture
// ============================================

import type { ToolDefinition, ToolCategory } from "../types.js";

// Category metadata for lazy loading
export const TOOL_CATEGORIES: Record<ToolCategory, { label: string; description: string }> = {
  accounts: { label: "Account Management", description: "List accounts, get account info, billing, hierarchy" },
  campaigns: { label: "Campaign Management", description: "Create, update, pause, enable, remove campaigns and budgets" },
  ad_groups: { label: "Ad Group Management", description: "Create, update, pause ad groups within campaigns" },
  ads: { label: "Ad Management", description: "Create and manage responsive search ads, display ads" },
  keywords: { label: "Keywords & Targeting", description: "Add/remove keywords, keyword ideas, negatives, match types" },
  reporting: { label: "Performance & Reporting", description: "Campaign/ad group/keyword metrics, search terms, geo/device reports" },
  bidding: { label: "Bidding & Budget", description: "Bidding strategies, bid recommendations, budget optimization" },
  conversions: { label: "Conversion Tracking", description: "Conversion actions, metrics, offline uploads" },
  advanced: { label: "Advanced / Utilities", description: "Raw GAQL queries, export, change history, labels" },
};

// Core tools loaded on init (always available)
const CORE_TOOL_NAMES = new Set([
  "list_accessible_customers",
  "list_campaigns",
  "get_performance_summary",
  "get_campaign_performance",
  "run_gaql_query",
  "export_report",
  "get_keyword_ideas",
  "list_recommendations",
  "load_tools_category",
]);

// Full tool registry (populated by category modules)
const allTools = new Map<string, ToolDefinition>();
const loadedCategories = new Set<ToolCategory>();

/**
 * Register tools from a category module
 */
export function registerTools(tools: ToolDefinition[]): void {
  for (const tool of tools) {
    allTools.set(tool.name, tool);
  }
}

/**
 * Get core tools (always loaded)
 */
export function getCoreTools(): ToolDefinition[] {
  return Array.from(allTools.values()).filter((t) => CORE_TOOL_NAMES.has(t.name));
}

/**
 * Get all currently loaded tools
 */
export function getAllLoadedTools(): ToolDefinition[] {
  return Array.from(allTools.values());
}

/**
 * Get a specific tool by name
 */
export function getTool(name: string): ToolDefinition | undefined {
  return allTools.get(name);
}

/**
 * Load a tool category on demand
 */
export async function loadCategory(category: ToolCategory): Promise<ToolDefinition[]> {
  if (loadedCategories.has(category)) {
    return Array.from(allTools.values()).filter((t) => t.category === category);
  }

  // Dynamic import of category module
  const moduleMap: Record<ToolCategory, () => Promise<{ default: ToolDefinition[] }>> = {
    accounts: () => import("./accounts.js"),
    campaigns: () => import("./campaigns.js"),
    ad_groups: () => import("./ad-groups.js"),
    ads: () => import("./ads.js"),
    keywords: () => import("./keywords.js"),
    reporting: () => import("./reporting.js"),
    bidding: () => import("./bidding.js"),
    conversions: () => import("./conversions.js"),
    advanced: () => import("./advanced.js"),
  };

  const loader = moduleMap[category];
  if (!loader) throw new Error(`Unknown category: ${category}`);

  const mod = await loader();
  const tools = mod.default;
  registerTools(tools);
  loadedCategories.add(category);

  return tools;
}

/**
 * Check if a category has been loaded
 */
export function isCategoryLoaded(category: ToolCategory): boolean {
  return loadedCategories.has(category);
}

/**
 * Get list of available categories with load status
 */
export function getCategoryStatus(): Array<{ category: ToolCategory; loaded: boolean; label: string; description: string }> {
  return Object.entries(TOOL_CATEGORIES).map(([cat, meta]) => ({
    category: cat as ToolCategory,
    loaded: loadedCategories.has(cat as ToolCategory),
    label: meta.label,
    description: meta.description,
  }));
}

// ============================================
// META-TOOL: load_tools_category
// ============================================
export const loadToolsCategoryTool: ToolDefinition = {
  name: "load_tools_category",
  description:
    "Load additional Google Ads tools by category. Use this to access tools beyond the core set. " +
    "Categories: accounts, campaigns, ad_groups, ads, keywords, reporting, bidding, conversions, advanced. " +
    "Call with no category to see available categories and their status.",
  category: "advanced",
  annotations: {
    title: "Load Tool Category",
    readOnlyHint: true,
    destructiveHint: false,
    idempotentHint: true,
    openWorldHint: false,
  },
  inputSchema: {
    type: "object",
    properties: {
      category: {
        type: "string",
        description: "Category to load. Omit to list available categories.",
        enum: Object.keys(TOOL_CATEGORIES),
      },
    },
  },
  handler: async (args) => {
    if (!args.category) {
      const status = getCategoryStatus();
      const lines = status.map(
        (s) => `${s.loaded ? "✅" : "⬜"} **${s.label}** (\`${s.category}\`) — ${s.description}`
      );
      return {
        content: [
          {
            type: "text",
            text: `## Available Tool Categories\n\n${lines.join("\n")}\n\nUse \`load_tools_category\` with a category name to load its tools.`,
          },
        ],
      };
    }

    const category = args.category as ToolCategory;
    const tools = await loadCategory(category);
    const toolLines = tools.map((t) => {
      const badges: string[] = [];
      if (t.annotations.readOnlyHint) badges.push("📖");
      if (t.annotations.destructiveHint) badges.push("⚠️");
      if (t.annotations.openWorldHint) badges.push("🌐");
      return `- \`${t.name}\` ${badges.join("")} — ${t.description}`;
    });

    return {
      content: [
        {
          type: "text",
          text: `## Loaded: ${TOOL_CATEGORIES[category].label}\n\n${toolLines.join("\n")}\n\n${tools.length} tools now available.`,
        },
      ],
    };
  },
};

// Register the meta-tool
registerTools([loadToolsCategoryTool]);
