/**
 * CultGuard Autonomous Monitoring Extension for pi-agent
 * 
 * Provides OSINT monitoring tools and workflows for continuous surveillance
 * of social media entities, content analysis, and evidence collection.
 */

import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { Type } from "@sinclair/typebox";
import { StringEnum } from "@mariozechner/pi-ai";
import { randomUUID } from "node:crypto";

// ─── Extension State ────────────────────────────────────────────────────────

interface MonitoringState {
  activeInvestigations: Set<string>;
  lastScrapeTime: Map<string, number>;
  alertThresholds: AlertThresholds;
}

interface AlertThresholds {
  postSpike: number;        // Alert if >N posts in M minutes
  reactionSpike: number;    // Alert if reactions exceed threshold
  suspiciousKeywords: string[];
  newEntityThreshold: number;
}

const DEFAULT_THRESHOLDS: AlertThresholds = {
  postSpike: 10,
  reactionSpike: 1000,
  suspiciousKeywords: ["election", "vote", "protest", "breaking", "urgent"],
  newEntityThreshold: 5,
};

let monitoringState: MonitoringState = {
  activeInvestigations: new Set(),
  lastScrapeTime: new Map(),
  alertThresholds: DEFAULT_THRESHOLDS,
};

type QueryRow = Record<string, unknown>;
type QueryResult<T extends QueryRow = QueryRow> = { rows: T[] };
type QueryFn = <T extends QueryRow = QueryRow>(
  text: string,
  values?: unknown[],
) => Promise<QueryResult<T>>;

function toSqlLiteral(value: unknown): string {
  if (value === null || value === undefined) return "NULL";
  if (typeof value === "number") {
    if (!Number.isFinite(value)) throw new Error("Non-finite number in SQL parameter");
    return String(value);
  }
  if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
  if (value instanceof Date) return `'${value.toISOString().replace(/'/g, "''")}'::timestamptz`;
  if (typeof value === "object") return `'${JSON.stringify(value).replace(/'/g, "''")}'::jsonb`;
  return `'${String(value).replace(/'/g, "''")}'`;
}

function renderSql(text: string, values: unknown[] = []): string {
  let sql = text;
  for (let i = values.length; i >= 1; i -= 1) {
    sql = sql.replace(new RegExp(`\\$${i}(?!\\d)`, "g"), toSqlLiteral(values[i - 1]));
  }
  return sql;
}

// ─── Extension Entry Point ──────────────────────────────────────────────────

