// ============================================
// AD GROUP MANAGEMENT TOOLS
// ============================================

import type { ToolDefinition, GoogleAdsClient, ToolResult } from "../types.js";
import { microsToMoney, formatPercent, formatNumber } from "../types.js";

// ---- Helpers ----

function resolveCustomerId(args: Record<string, any>, client: GoogleAdsClient): string {
  const cid = args.customer_id || client.getCustomerId();
  if (!cid) throw new Error("customer_id is required — pass it explicitly or set GOOGLE_ADS_CUSTOMER_ID.");
  return cid.replace(/-/g, "");
}

function dateRangeClause(dateRange?: string): string {
  const allowed = ["LAST_7_DAYS", "LAST_30_DAYS", "LAST_90_DAYS", "THIS_MONTH", "LAST_MONTH", "TODAY", "YESTERDAY"];
  if (!dateRange) return "LAST_30_DAYS";
  const dr = dateRange.toUpperCase().replace(/ /g, "_");
  return allowed.includes(dr) ? dr : "LAST_30_DAYS";
}

function textResult(text: string): ToolResult {
  return { content: [{ type: "text", text }] };
}

function errorResult(message: string): ToolResult {
  return { content: [{ type: "text", text: `❌ ${message}` }], isError: true };
}

// ---- Tools ----

