/**
 * Lead Forms Tools (Tier 2 - Advanced)
 * Tools for managing lead gen forms and downloading leads
 */

import { z } from "zod";
import type { ToolRegistry } from "../server.js";
import type {
  LeadForm,
  Lead,
  ToolCategory,
  LoadTier,
} from "../types/meta-api.js";

export const category: ToolCategory = "leads";
export const tier: LoadTier = "advanced";

// ============================================================
// Shared Schemas
// ============================================================

const dateFilterSchema = z
  .object({
    since: z.string().describe("Start date (YYYY-MM-DD or ISO timestamp)"),
    until: z.string().describe("End date (YYYY-MM-DD or ISO timestamp)"),
  })
  .optional()
  .describe("Date range filter for leads");

// ============================================================
// Tool Registration
// ============================================================

export function registerLeadsTools(registry: ToolRegistry): void {
  const client = registry.getClient();

  // ============================================================
  // list_lead_forms
  // ============================================================
  registry.registerTool({
    name: "list_lead_forms",
    description: "List all lead gen forms for a Facebook Page",
    inputSchema: z.object({
      page_id: z.string().describe("Facebook Page ID"),
      limit: z
        .number()
        .optional()
        .describe("Maximum number of forms to return"),
    }),
    annotations: {
      title: "List Lead Forms",
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "leads",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const params = args as {
          page_id: string;
          limit?: number;
        };

        const queryParams: Record<string, string> = {
          fields:
            "id,name,status,locale,created_time,questions,privacy_policy_url,thank_you_page",
        };

        if (params.limit) {
          queryParams.limit = params.limit.toString();
        }

        const forms = (await client.getAllPages(
          `${params.page_id}/leadgen_forms`,
          queryParams
        )) as LeadForm[];

        const result = {
          forms: forms.map((form) => ({
            id: form.id,
            name: form.name,
            status: form.status,
            locale: form.locale,
            created_time: form.created_time,
            questions: form.questions?.map((q) => ({
              key: q.key,
              label: q.label,
              type: q.type,
            })),
            has_privacy_policy: !!form.privacy_policy_url,
            has_thank_you_page: !!form.thank_you_page,
          })),
          page_id: params.page_id,
          total_count: forms.length,
        };

        return {
          content: [
            {
              type: "text" as const,
              text: JSON.stringify(result, null, 2),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text" as const,
              text: `Error: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
          isError: true,
        };
      }
    },
  });

  // ============================================================
  // get_leads
  // ============================================================
  registry.registerTool({
    name: "get_leads",
    description: "Download lead data from a lead gen form",
    inputSchema: z.object({
      form_id: z.string().describe("Lead form ID"),
      limit: z.number().optional().describe("Maximum number of leads"),
      filtering: dateFilterSchema,
    }),
    annotations: {
      title: "Download Leads",
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "leads",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const params = args as {
          form_id: string;
          limit?: number;
          filtering?: {
            since: string;
            until: string;
          };
        };

        const queryParams: Record<string, string> = {
          fields: "id,created_time,field_data",
        };

        if (params.limit) {
          queryParams.limit = params.limit.toString();
        }

        if (params.filtering) {
          queryParams.filtering = JSON.stringify([
            {
              field: "time_created",
              operator: "GREATER_THAN",
              value: params.filtering.since,
            },
            {
              field: "time_created",
              operator: "LESS_THAN",
              value: params.filtering.until,
            },
          ]);
        }

        const leads = (await client.getAllPages(
          `${params.form_id}/leads`,
          queryParams
        )) as Lead[];

        // Format lead data
        const formattedLeads = leads.map((lead) => {
          const leadData: Record<string, string | string[]> = {
            id: lead.id,
            created_time: lead.created_time,
          };

          // Convert field_data array to object
          lead.field_data.forEach((field) => {
            leadData[field.name] =
              field.values.length === 1 ? field.values[0] : field.values;
          });

          return leadData;
        });

        const result = {
          leads: formattedLeads,
          form_id: params.form_id,
          total_count: leads.length,
          date_range: params.filtering,
          note: "Lead data contains PII. Handle according to privacy regulations (GDPR, CCPA, etc.)",
        };

        return {
          content: [
            {
              type: "text" as const,
              text: JSON.stringify(result, null, 2),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text" as const,
              text: `Error: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
          isError: true,
        };
      }
    },
  });

  // ============================================================
  // get_lead_form_stats
  // ============================================================
  registry.registerTool({
    name: "get_lead_form_stats",
    description: "Get performance statistics for a lead gen form",
    inputSchema: z.object({
      form_id: z.string().describe("Lead form ID"),
      date_preset: z
        .enum([
          "today",
          "yesterday",
          "last_7d",
          "last_14d",
          "last_28d",
          "last_30d",
          "last_90d",
          "this_month",
          "last_month",
        ])
        .optional()
        .describe("Date preset for stats (default: last_30d)"),
      time_range: z
        .object({
          since: z.string().describe("Start date (YYYY-MM-DD)"),
          until: z.string().describe("End date (YYYY-MM-DD)"),
        })
        .optional()
        .describe("Custom date range (alternative to date_preset)"),
    }),
    annotations: {
      title: "Get Lead Form Stats",
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "leads",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const params = args as {
          form_id: string;
          date_preset?: string;
          time_range?: {
            since: string;
            until: string;
          };
        };

        // Get form details
        const form = (await client.get(params.form_id, {
          fields: "id,name,status,page_id",
        })) as LeadForm;

        // Get ads using this form to calculate stats
        const adsResponse = (await client.get("/ads", {
          filtering: JSON.stringify([
            {
              field: "effective_status",
              operator: "IN",
              value: ["ACTIVE", "PAUSED"],
            },
          ]),
          fields: "id,name,adset_id,creative{id}",
          limit: "100",
        })) as {
          data: Array<{ id: string; name: string; adset_id: string }>;
        };

        // For each ad, check if it uses this lead form
        // This is simplified - in production, you'd need to check creative specs
        const relevantAds = adsResponse.data || [];

        // Get insights for ads using this form
        const insightsPromises = relevantAds.map(async (ad) => {
          try {
            const queryParams: Record<string, string> = {
              fields:
                "impressions,clicks,spend,ctr,cpc,actions,cost_per_action_type",
            };

            if (params.date_preset) {
              queryParams.date_preset = params.date_preset;
            } else if (params.time_range) {
              queryParams.time_range = JSON.stringify(params.time_range);
            } else {
              queryParams.date_preset = "last_30d";
            }

            const insights = (await client.get(
              `${ad.id}/insights`,
              queryParams
            )) as {
              data: Array<{
                impressions: string;
                clicks: string;
                spend: string;
                ctr: string;
                cpc: string;
                actions?: Array<{ action_type: string; value: string }>;
                cost_per_action_type?: Array<{
                  action_type: string;
                  value: string;
                }>;
              }>;
            };

            return insights.data[0];
          } catch {
            return null;
          }
        });

        const allInsights = (await Promise.all(insightsPromises)).filter(
          (insight): insight is NonNullable<typeof insight> => insight !== null
        );

        // Aggregate statistics
        const totalImpressions = allInsights.reduce(
          (sum, insight) => sum + parseInt(insight.impressions || "0", 10),
          0
        );
        const totalClicks = allInsights.reduce(
          (sum, insight) => sum + parseInt(insight.clicks || "0", 10),
          0
        );
        const totalSpend = allInsights.reduce(
          (sum, insight) => sum + parseFloat(insight.spend || "0"),
          0
        );

        // Extract lead actions
        const totalLeads = allInsights.reduce((sum, insight) => {
          const leadActions = (insight.actions || []).filter((action) =>
            action.action_type.includes("lead")
          );
          return (
            sum +
            leadActions.reduce((s, a) => s + parseInt(a.value || "0", 10), 0)
          );
        }, 0);

        // Calculate cost per lead
        const costPerLead = totalLeads > 0 ? totalSpend / totalLeads : 0;

        // Get actual lead count from form
        const leadsResponse = (await client.get(
          `${params.form_id}/leads`,
          {
            fields: "id,created_time",
            limit: "10000",
          }
        )) as { data: Lead[] };

        const actualLeadCount = leadsResponse.data.length;

        const result = {
          form_id: params.form_id,
          form_name: form.name,
          form_status: form.status,
          page_id: form.page_id,
          date_range: params.date_preset || params.time_range || "last_30d",
          performance: {
            impressions: totalImpressions,
            clicks: totalClicks,
            leads: totalLeads,
            spend: totalSpend,
            ctr:
              totalImpressions > 0 ? (totalClicks / totalImpressions) * 100 : 0,
            cost_per_click: totalClicks > 0 ? totalSpend / totalClicks : 0,
            cost_per_lead: costPerLead,
            conversion_rate:
              totalClicks > 0 ? (totalLeads / totalClicks) * 100 : 0,
          },
          actual_lead_count: actualLeadCount,
          note: "Stats are aggregated from ads using this form. Actual lead count may differ from reported leads in insights.",
        };

        return {
          content: [
            {
              type: "text" as const,
              text: JSON.stringify(result, null, 2),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text" as const,
              text: `Error: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
          isError: true,
        };
      }
    },
  });
}