export default function (pi: ExtensionAPI) {
  const createQuery = (signal?: AbortSignal): QueryFn => {
    return async <T extends QueryRow = QueryRow>(text: string, values: unknown[] = []) => {
      const sql = renderSql(text, values);
      const wrappedSql = `WITH q AS (${sql}) SELECT COALESCE(json_agg(q), '[]'::json) FROM q;`;
      const result = await pi.exec(
        "psql",
        ["-X", "-A", "-t", "-q", "cultguard", "-c", wrappedSql],
        { signal, timeout: 30_000 },
      );

      if (result.code !== 0) {
        const stderr = result.stderr.trim();
        throw new Error(
          stderr || "psql query failed. Run pi inside `devenv shell` so the pure dev environment is active.",
        );
      }

      const output = result.stdout.trim();
      const rows = output ? JSON.parse(output) : [];
      return { rows: Array.isArray(rows) ? (rows as T[]) : [] };
    };
  };

  // Restore state on session start
  pi.on("session_start", async (_event, ctx) => {
    ctx.ui.notify("CultGuard Monitoring Extension loaded", "info");
    
    // Reconstruct state from session history if available
    const entries = ctx.sessionManager.getEntries();
    for (const entry of entries) {
      if (entry.type === "message" && entry.message.role === "toolResult") {
        if (entry.message.toolName === "start_monitoring") {
          const invId = entry.message.details?.investigationId as string;
          if (invId) {
            monitoringState.activeInvestigations.add(invId);
          }
        }
      }
    }
  });

  // ─── Custom Tools ────────────────────────────────────────────────────────

  /**
   * Start continuous monitoring of a Facebook page
   */
  pi.registerTool({
    name: "start_monitoring",
    label: "Start Monitoring",
    description: "Start autonomous monitoring of a Facebook page or entity. Sets up continuous surveillance with configurable intervals.",
    promptSnippet: "Monitor a Facebook page continuously",
    promptGuidelines: [
      "Use this tool to start long-term monitoring of suspicious pages",
      "Specify monitoring_interval_minutes based on page activity level (5-60 min)",
      "Enable auto_scrape to automatically collect new content",
    ],
    parameters: Type.Object({
      investigation_id: Type.String({ 
        description: "Investigation ID (e.g., 'lebanon-liberates-2026')" 
      }),
      page_url: Type.String({ 
        description: "Facebook page URL to monitor" 
      }),
      monitoring_interval_minutes: Type.Number({ 
        description: "How often to check for new content (5-1440)",
        minimum: 5,
        maximum: 1440,
        default: 30,
      }),
      auto_scrape: Type.Boolean({ 
        description: "Automatically scrape new posts/comments when detected",
        default: true,
      }),
      auto_ingest: Type.Boolean({ 
        description: "Automatically ingest media and evidence",
        default: true,
      }),
      alert_on_spike: Type.Boolean({ 
        description: "Send alerts when activity spikes detected",
        default: true,
      }),
    }),
    async execute(toolCallId, params, signal, onUpdate, ctx) {
      try {
        const query = createQuery(signal);

        // Validate investigation exists
        const invResult = await query(
          "SELECT id, name, status FROM investigations WHERE id = $1",
          [params.investigation_id]
        );
        
        if (invResult.rows.length === 0) {
          throw new Error(`Investigation '${params.investigation_id}' not found`);
        }

        // Create or update entity for the page
        const pageId = extractFacebookPageId(params.page_url);
        const entityId = `fb_page_${pageId}`;
        
        const entityResult = await query(
          `INSERT INTO entities (id, investigation_id, type, name, url, platform, collected_at, confidence, is_sock)
           VALUES ($1, $2, 'page', NULL, $3, 'facebook', NOW(), 100, false)
           ON CONFLICT (id) DO UPDATE SET 
             url = $3,
             collected_at = NOW()
           RETURNING id`,
          [entityId, params.investigation_id, params.page_url]
        );

        // Register investigation for monitoring
        monitoringState.activeInvestigations.add(params.investigation_id);
        monitoringState.lastScrapeTime.set(params.investigation_id, Date.now());

        // Schedule next monitoring cycle (using pi's event system)
        const nextCheck = params.monitoring_interval_minutes * 60 * 1000;
        
        // Send follow-up message to trigger next monitoring cycle
        const followUpMessage = {
          customType: "cultguard-monitoring",
          content: `Monitoring cycle for ${params.investigation_id}. Next check in ${params.monitoring_interval_minutes} minutes.`,
          display: false,
          details: {
            investigationId: params.investigation_id,
            pageUrl: params.page_url,
            nextCheck: Date.now() + nextCheck,
          },
        };

        pi.sendMessage(followUpMessage, {
          deliverAs: "followUp",
          triggerTurn: false,
        });

        return {
          content: [
            {
              type: "text",
              text: `✅ Started monitoring ${params.page_url}\n\n` +
                    `• Investigation: ${params.investigation_id}\n` +
                    `• Check interval: ${params.monitoring_interval_minutes} minutes\n` +
                    `• Auto-scrape: ${params.auto_scrape ? "enabled" : "disabled"}\n` +
                    `• Auto-ingest: ${params.auto_ingest ? "enabled" : "disabled"}\n` +
                    `• Alert on spike: ${params.alert_on_spike ? "enabled" : "disabled"}\n\n` +
                    `Monitoring state persisted. Agent will check for new content automatically.`,
            },
          ],
          details: {
            investigationId: params.investigation_id,
            entityId,
            pageUrl: params.page_url,
            monitoringInterval: params.monitoring_interval_minutes,
            nextCheck: Date.now() + nextCheck,
          },
        };
      } catch (error) {
        const message = error instanceof Error ? error.message : "Unknown error";
        return {
          content: [{ type: "text", text: `❌ Failed to start monitoring: ${message}` }],
          details: { error: message },
          isError: true,
        };
      }
    },
    renderResult(result, options, theme, context) {
      if (result.isError) {
        return [{ type: "text", text: result.content[0].text, style: theme.error }];
      }
      return result.content.map((c) => ({ type: "text" as const, text: c.text }));
    },
  });

  /**
   * Check for new content since last monitoring cycle
   */
  pi.registerTool({
    name: "check_new_content",
    label: "Check New Content",
    description: "Check monitored pages for new posts, comments, or activity since last check. Returns summary of new content.",
    promptSnippet: "Check for new posts and activity",
    parameters: Type.Object({
      investigation_id: Type.String({ 
        description: "Investigation ID to check" 
      }),
      since_minutes: Type.Number({ 
        description: "Look back this many minutes",
        default: 60,
        minimum: 5,
        maximum: 1440,
      }),
      include_comments: Type.Boolean({ 
        description: "Include comment analysis",
        default: true,
      }),
    }),
    async execute(toolCallId, params, signal, onUpdate, ctx) {
      try {
        const query = createQuery(signal);
        const since = new Date(Date.now() - params.since_minutes * 60 * 1000);
        
        // Get all monitored entities for this investigation
        const entitiesResult = await query(
          `SELECT id, name, url, platform 
           FROM entities 
           WHERE investigation_id = $1 
           AND platform = 'facebook' 
           AND type = 'page'`,
          [params.investigation_id]
        );

        if (entitiesResult.rows.length === 0) {
          return {
            content: [{ 
              type: "text", 
              text: `No Facebook pages being monitored for investigation ${params.investigation_id}`,
            }],
            details: { pageCount: 0 },
          };
        }

        // Check for new content per entity
        const summaries = [];
        for (const entity of entitiesResult.rows) {
          const newContentResult = await query(
            `SELECT type, COUNT(*) as count, 
                    MAX(published_at) as latest,
                    SUM(COALESCE(likes, 0)) as total_likes,
                    SUM(COALESCE(shares, 0)) as total_shares,
                    SUM(COALESCE(comments, 0)) as total_comments
             FROM content 
             WHERE entity_id = $1 
             AND collected_at > $2
             GROUP BY type`,
            [entity.id, since]
          );

          if (newContentResult.rows.length > 0) {
            summaries.push({
              entityId: entity.id,
              entityName: entity.name,
              entityUrl: entity.url,
              content: newContentResult.rows,
            });
          }
        }

        if (summaries.length === 0) {
          return {
            content: [{ 
              type: "text", 
              text: `✅ No new content detected in the last ${params.since_minutes} minutes`,
            }],
            details: { checkedEntities: entitiesResult.rows.length, newContent: 0 },
          };
        }

        // Format summary
        let summaryText = `📊 New Content Summary (last ${params.since_minutes} minutes)\n\n`;
        let totalNewContent = 0;

        for (const summary of summaries) {
          summaryText += `\n**${summary.entityName || summary.entityUrl}**\n`;
          for (const row of summary.content) {
            summaryText += `• ${row.type}: ${row.count} (latest: ${row.latest})\n`;
            totalNewContent += Number(row.count);
          }
        }

        // Check for activity spikes
        const hasSpike = totalNewContent > monitoringState.alertThresholds.postSpike;
        if (hasSpike) {
          summaryText += `\n⚠️ **ALERT**: Activity spike detected (${totalNewContent} items)`;
          
          // Send notification
          ctx.ui.notify(`Activity spike: ${totalNewContent} new items`, "warning");
        }

        return {
          content: [{ type: "text", text: summaryText }],
          details: {
            checkedEntities: entitiesResult.rows.length,
            newContent: totalNewContent,
            hasSpike,
            summaries,
          },
        };
      } catch (error) {
        const message = error instanceof Error ? error.message : "Unknown error";
        return {
          content: [{ type: "text", text: `❌ Failed to check content: ${message}` }],
          details: { error: message },
          isError: true,
        };
      }
    },
  });

  /**
   * Analyze content for suspicious patterns
   */
  pi.registerTool({
    name: "analyze_content",
    label: "Analyze Content",
    description: "Analyze content for suspicious patterns, coordinated behavior, or policy violations using LLM reasoning.",
    promptSnippet: "Analyze content for suspicious patterns",
    promptGuidelines: [
      "Use this tool when new content needs classification or risk assessment",
      "Specify content_type to focus analysis (post, comment, ad)",
      "Enable coordinated_detection to check for astroturfing patterns",
    ],
    parameters: Type.Object({
      content_ids: Type.Array(Type.String(), { 
        description: "List of content IDs to analyze" 
      }),
      analysis_type: StringEnum(["risk", "coordination", "sentiment", "claims"] as const, {
        description: "Type of analysis to perform",
        default: "risk",
      }),
      include_llm: Type.Boolean({ 
        description: "Use LLM for deep analysis (costs tokens)",
        default: true,
      }),
    }),
    async execute(toolCallId, params, signal, onUpdate, ctx) {
      try {
        const query = createQuery(signal);

        // Fetch content details
        const placeholders = params.content_ids.map((_, i) => `$${i + 2}`).join(",");
        const contentResult = await query(
          `SELECT id, entity_id, type, text, published_at, likes, shares, comments, reactions
           FROM content 
           WHERE id IN (${placeholders})`,
          [params.analysis_type, ...params.content_ids]
        );

        if (contentResult.rows.length === 0) {
          return {
            content: [{ type: "text", text: "No content found for specified IDs" }],
            details: { analyzedCount: 0 },
          };
        }

        // Perform analysis
        const analyses = [];
        for (const content of contentResult.rows) {
          const analysis: any = {
            contentId: content.id,
            type: content.type,
            riskScore: 0,
            flags: [],
          };

          // Basic heuristic analysis
          if (content.text) {
            // Check for suspicious keywords
            for (const keyword of monitoringState.alertThresholds.suspiciousKeywords) {
              if (content.text.toLowerCase().includes(keyword)) {
                analysis.flags.push(`keyword:${keyword}`);
                analysis.riskScore += 10;
              }
            }

            // Check for urgency/manipulation language
            if (/(breaking|urgent|share now|must see)/i.test(content.text)) {
              analysis.flags.push("urgency_language");
              analysis.riskScore += 15;
            }
          }

          // Check engagement patterns
          const totalEngagement = (content.likes || 0) + (content.shares || 0) + (content.comments || 0);
          if (totalEngagement > monitoringState.alertThresholds.reactionSpike) {
            analysis.flags.push("high_engagement");
            analysis.riskScore += 20;
          }

          analyses.push(analysis);
        }

        // If LLM analysis requested, send follow-up for deep analysis
        if (params.include_llm) {
          pi.sendUserMessage(
            `Perform deep analysis on ${params.content_ids.length} content items. ` +
            `Focus on: ${params.analysis_type}. Look for coordinated behavior, manipulation tactics, and policy violations.`,
            { deliverAs: "followUp" }
          );
        }

        // Format results
        const flaggedContent = analyses.filter(a => a.riskScore > 20);
        let summaryText = `📈 Content Analysis Complete\n\n`;
        summaryText += `• Analyzed: ${analyses.length} items\n`;
        summaryText += `• Flagged: ${flaggedContent.length} items (risk score >20)\n\n`;

        if (flaggedContent.length > 0) {
          summaryText += `**High-Risk Content:**\n`;
          for (const item of flaggedContent) {
            summaryText += `• ${item.contentId}: risk=${item.riskScore}, flags=[${item.flags.join(", ")}]\n`;
          }
        }

        return {
          content: [{ type: "text", text: summaryText }],
          details: {
            analyzedCount: analyses.length,
            flaggedCount: flaggedContent.length,
            analyses,
          },
        };
      } catch (error) {
        const message = error instanceof Error ? error.message : "Unknown error";
        return {
          content: [{ type: "text", text: `❌ Analysis failed: ${message}` }],
          details: { error: message },
          isError: true,
        };
      }
    },
  });

  /**
   * Generate monitoring report
   */
  pi.registerTool({
    name: "generate_report",
    label: "Generate Report",
    description: "Generate comprehensive monitoring report for an investigation including timeline, entities, and key findings.",
    promptSnippet: "Generate investigation monitoring report",
    parameters: Type.Object({
      investigation_id: Type.String({ 
        description: "Investigation ID" 
      }),
      time_range_hours: Type.Number({ 
        description: "Report time range in hours",
        default: 24,
        minimum: 1,
        maximum: 720,
      }),
      include_network: Type.Boolean({ 
        description: "Include entity network analysis",
        default: true,
      }),
      format: StringEnum(["summary", "detailed", "executive"] as const, {
        description: "Report detail level",
        default: "summary",
      }),
    }),
    async execute(toolCallId, params, signal, onUpdate, ctx) {
      try {
        const query = createQuery(signal);
        const since = new Date(Date.now() - params.time_range_hours * 60 * 60 * 1000);
        
        // Get investigation details
        const invResult = await query(
          "SELECT id, name, description, status FROM investigations WHERE id = $1",
          [params.investigation_id]
        );

        if (invResult.rows.length === 0) {
          throw new Error(`Investigation '${params.investigation_id}' not found`);
        }

        const investigation = invResult.rows[0];

        // Get entity summary
        const entityResult = await query(
          `SELECT type, platform, COUNT(*) as count
           FROM entities
           WHERE investigation_id = $1
           GROUP BY type, platform`,
          [params.investigation_id]
        );

        // Get content timeline
        const contentResult = await query(
          `SELECT DATE_TRUNC('hour', published_at) as hour, 
                  type, 
                  COUNT(*) as count
           FROM content
           WHERE investigation_id = $1 
           AND published_at > $2
           GROUP BY hour, type
           ORDER BY hour`,
          [params.investigation_id, since]
        );

        // Get top content by engagement
        const topContentResult = await query(
          `SELECT id, entity_id, type, text, 
                  (COALESCE(likes, 0) + COALESCE(shares, 0) + COALESCE(comments, 0)) as engagement
           FROM content
           WHERE investigation_id = $1 
           AND published_at > $2
           ORDER BY engagement DESC
           LIMIT 10`,
          [params.investigation_id, since]
        );

        // Build report
        let report = `# Monitoring Report: ${investigation.name}\n\n`;
        report += `**Investigation ID:** ${investigation.id}\n`;
        report += `**Status:** ${investigation.status || "active"}\n`;
        report += `**Time Range:** Last ${params.time_range_hours} hours\n`;
        report += `**Generated:** ${new Date().toISOString()}\n\n`;

        // Executive summary
        if (params.format === "executive" || params.format === "detailed") {
          report += `## Executive Summary\n\n`;
          report += `${investigation.description || "No description available."}\n\n`;
        }

        // Entity breakdown
        report += `## Entity Summary\n\n`;
        for (const row of entityResult.rows) {
          report += `• ${row.platform}/${row.type}: ${row.count}\n`;
        }
        report += `\n`;

        // Content timeline
        report += `## Content Timeline\n\n`;
        report += `Total content items: ${contentResult.rows.reduce((sum, r) => sum + Number(r.count), 0)}\n\n`;

        if (contentResult.rows.length > 0) {
          report += `| Time | Type | Count |\n|------|------|-------|\n`;
          for (const row of contentResult.rows.slice(-20)) {
            report += `| ${row.hour} | ${row.type} | ${row.count} |\n`;
          }
          report += `\n`;
        }

        // Top content
        report += `## Top Content by Engagement\n\n`;
        for (const item of topContentResult.rows) {
          const textPreview = item.text ? item.text.slice(0, 100) + "..." : "[no text]";
          report += `**${item.type}** (${item.engagement} engagements)\n`;
          report += `${textPreview}\n\n`;
        }

        // Network analysis
        if (params.include_network) {
          report += `## Network Analysis\n\n`;
          const networkResult = await query(
            `SELECT source_id, target_id, type, strength
             FROM relationships
             WHERE investigation_id = $1
             ORDER BY strength DESC
             LIMIT 20`,
            [params.investigation_id]
          );

          if (networkResult.rows.length > 0) {
            report += `Identified ${networkResult.rows.length} relationships:\n\n`;
            for (const rel of networkResult.rows) {
              report += `• ${rel.source_id} → ${rel.target_id} (${rel.type}, strength: ${rel.strength})\n`;
            }
          } else {
            report += `No relationships mapped yet.\n`;
          }
          report += `\n`;
        }

        // Recommendations
        if (params.format === "detailed") {
          report += `## Recommendations\n\n`;
          report += `1. Continue monitoring high-engagement content\n`;
          report += `2. Investigate flagged entities for coordination\n`;
          report += `3. Expand data collection to related platforms\n`;
          report += `4. Consider deep analysis of top content items\n`;
        }

        return {
          content: [{ type: "text", text: report }],
          details: {
            investigationId: params.investigation_id,
            timeRangeHours: params.time_range_hours,
            entityCount: entityResult.rows.reduce((sum, r) => sum + Number(r.count), 0),
            contentCount: contentResult.rows.reduce((sum, r) => sum + Number(r.count), 0),
            reportFormat: params.format,
          },
        };
      } catch (error) {
        const message = error instanceof Error ? error.message : "Unknown error";
        return {
          content: [{ type: "text", text: `❌ Report generation failed: ${message}` }],
          details: { error: message },
          isError: true,
        };
      }
    },
  });

  /**
   * Configure monitoring thresholds
   */
  pi.registerTool({
    name: "configure_alerts",
    label: "Configure Alerts",
    description: "Configure alert thresholds and notification preferences for monitoring.",
    parameters: Type.Object({
      post_spike_threshold: Type.Optional(Type.Number({ 
        description: "Alert if more than N posts in monitoring interval",
        minimum: 1,
      })),
      reaction_spike_threshold: Type.Optional(Type.Number({ 
        description: "Alert if total reactions exceed N",
        minimum: 1,
      })),
      suspicious_keywords: Type.Optional(Type.Array(Type.String(), { 
        description: "Keywords to flag in content" 
      })),
    }),
    async execute(toolCallId, params, signal, onUpdate, ctx) {
      // Update thresholds
      if (params.post_spike_threshold !== undefined) {
        monitoringState.alertThresholds.postSpike = params.post_spike_threshold;
      }
      if (params.reaction_spike_threshold !== undefined) {
        monitoringState.alertThresholds.reactionSpike = params.reaction_spike_threshold;
      }
      if (params.suspicious_keywords !== undefined) {
        monitoringState.alertThresholds.suspiciousKeywords = params.suspicious_keywords;
      }

      let responseText = `✅ Alert configuration updated\n\n`;
      responseText += `Current thresholds:\n`;
      responseText += `• Post spike: >${monitoringState.alertThresholds.postSpike} posts\n`;
      responseText += `• Reaction spike: >${monitoringState.alertThresholds.reactionSpike} reactions\n`;
      responseText += `• Suspicious keywords: ${monitoringState.alertThresholds.suspiciousKeywords.join(", ")}\n`;

      return {
        content: [{ type: "text", text: responseText }],
        details: {
          thresholds: monitoringState.alertThresholds,
        },
      };
    },
  });

  // ─── Custom Commands ──────────────────────────────────────────────────────

  pi.registerCommand("monitoring-status", {
    description: "Show current monitoring status and active investigations",
    handler: async (_args, ctx) => {
      let status = `📊 CultGuard Monitoring Status\n\n`;
      status += `Active investigations: ${monitoringState.activeInvestigations.size}\n`;
      
      if (monitoringState.activeInvestigations.size > 0) {
        status += `\n`;
        for (const invId of monitoringState.activeInvestigations) {
          const lastCheck = monitoringState.lastScrapeTime.get(invId);
          const lastCheckStr = lastCheck 
            ? new Date(lastCheck).toLocaleString()
            : "never";
          status += `• ${invId} (last check: ${lastCheckStr})\n`;
        }
      }

      status += `\nAlert thresholds:\n`;
      status += `• Post spike: >${monitoringState.alertThresholds.postSpike}\n`;
      status += `• Reaction spike: >${monitoringState.alertThresholds.reactionSpike}\n`;
      status += `• Keywords: ${monitoringState.alertThresholds.suspiciousKeywords.join(", ")}\n`;

      ctx.ui.notify(status, "info");
    },
  });

  pi.registerCommand("monitoring-reset", {
    description: "Reset monitoring state (clear active investigations)",
    handler: async (_args, ctx) => {
      const confirmed = await ctx.ui.confirm(
        "Reset Monitoring",
        "This will clear all active monitoring sessions. Continue?"
      );

      if (confirmed) {
        monitoringState.activeInvestigations.clear();
        monitoringState.lastScrapeTime.clear();
        ctx.ui.notify("Monitoring state reset", "info");
      } else {
        ctx.ui.notify("Cancelled", "info");
      }
    },
  });

  // ─── Event Hooks ──────────────────────────────────────────────────────────

  // Intercept tool calls for monitoring-related actions
  pi.on("tool_call", async (event, ctx) => {
    // Add monitoring context to fb-scrape tool calls
    if (event.toolName === "bash" && ctx.isIdle()) {
      // Could add custom bash operations for monitoring here
    }
  });

  // Notify on session start
  pi.on("session_start", async (_event, ctx) => {
    const activeCount = monitoringState.activeInvestigations.size;
    if (activeCount > 0) {
      ctx.ui.setStatus("cultguard", `Monitoring ${activeCount} investigations`);
    }
  });
}

// ─── Helper Functions ───────────────────────────────────────────────────────

function extractFacebookPageId(url: string): string {
  // Extract page ID from various Facebook URL formats
  const patterns = [
    /facebook\.com\/(\d+)/,  // Numeric ID
    /facebook\.com\/people\/[^/]+\/(\d+)/,  // People URL
    /facebook\.com\/p\/[^/]+\/(\d+)/,  // Profile URL
  ];

  for (const pattern of patterns) {
    const match = url.match(pattern);
    if (match) {
      return match[1];
    }
  }

  // Fallback: use last path segment
  try {
    const urlObj = new URL(url);
    return urlObj.pathname.split("/").filter(Boolean).pop() || randomUUID();
  } catch {
    return randomUUID();
  }
}