const tools: ToolDefinition[] = [
  // ============================
  // list_ad_groups
  // ============================
  {
    name: "list_ad_groups",
    description:
      "List ad groups for a campaign with status, type, bids, and performance metrics (impressions, clicks, cost, conversions, CTR).",
    category: "ad_groups",
    annotations: {
      title: "List Ad Groups",
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    inputSchema: {
      type: "object",
      properties: {
        customer_id: {
          type: "string",
          description: "Google Ads customer ID (defaults to configured account).",
        },
        campaign_id: {
          type: "string",
          description: "Campaign ID to list ad groups for.",
        },
        date_range: {
          type: "string",
          description: "Date range for metrics: LAST_7_DAYS, LAST_30_DAYS, LAST_90_DAYS, THIS_MONTH, LAST_MONTH, TODAY, YESTERDAY. Default: LAST_30_DAYS.",
          enum: ["LAST_7_DAYS", "LAST_30_DAYS", "LAST_90_DAYS", "THIS_MONTH", "LAST_MONTH", "TODAY", "YESTERDAY"],
        },
        status_filter: {
          type: "string",
          description: "Filter by ad group status.",
          enum: ["ENABLED", "PAUSED", "REMOVED"],
        },
        limit: {
          type: "number",
          description: "Maximum number of ad groups to return (default: 50).",
        },
      },
      required: ["campaign_id"],
    },
    _meta: {
      labels: {
        category: "ad_groups",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args, client) => {
      const cid = resolveCustomerId(args, client);
      const dr = dateRangeClause(args.date_range);
      const limit = Math.min(args.limit || 50, 500);

      let query = `
        SELECT
          ad_group.id,
          ad_group.name,
          ad_group.status,
          ad_group.type,
          ad_group.cpc_bid_micros,
          ad_group.resource_name,
          campaign.id,
          campaign.name,
          metrics.impressions,
          metrics.clicks,
          metrics.cost_micros,
          metrics.conversions,
          metrics.ctr,
          metrics.average_cpc
        FROM ad_group
        WHERE campaign.id = ${args.campaign_id}
          AND segments.date DURING ${dr}`;

      if (args.status_filter) {
        query += `\n          AND ad_group.status = '${args.status_filter}'`;
      }

      query += `\n        ORDER BY metrics.cost_micros DESC\n        LIMIT ${limit}`;

      const rows = await client.query(cid, query);

      if (!rows.length) {
        return textResult("No ad groups found for this campaign and filter.");
      }

      const lines = rows.map((r: any) => {
        const ag = r.adGroup || {};
        const m = r.metrics || {};
        const cpcBid = ag.cpcBidMicros ? `$${microsToMoney(ag.cpcBidMicros)}` : "—";
        return [
          `**${ag.name || "Unnamed"}** (ID: ${ag.id})`,
          `  Status: ${ag.status || "UNKNOWN"} | Type: ${ag.type || "—"} | Max CPC Bid: ${cpcBid}`,
          `  Impressions: ${formatNumber(m.impressions || 0)} | Clicks: ${formatNumber(m.clicks || 0)} | CTR: ${formatPercent(m.ctr || 0)}`,
          `  Cost: $${microsToMoney(m.costMicros || 0)} | Avg CPC: $${microsToMoney(m.averageCpc || 0)} | Conversions: ${formatNumber(m.conversions || 0)}`,
        ].join("\n");
      });

      return textResult(
        `## Ad Groups for Campaign ${args.campaign_id} (${dr.replace(/_/g, " ")})\n\n${lines.join("\n\n")}\n\n_${rows.length} ad group(s) returned._`
      );
    },
  },

  // ============================
  // get_ad_group
  // ============================
  {
    name: "get_ad_group",
    description: "Get detailed information about a single ad group by ID, including status, type, bids, and performance metrics.",
    category: "ad_groups",
    annotations: {
      title: "Get Ad Group Details",
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    inputSchema: {
      type: "object",
      properties: {
        customer_id: {
          type: "string",
          description: "Google Ads customer ID (defaults to configured account).",
        },
        ad_group_id: {
          type: "string",
          description: "The ad group ID to retrieve.",
        },
      },
      required: ["ad_group_id"],
    },
    _meta: {
      labels: {
        category: "ad_groups",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args, client) => {
      const cid = resolveCustomerId(args, client);

      const query = `
        SELECT
          ad_group.id,
          ad_group.name,
          ad_group.status,
          ad_group.type,
          ad_group.cpc_bid_micros,
          ad_group.cpm_bid_micros,
          ad_group.target_cpa_micros,
          ad_group.target_roas,
          ad_group.resource_name,
          ad_group.ad_rotation_mode,
          ad_group.effective_target_cpa_micros,
          ad_group.effective_target_roas,
          campaign.id,
          campaign.name,
          campaign.status,
          metrics.impressions,
          metrics.clicks,
          metrics.cost_micros,
          metrics.conversions,
          metrics.conversions_value,
          metrics.ctr,
          metrics.average_cpc,
          metrics.average_cpm
        FROM ad_group
        WHERE ad_group.id = ${args.ad_group_id}
          AND segments.date DURING LAST_30_DAYS
        LIMIT 1`;

      const rows = await client.query(cid, query);

      if (!rows.length) {
        return errorResult(`Ad group ${args.ad_group_id} not found.`);
      }

      const r = rows[0];
      const ag = r.adGroup || {};
      const camp = r.campaign || {};
      const m = r.metrics || {};

      const details = [
        `## Ad Group: ${ag.name || "Unnamed"}`,
        "",
        `| Field | Value |`,
        `|-------|-------|`,
        `| ID | ${ag.id} |`,
        `| Status | ${ag.status} |`,
        `| Type | ${ag.type || "—"} |`,
        `| Campaign | ${camp.name || "—"} (ID: ${camp.id || "—"}, ${camp.status || "—"}) |`,
        `| Ad Rotation | ${ag.adRotationMode || "—"} |`,
        `| Max CPC Bid | ${ag.cpcBidMicros ? "$" + microsToMoney(ag.cpcBidMicros) : "—"} |`,
        `| Max CPM Bid | ${ag.cpmBidMicros ? "$" + microsToMoney(ag.cpmBidMicros) : "—"} |`,
        `| Target CPA | ${ag.targetCpaMicros ? "$" + microsToMoney(ag.targetCpaMicros) : "—"} |`,
        `| Target ROAS | ${ag.targetRoas || "—"} |`,
        `| Effective Target CPA | ${ag.effectiveTargetCpaMicros ? "$" + microsToMoney(ag.effectiveTargetCpaMicros) : "—"} |`,
        `| Effective Target ROAS | ${ag.effectiveTargetRoas || "—"} |`,
        "",
        `### Performance (Last 30 Days)`,
        `| Metric | Value |`,
        `|--------|-------|`,
        `| Impressions | ${formatNumber(m.impressions || 0)} |`,
        `| Clicks | ${formatNumber(m.clicks || 0)} |`,
        `| CTR | ${formatPercent(m.ctr || 0)} |`,
        `| Cost | $${microsToMoney(m.costMicros || 0)} |`,
        `| Avg CPC | $${microsToMoney(m.averageCpc || 0)} |`,
        `| Avg CPM | $${microsToMoney(m.averageCpm || 0)} |`,
        `| Conversions | ${formatNumber(m.conversions || 0)} |`,
        `| Conversion Value | $${(m.conversionsValue || 0).toFixed(2)} |`,
      ];

      return textResult(details.join("\n"));
    },
  },

  // ============================
  // create_ad_group
  // ============================
  {
    name: "create_ad_group",
    description:
      "Create a new ad group in a campaign. ⚠️ This will create a live ad group in your Google Ads account. " +
      "Make sure the campaign exists and you intend to create this ad group before proceeding.",
    category: "ad_groups",
    annotations: {
      title: "Create Ad Group",
      readOnlyHint: false,
      destructiveHint: true,
      idempotentHint: false,
      openWorldHint: false,
    },
    inputSchema: {
      type: "object",
      properties: {
        customer_id: {
          type: "string",
          description: "Google Ads customer ID (defaults to configured account).",
        },
        campaign_id: {
          type: "string",
          description: "Campaign ID to create the ad group in.",
        },
        name: {
          type: "string",
          description: "Name for the new ad group.",
        },
        type: {
          type: "string",
          description: "Ad group type.",
          enum: [
            "SEARCH_STANDARD",
            "DISPLAY_STANDARD",
            "SHOPPING_PRODUCT_ADS",
            "HOTEL_ADS",
            "SHOPPING_SMART_ADS",
            "VIDEO_BUMPER",
            "VIDEO_TRUE_VIEW_IN_STREAM",
            "VIDEO_TRUE_VIEW_IN_DISPLAY",
            "VIDEO_RESPONSIVE",
            "SMART_CAMPAIGN_ADS",
          ],
        },
        cpc_bid_amount: {
          type: "number",
          description: "Max CPC bid in dollars (e.g. 1.50 for $1.50). Will be converted to micros.",
        },
        status: {
          type: "string",
          description: "Initial status. Default: ENABLED.",
          enum: ["ENABLED", "PAUSED"],
        },
      },
      required: ["campaign_id", "name"],
    },
    _meta: {
      labels: {
        category: "ad_groups",
        access: "delete",
        complexity: "simple"
      }
    },
    handler: async (args, client) => {
      const cid = resolveCustomerId(args, client);

      const resource: Record<string, any> = {
        campaign: `customers/${cid}/campaigns/${args.campaign_id}`,
        name: args.name,
        status: args.status || "ENABLED",
      };

      if (args.type) {
        resource.type = args.type;
      }

      if (args.cpc_bid_amount != null) {
        resource.cpcBidMicros = String(Math.round(args.cpc_bid_amount * 1_000_000));
      }

      const result = await client.mutate(cid, [
        {
          entity: "adGroup",
          operation: "create",
          resource,
        },
      ]);

      const createdName =
        result?.mutateOperationResponses?.[0]?.adGroupResult?.resourceName ||
        result?.results?.[0]?.resourceName ||
        "unknown";

      return textResult(
        `✅ Ad group **${args.name}** created successfully.\n\n` +
          `- Campaign: ${args.campaign_id}\n` +
          `- Type: ${args.type || "default"}\n` +
          `- Max CPC: ${args.cpc_bid_amount != null ? "$" + args.cpc_bid_amount.toFixed(2) : "—"}\n` +
          `- Status: ${args.status || "ENABLED"}\n` +
          `- Resource: \`${createdName}\``
      );
    },
  },

  // ============================
  // update_ad_group
  // ============================
  {
    name: "update_ad_group",
    description:
      "Update an existing ad group's settings (name, CPC bid, target CPA, target ROAS, ad rotation). " +
      "⚠️ This modifies a live ad group. Only provided fields will be updated.",
    category: "ad_groups",
    annotations: {
      title: "Update Ad Group",
      readOnlyHint: false,
      destructiveHint: true,
      idempotentHint: true,
      openWorldHint: false,
    },
    inputSchema: {
      type: "object",
      properties: {
        customer_id: {
          type: "string",
          description: "Google Ads customer ID (defaults to configured account).",
        },
        ad_group_id: {
          type: "string",
          description: "The ad group ID to update.",
        },
        name: {
          type: "string",
          description: "New ad group name.",
        },
        cpc_bid_amount: {
          type: "number",
          description: "New max CPC bid in dollars (e.g. 2.00 for $2.00).",
        },
        target_cpa_amount: {
          type: "number",
          description: "Target CPA in dollars.",
        },
        target_roas: {
          type: "number",
          description: "Target ROAS (e.g. 4.0 for 400%).",
        },
        ad_rotation_mode: {
          type: "string",
          description: "Ad rotation mode.",
          enum: ["OPTIMIZE", "ROTATE_FOREVER"],
        },
      },
      required: ["ad_group_id"],
    },
    _meta: {
      labels: {
        category: "ad_groups",
        access: "delete",
        complexity: "simple"
      }
    },
    handler: async (args, client) => {
      const cid = resolveCustomerId(args, client);
      const resourceName = `customers/${cid}/adGroups/${args.ad_group_id}`;

      const resource: Record<string, any> = { resourceName };
      const updateFields: string[] = [];

      if (args.name != null) {
        resource.name = args.name;
        updateFields.push("name");
      }
      if (args.cpc_bid_amount != null) {
        resource.cpcBidMicros = String(Math.round(args.cpc_bid_amount * 1_000_000));
        updateFields.push("cpc_bid_micros");
      }
      if (args.target_cpa_amount != null) {
        resource.targetCpaMicros = String(Math.round(args.target_cpa_amount * 1_000_000));
        updateFields.push("target_cpa_micros");
      }
      if (args.target_roas != null) {
        resource.targetRoas = args.target_roas;
        updateFields.push("target_roas");
      }
      if (args.ad_rotation_mode) {
        resource.adRotationMode = args.ad_rotation_mode;
        updateFields.push("ad_rotation_mode");
      }

      if (!updateFields.length) {
        return errorResult("No fields provided to update. Specify at least one field (name, cpc_bid_amount, target_cpa_amount, target_roas, ad_rotation_mode).");
      }

      await client.mutate(cid, [
        {
          entity: "adGroup",
          operation: "update",
          resource,
          updateMask: updateFields.join(","),
        },
      ]);

      return textResult(
        `✅ Ad group **${args.ad_group_id}** updated successfully.\n\nUpdated fields: ${updateFields.join(", ")}`
      );
    },
  },

  // ============================
  // pause_ad_group
  // ============================
  {
    name: "pause_ad_group",
    description:
      "Pause an ad group, stopping all ads within it from serving. ⚠️ This immediately pauses a live ad group.",
    category: "ad_groups",
    annotations: {
      title: "Pause Ad Group",
      readOnlyHint: false,
      destructiveHint: true,
      idempotentHint: true,
      openWorldHint: false,
    },
    inputSchema: {
      type: "object",
      properties: {
        customer_id: {
          type: "string",
          description: "Google Ads customer ID (defaults to configured account).",
        },
        ad_group_id: {
          type: "string",
          description: "The ad group ID to pause.",
        },
      },
      required: ["ad_group_id"],
    },
    _meta: {
      labels: {
        category: "ad_groups",
        access: "delete",
        complexity: "simple"
      }
    },
    handler: async (args, client) => {
      const cid = resolveCustomerId(args, client);
      const resourceName = `customers/${cid}/adGroups/${args.ad_group_id}`;

      await client.mutate(cid, [
        {
          entity: "adGroup",
          operation: "update",
          resource: { resourceName, status: "PAUSED" },
          updateMask: "status",
        },
      ]);

      return textResult(`⏸️ Ad group **${args.ad_group_id}** has been paused.`);
    },
  },

  // ============================
  // enable_ad_group
  // ============================
  {
    name: "enable_ad_group",
    description:
      "Enable a paused ad group, allowing its ads to begin serving again. ⚠️ This immediately enables a live ad group.",
    category: "ad_groups",
    annotations: {
      title: "Enable Ad Group",
      readOnlyHint: false,
      destructiveHint: true,
      idempotentHint: true,
      openWorldHint: false,
    },
    inputSchema: {
      type: "object",
      properties: {
        customer_id: {
          type: "string",
          description: "Google Ads customer ID (defaults to configured account).",
        },
        ad_group_id: {
          type: "string",
          description: "The ad group ID to enable.",
        },
      },
      required: ["ad_group_id"],
    },
    _meta: {
      labels: {
        category: "ad_groups",
        access: "delete",
        complexity: "simple"
      }
    },
    handler: async (args, client) => {
      const cid = resolveCustomerId(args, client);
      const resourceName = `customers/${cid}/adGroups/${args.ad_group_id}`;

      await client.mutate(cid, [
        {
          entity: "adGroup",
          operation: "update",
          resource: { resourceName, status: "ENABLED" },
          updateMask: "status",
        },
      ]);

      return textResult(`▶️ Ad group **${args.ad_group_id}** has been enabled.`);
    },
  },
];

export default tools;
