import { createAnthropic } from "@ai-sdk/anthropic";
import { streamText, tool } from "ai";
import { z } from "zod";
import { getChannel } from "@/lib/channels";
import { existsSync } from "fs";
import { join } from "path";
import {
  readLeads,
  readDailyStats,
  getSavedSearches,
  startScrapeJob,
  getJob,
  exportLeadsAsCsv,
  exportLeadsAsJson,
} from "@/lib/reonomy-service";

const anthropic = createAnthropic({
  apiKey: process.env.LB_ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY || "",
});

// Map channel MCP app IDs to actual app file names
const APP_NAME_MAP: Record<string, string> = {
  // n8n apps
  "n8n-workflow-builder": "workflow-builder",
  "n8n-workflow-dashboard": "workflow-dashboard",
  "n8n-execution-monitor": "execution-dashboard",
  "n8n-node-config": "node-explorer",
  "n8n-node-explorer": "node-explorer",
  "n8n-template-gallery": "template-gallery",
  "n8n-health-monitor": "health-monitor",
  "n8n-credential-manager": "workflow-dashboard",
  "n8n-webhook-tester": "workflow-tester",
  "n8n-expression-editor": "workflow-detail",
  "n8n-workflow-templates": "template-gallery",
  "n8n-error-analyzer": "health-monitor",
  // competitor research apps
  "competitor-intake-form": "intake-form",
  "competitor-dashboard": "dashboard",
  // GHL apps — all 65
  "ghl-affiliate-dashboard": "affiliate-dashboard",
  "ghl-agent-stats": "agent-stats",
  "ghl-appointment-booker": "appointment-booker",
  "ghl-appointment-detail": "appointment-detail",
  "ghl-blog-manager": "blog-manager",
  "ghl-calendar-resources": "calendar-resources",
  "ghl-calendar-view": "calendar-view",
  "ghl-call-detail": "call-detail",
  "ghl-call-log": "call-log",
  "ghl-campaign-stats": "campaign-stats",
  "ghl-company-detail": "company-detail",
  "ghl-company-list": "company-list",
  "ghl-contact-card": "contact-card",
  "ghl-contact-creator": "contact-creator",
  "ghl-contact-grid": "contact-grid",
  "ghl-contact-timeline": "contact-timeline",
  "ghl-conversation-list": "conversation-list",
  "ghl-conversation-thread": "conversation-thread",
  "ghl-coupon-manager": "coupon-manager",
  "ghl-course-catalog": "course-catalog",
  "ghl-course-detail": "course-detail",
  "ghl-custom-fields-manager": "custom-fields-manager",
  "ghl-duplicate-checker": "duplicate-checker",
  "ghl-email-template-preview": "email-template-preview",
  "ghl-estimate-builder": "estimate-builder",
  "ghl-estimate-preview": "estimate-preview",
  "ghl-form-list": "form-list",
  "ghl-form-submissions": "form-submissions",
  "ghl-free-slots-finder": "free-slots-finder",
  "ghl-funnel-detail": "funnel-detail",
  "ghl-funnel-list": "funnel-list",
  "ghl-inventory-dashboard": "inventory-dashboard",
  "ghl-invoice-builder": "invoice-builder",
  "ghl-invoice-list": "invoice-list",
  "ghl-invoice-preview": "invoice-preview",
  "ghl-location-dashboard": "location-dashboard",
  "ghl-media-library": "media-library",
  "ghl-message-composer": "message-composer",
  "ghl-message-detail": "message-detail",
  "ghl-opportunity-card": "opportunity-card",
  "ghl-opportunity-editor": "opportunity-editor",
  "ghl-order-detail": "order-detail",
  "ghl-order-list": "order-list",
  "ghl-pipeline-analytics": "pipeline-analytics",
  "ghl-pipeline-funnel": "pipeline-funnel",
  "ghl-pipeline-kanban": "pipeline-kanban",
  "ghl-product-catalog": "product-catalog",
  "ghl-product-detail": "product-detail",
  "ghl-revenue-dashboard": "revenue-dashboard",
  "ghl-reviews-dashboard": "reviews-dashboard",
  "ghl-smartlist-viewer": "smartlist-viewer",
  "ghl-social-accounts": "social-accounts",
  "ghl-social-calendar": "social-calendar",
  "ghl-social-post-composer": "social-post-composer",
  "ghl-subscription-manager": "subscription-manager",
  "ghl-survey-list": "survey-list",
  "ghl-survey-submissions": "survey-submissions",
  "ghl-tags-manager": "tags-manager",
  "ghl-task-board": "task-board",
  "ghl-team-management": "team-management",
  "ghl-template-library": "template-library",
  "ghl-transaction-list": "transaction-list",
  "ghl-user-detail": "user-detail",
  "ghl-workflow-detail": "workflow-detail",
  "ghl-workflow-status": "workflow-status",
  // Legacy GHL aliases
  "ghl-pipeline-board": "pipeline-board",
  "ghl-quick-book": "quick-book",
  // Google Ads apps
  "google-ads-campaign-dashboard": "campaign-dashboard",
  "google-ads-performance-overview": "performance-overview",
  "google-ads-keyword-analyzer": "keyword-analyzer",
  "google-ads-budget-optimizer": "budget-optimizer",
  "google-ads-search-terms": "search-terms",
  "google-ads-campaign-detail": "campaign-detail",
  "google-ads-recommendations": "recommendations",
  // Meta Ads apps
  "meta-ads-campaign-dashboard": "campaign-dashboard",
  "meta-ads-performance-heatmap": "performance-heatmap",
  "meta-ads-audience-builder": "audience-builder",
  "meta-ads-creative-preview": "creative-preview",
  "meta-ads-funnel-analyzer": "funnel-analyzer",
  "meta-ads-spend-tracker": "spend-tracker",
  "meta-ads-ad-performance-grid": "ad-performance-grid",
  "meta-ads-ab-test-results": "ab-test-results",
  "meta-ads-account-health": "account-health",
  "meta-ads-campaign-builder": "campaign-builder",
  "meta-ads-ad-library-browser": "ad-library-browser",
  // Google Console apps
  "gsc-performance-dashboard": "dashboard",
  "gsc-quick-wins-board": "quick-wins",
  "gsc-url-health-inspector": "url-health",
  "gsc-cannibalization-map": "cannibalization",
  "gsc-content-decay-tracker": "content-decay",
  // Reonomy apps
  "reonomy-search-builder": "reonomy-search-builder",
  "reonomy-results-viewer": "reonomy-results-viewer",
  "reonomy-dashboard": "reonomy-dashboard",
  // Twilio apps
  "twilio-dashboard": "dashboard",
  "twilio-campaign-live": "campaign-live",
  "twilio-conversation-thread": "conversation-thread",
  "twilio-message-log": "message-log",
  "twilio-call-analytics": "call-analytics",
  "twilio-deep-scan-report": "deep-scan-report",
  "twilio-batch-validate": "batch-validate",
  "twilio-number-hunt": "number-hunt",
  "twilio-number-inventory": "number-inventory",
  "twilio-flow-diagram": "flow-diagram",
  "twilio-flow-list": "flow-list",
  "twilio-agent-status": "agent-status",
  "twilio-queue-manager": "queue-manager",
  "twilio-inbox": "inbox",
  "twilio-cost-report": "cost-report",
  "twilio-health-check": "health-check",
  "twilio-error-log": "error-log",
  "twilio-deploy-status": "deploy-status",
  "twilio-compliance-check": "compliance-check",
};

// Intent-to-app mapping: keywords in user message → which apps are relevant
const APP_INTENT_MAP: Record<string, string[]> = {
  // GHL intents
  pipeline: ["ghl-pipeline-kanban", "ghl-pipeline-analytics", "ghl-opportunity-card"],
  deal: ["ghl-pipeline-kanban", "ghl-opportunity-card", "ghl-opportunity-editor"],
  opportunity: ["ghl-pipeline-kanban", "ghl-opportunity-card", "ghl-opportunity-editor"],
  contact: ["ghl-contact-grid", "ghl-contact-timeline", "ghl-contact-card"],
  lead: ["ghl-contact-grid", "ghl-contact-creator", "ghl-smartlist-viewer"],
  calendar: ["ghl-calendar-view", "ghl-calendar-resources"],
  appointment: ["ghl-calendar-view", "ghl-appointment-booker", "ghl-free-slots-finder"],
  schedule: ["ghl-calendar-view", "ghl-appointment-booker", "ghl-free-slots-finder"],
  campaign: ["ghl-campaign-stats"],
  invoice: ["ghl-invoice-list", "ghl-invoice-builder", "ghl-invoice-preview"],
  billing: ["ghl-invoice-list", "ghl-transaction-list", "ghl-revenue-dashboard"],
  estimate: ["ghl-estimate-builder", "ghl-estimate-preview"],
  book: ["ghl-appointment-booker"],
  booking: ["ghl-appointment-booker", "ghl-free-slots-finder"],
  workflow: ["ghl-workflow-status", "ghl-workflow-detail"],
  automation: ["ghl-workflow-status", "ghl-workflow-detail"],
  agent: ["ghl-agent-stats"],
  team: ["ghl-team-management", "ghl-agent-stats"],
  company: ["ghl-company-list", "ghl-company-detail"],
  conversation: ["ghl-conversation-list", "ghl-conversation-thread"],
  chat: ["ghl-conversation-list", "ghl-message-composer"],
  email: ["ghl-email-template-preview", "ghl-message-composer"],
  call: ["ghl-call-log", "ghl-call-detail"],
  phone: ["ghl-call-log"],
  order: ["ghl-order-list", "ghl-order-detail"],
  product: ["ghl-product-catalog", "ghl-product-detail"],
  inventory: ["ghl-inventory-dashboard"],
  revenue: ["ghl-revenue-dashboard", "ghl-transaction-list"],
  payment: ["ghl-transaction-list", "ghl-revenue-dashboard"],
  subscription: ["ghl-subscription-manager"],
  coupon: ["ghl-coupon-manager"],
  funnel: ["ghl-funnel-list", "ghl-funnel-detail", "ghl-pipeline-funnel"],
  form: ["ghl-form-list", "ghl-form-submissions"],
  survey: ["ghl-survey-list", "ghl-survey-submissions"],
  social: ["ghl-social-accounts", "ghl-social-calendar", "ghl-social-post-composer"],
  course: ["ghl-course-catalog", "ghl-course-detail"],
  membership: ["ghl-course-catalog"],
  blog: ["ghl-blog-manager"],
  media: ["ghl-media-library"],
  task: ["ghl-task-board"],
  review: ["ghl-reviews-dashboard"],
  reputation: ["ghl-reviews-dashboard"],
  affiliate: ["ghl-affiliate-dashboard"],
  duplicate: ["ghl-duplicate-checker"],
  tag: ["ghl-tags-manager"],
  "custom field": ["ghl-custom-fields-manager"],
  "smart list": ["ghl-smartlist-viewer"],
  template: ["ghl-template-library", "ghl-email-template-preview", "n8n-template-gallery"],
  location: ["ghl-location-dashboard"],
  // n8n intents
  "build workflow": ["n8n-workflow-builder"],
  "create workflow": ["n8n-workflow-builder"],
  "new workflow": ["n8n-workflow-builder"],
  execution: ["n8n-execution-monitor"],
  "workflow status": ["n8n-workflow-dashboard"],
  "my workflows": ["n8n-workflow-dashboard"],
  node: ["n8n-node-config"],
  // Google Ads intents
  "campaign performance": ["google-ads-campaign-dashboard"],
  "ad performance": ["google-ads-performance-overview"],
  keyword: ["google-ads-keyword-analyzer"],
  budget: ["google-ads-budget-optimizer"],
  "search term": ["google-ads-search-terms"],
  recommendation: ["google-ads-recommendations"],
  // Meta Ads intents
  "ad creative": ["meta-ads-creative-preview"],
  audience: ["meta-ads-audience-builder"],
  heatmap: ["meta-ads-performance-heatmap"],
  "ad funnel": ["meta-ads-funnel-analyzer"],
  spend: ["meta-ads-spend-tracker"],
  "a/b test": ["meta-ads-ab-test-results"],
  "split test": ["meta-ads-ab-test-results"],
  "ad library": ["meta-ads-ad-library-browser"],
  // Google Console intents
  seo: ["gsc-performance-dashboard", "gsc-quick-wins-board"],
  "search console": ["gsc-performance-dashboard"],
  "quick win": ["gsc-quick-wins-board"],
  indexing: ["gsc-url-health-inspector"],
  "url health": ["gsc-url-health-inspector"],
  cannibalization: ["gsc-cannibalization-map"],
  "content decay": ["gsc-content-decay-tracker"],
  // Twilio intents
  sms: ["twilio-dashboard", "twilio-message-log"],
  message: ["twilio-message-log"],
  "twilio call": ["twilio-call-analytics"],
  "phone number": ["twilio-number-inventory", "twilio-number-hunt"],
  "buy number": ["twilio-number-hunt"],
  verify: ["twilio-dashboard"],
  "studio flow": ["twilio-flow-diagram", "twilio-flow-list"],
  queue: ["twilio-queue-manager"],
  cost: ["twilio-cost-report"],
  // Reonomy intents
  property: ["reonomy-search-builder", "reonomy-results-viewer"],
  "property search": ["reonomy-search-builder"],
  "owner contact": ["reonomy-results-viewer"],
  "real estate": ["reonomy-search-builder", "reonomy-dashboard"],
  commercial: ["reonomy-search-builder", "reonomy-dashboard"],
  "lead extraction": ["reonomy-results-viewer"],
  scrape: ["reonomy-results-viewer", "reonomy-dashboard"],
  reonomy: ["reonomy-dashboard", "reonomy-search-builder", "reonomy-results-viewer"],
  multifamily: ["reonomy-search-builder", "reonomy-results-viewer"],
  office: ["reonomy-search-builder", "reonomy-results-viewer"],
  industrial: ["reonomy-search-builder"],
  "pre-foreclosure": ["reonomy-search-builder"],
  distressed: ["reonomy-search-builder"],
  // Competitor Research intents
  competitor: ["competitor-intake-form", "competitor-dashboard"],
  research: ["competitor-intake-form", "competitor-dashboard"],
};

// Directories to search for MCP app HTML files (per MCP server)
const APP_DIRS = [
  join(process.cwd(), "../n8n-mcp-apps/dist/app-ui"),
  join(process.cwd(), "../competitor-research-mcp/dist/app-ui"),
  join(process.cwd(), "../mcp-diagrams/GoHighLevel-MCP/dist/app-ui"),
  join(process.cwd(), "../mcp-diagrams/ghl-mcp-apps-only/dist/app-ui"),
  join(process.cwd(), "../mcp-diagrams/google-ads-mcp/dist/app-ui"),
  join(process.cwd(), "../meta-ads-mcp/dist/app-ui"),
  join(process.cwd(), "../google-console-mcp/dist/app-ui"),
  join(process.cwd(), "../twilio-mcp/dist/app-ui"),
  // Reonomy apps (CRE data)
  join(process.cwd(), "../reonomy-mcp/dist/app-ui"),
  // GHL apps built as subdirectories (dist/apps/{name}/index.html)
  join(process.cwd(), "../mcp-diagrams/GoHighLevel-MCP/src/ui/dist/apps"),
];

// Check if an app file exists in any known MCP app directory
function appExists(appId: string): boolean {
  const appFileName = APP_NAME_MAP[appId] || appId;
  return APP_DIRS.some((dir) =>
    existsSync(join(dir, `${appFileName}.html`)) ||
    existsSync(join(dir, appFileName, "index.html"))
  );
}

// Determine which apps are relevant based on user message
function getRelevantApps(
  userMessage: string,
  channelApps: string[]
): string[] {
  const lower = userMessage.toLowerCase();
  const matched = new Set<string>();

  // Check intent keywords against the user's message
  for (const [keyword, appIds] of Object.entries(APP_INTENT_MAP)) {
    if (lower.includes(keyword)) {
      for (const appId of appIds) {
        // Only include if it's one of the channel's apps
        if (channelApps.includes(appId)) {
          matched.add(appId);
        }
      }
    }
  }

  // If no specific intent matched, don't show any apps
  // (let the AI response handle it naturally)
  return Array.from(matched);
}

// Thread-specific system prompt for app data generation
const THREAD_SYSTEM_PROMPT = `

## MANDATORY: APP_DATA BLOCK (DO NOT SKIP)

You are in an APP THREAD. Every response you give MUST include a hidden APP_DATA block that updates the visual app above the conversation. This is NOT optional.

FORMAT (place at the VERY END of your response):
<!--APP_DATA:{"key":"value"}:END_APP_DATA-->

RULES:
1. EVERY response MUST have exactly one APP_DATA block — no exceptions
2. The JSON must be valid and on a SINGLE LINE (no line breaks inside)
3. Place it AFTER your text explanation
4. Generate REALISTIC data matching what the user requested
5. Include 5-10 records for lists, complete details for single items
6. The block is automatically parsed and hidden from the user
7. Also write a brief natural language explanation before the block
8. When the user refines, generate completely NEW APP_DATA (replace, don't append)

If you forget the APP_DATA block, the visual app won't update and the user will see stale data. ALWAYS include it.`;

// Enhanced system prompt addition for the automations channel
// Instructs the AI to include workflow JSON blocks in responses
const WORKFLOW_JSON_PROMPT = `

WORKFLOW BUILDER INTEGRATION:
When the user asks you to build, create, set up, or modify a workflow or automation, you MUST include a hidden workflow specification block in your response using this exact format:

<!--WORKFLOW_JSON:{"name":"Workflow Name","nodes":[{"name":"Node Name","type":"n8n-nodes-base.nodeType","icon":"emoji","category":"Category","parameters":{"key":"value"}}],"requiredCredentials":[{"service":"ServiceName","icon":"emoji","type":"credential-type","description":"What this credential does"}]}:END_WORKFLOW-->

Rules:
- ALWAYS include this block when the user describes a workflow they want built
- Place it at the END of your response, after your natural language explanation
- Use real n8n node types from this list:
  Triggers: n8n-nodes-base.webhook (🌐), n8n-nodes-base.scheduleTrigger (⏰), n8n-nodes-base.formTrigger (📝), n8n-nodes-base.manualTrigger (👆), @n8n/n8n-nodes-langchain.chatTrigger (💬)
  Actions: n8n-nodes-base.httpRequest (🌍), n8n-nodes-base.slack (💬), n8n-nodes-base.gmail (📧), n8n-nodes-base.discord (🎮), n8n-nodes-base.telegram (✈️)
  Transform: n8n-nodes-base.code (💻), n8n-nodes-base.set (✏️), n8n-nodes-base.if (🔀), n8n-nodes-base.switch (🔃), n8n-nodes-base.merge (🔗)
  Flow: n8n-nodes-base.wait (⏳), n8n-nodes-base.splitInBatches (🔁), n8n-nodes-base.errorTrigger (🚨)
  AI: @n8n/n8n-nodes-langchain.openAi (🧠), @n8n/n8n-nodes-langchain.agent (🤖), @n8n/n8n-nodes-langchain.vectorStore (📊), @n8n/n8n-nodes-langchain.textClassifier (🏷️)
- Categories must be one of: "Triggers", "Actions", "Transform", "Flow", "AI"
- Include sensible default parameters for each node
- The JSON block will be automatically parsed and NOT shown to the user, so also write a clear natural language explanation of the workflow
- Keep the JSON on a SINGLE LINE (no line breaks inside the JSON object)
- Start every workflow with an appropriate trigger node
- Name the workflow descriptively based on what the user asked for

REQUIRED CREDENTIALS:
You MUST include a "requiredCredentials" array in the workflow JSON. Determine which credentials are needed based on the nodes you generate. Use these mappings:
- Gmail node → { "service": "Gmail", "icon": "📧", "type": "google-oauth2", "description": "Read and send emails" }
- Slack node → { "service": "Slack", "icon": "💬", "type": "slack-oauth2", "description": "Send messages to channels" }
- Google Drive node → { "service": "Google Drive", "icon": "📁", "type": "google-oauth2", "description": "Access files and folders" }
- Google Sheets node → { "service": "Google Sheets", "icon": "📊", "type": "google-oauth2", "description": "Read and write spreadsheet data" }
- Telegram node → { "service": "Telegram", "icon": "✈️", "type": "telegram-api", "description": "Send and receive Telegram messages" }
- Discord node → { "service": "Discord", "icon": "🎮", "type": "discord-webhook", "description": "Send messages via webhook" }
- OpenAI/AI nodes → { "service": "OpenAI", "icon": "🧠", "type": "openai-api", "description": "AI text generation and analysis" }
- HTTP Request → no credential needed (manual config)
- Code/IF/Switch/Set/Merge/Wait/Loop/SplitInBatches → no credential needed
- Schedule/Manual/Form/Webhook/Chat triggers → no credential needed
- Deduplicate: if multiple nodes use the same credential type (e.g., Gmail + Google Sheets both use google-oauth2), include it only ONCE
- If NO credentials are needed, use an empty array: "requiredCredentials":[]`;

export async function POST(request: Request) {
  try {
    const body = await request.json();
    const { messages, channelId, threadContext } = body as {
      messages: { role: "user" | "assistant"; content: string }[];
      channelId: string;
      threadContext?: {
        appId: string;
        category: string;
        previousAppData: Record<string, unknown> | null;
      };
    };

    if (!messages || !Array.isArray(messages)) {
      return new Response("Missing messages", { status: 400 });
    }

    const channel = getChannel(channelId || "general");
    const baseSystemPrompt =
      channel?.systemPrompt || "You are a helpful assistant.";

    // Build the system prompt based on context
    let systemPrompt = baseSystemPrompt;

    if (threadContext) {
      const { getAppIntake } = await import("@/lib/app-intakes");
      const intake = getAppIntake(threadContext.appId);
      const addonPrompt = intake?.systemPromptAddon || "";

      // For workflow builder: use the proven WORKFLOW_JSON format (same as main chat)
      if (threadContext.appId === "n8n-workflow-builder") {
        systemPrompt += WORKFLOW_JSON_PROMPT;
      } else {
        // Other apps: use APP_DATA thread format
        systemPrompt += THREAD_SYSTEM_PROMPT;
        systemPrompt += `\n\nAPP CONTEXT:\n- App ID: ${threadContext.appId}\n- Category: ${threadContext.category}\n- ${addonPrompt}`;
      }

      if (threadContext.previousAppData) {
        systemPrompt += `\n\nPREVIOUS APP DATA (the user may want to refine this):\n${JSON.stringify(threadContext.previousAppData).substring(0, 2000)}`;
      }
    } else if (channelId === "reonomy") {
      // Reonomy channel: inject REAL scraped data + give the AI real tools
      const realLeads = readLeads();
      const dailyStats = readDailyStats();
      const savedSearches = getSavedSearches();

      systemPrompt += `\n\n## CRITICAL: USE ONLY REAL DATA — NEVER MAKE UP LEADS

You have REAL tools to search, scrape, and export property data. Use them!

When users ask for leads:
1. ONLY present leads from your tools — NEVER invent addresses, owners, or phone numbers
2. Use the reonomy_scrape tool when users want NEW leads from a specific area
3. Use reonomy_get_leads to view what's already been scraped
4. After getting real results, present them formatted nicely
5. When presenting results, include an APP_DATA block at the end:
   <!--APP_DATA:{"properties":[...the real lead objects...]}:END_APP_DATA-->

## CURRENT DATABASE
- Total leads: ${realLeads?.totalLeads || 0}
- Last updated: ${realLeads?.lastUpdated || "never"}
- Daily usage: ${dailyStats.propertiesScraped}/50 today (${50 - dailyStats.propertiesScraped} remaining)

## SAVED SEARCHES (use these search IDs for scraping)
${savedSearches.map(s => `- "${s.name}" (ID: ${s.searchId}) — ${s.description || ""}`).join("\n")}

## HOW SCRAPING WORKS
- Each scrape spawns a real browser that logs into Reonomy and extracts data
- It takes ~30-60 seconds per property (anti-detection delays)
- After starting a scrape, tell the user it's running and check status with reonomy_scrape_status
- Max 50 properties per day
- The scraper extracts: property address, type, size, owner names, phone numbers, emails
`;
    } else if (channelId === "automations") {
      // Automations channel: add workflow JSON instructions
      systemPrompt += WORKFLOW_JSON_PROMPT;
    }

    // Build tools for Reonomy channel (real scraper integration)
    const reonomyTools = channelId === "reonomy" ? {
      reonomy_scrape: tool({
        description: "Start a real scrape of properties from Reonomy. Launches a browser that logs in and extracts owner contact info. Takes 30-60 seconds per property.",
        parameters: z.object({
          searchId: z.string().optional().describe("Reonomy search ID to use. Defaults to the FL Multifamily search."),
          maxProperties: z.number().optional().describe("Max properties to scrape (1-20). Default 5."),
        }),
        execute: async ({ searchId, maxProperties }) => {
          const job = startScrapeJob({
            searchId: searchId || undefined,
            maxProperties: maxProperties || 5,
          });
          return job.status === "running"
            ? { success: true, jobId: job.id, message: `Scrape started! Extracting up to ${maxProperties || 5} properties. This takes ~30-60 seconds per property. The scraper is running in the background.` }
            : { success: false, error: job.error };
        },
      }),
      reonomy_scrape_status: tool({
        description: "Check the status of a running scrape job",
        parameters: z.object({
          jobId: z.string().describe("The job ID returned from reonomy_scrape"),
        }),
        execute: async ({ jobId }) => {
          const job = getJob(jobId);
          if (!job) return { error: "Job not found" };
          return job;
        },
      }),
      reonomy_get_leads: tool({
        description: "Get all currently scraped leads from the database. Returns real property data with owner contacts.",
        parameters: z.object({
          state: z.string().optional().describe("Filter by state (e.g. 'NJ', 'FL')"),
          propertyType: z.string().optional().describe("Filter by property type (e.g. 'Retail', 'Office')"),
        }),
        execute: async ({ state, propertyType }) => {
          const data = readLeads();
          if (!data || data.leads.length === 0) {
            return { totalLeads: 0, leads: [], message: "No leads in database. Run a scrape first." };
          }
          let filtered = data.leads;
          if (state) filtered = filtered.filter(l => l.state?.toLowerCase() === state.toLowerCase());
          if (propertyType) filtered = filtered.filter(l => l.propertyType?.toLowerCase().includes(propertyType.toLowerCase()));
          return { totalLeads: filtered.length, lastUpdated: data.lastUpdated, leads: filtered };
        },
      }),
      reonomy_export: tool({
        description: "Export scraped leads as CSV or JSON",
        parameters: z.object({
          format: z.enum(["csv", "json"]).optional().describe("Export format. Default csv."),
        }),
        execute: async ({ format }) => {
          const data = readLeads();
          if (!data || data.leads.length === 0) return { error: "No leads to export." };
          const fmt = format || "csv";
          const exported = fmt === "json" ? exportLeadsAsJson(data.leads) : exportLeadsAsCsv(data.leads);
          return { format: fmt, recordCount: data.leads.length, data: exported };
        },
      }),
      reonomy_stats: tool({
        description: "Get scraping stats — daily usage, total leads, limits",
        parameters: z.object({}),
        execute: async () => {
          const data = readLeads();
          const stats = readDailyStats();
          return {
            totalLeads: data?.totalLeads || 0,
            lastUpdated: data?.lastUpdated || null,
            dailyScraped: stats.propertiesScraped,
            dailyLimit: 50,
            remaining: 50 - stats.propertiesScraped,
          };
        },
      }),
    } : {};

    const result = streamText({
      model: anthropic("claude-sonnet-4-20250514"),
      system: systemPrompt,
      messages: messages.map((m) => ({
        role: m.role as "user" | "assistant",
        content: m.content,
      })),
      tools: reonomyTools,
      maxSteps: 5,
      temperature: 0.7,
    });

    // If this is a thread request, skip MCP app filtering — threads manage their own apps
    if (threadContext) {
      return result.toTextStreamResponse();
    }

    // Smart app filtering: only show apps relevant to the user's message
    const lastUserMessage =
      messages.filter((m) => m.role === "user").pop()?.content || "";

    if (channel?.mcpApps && channel.mcpApps.length > 0) {
      // Filter to only relevant apps based on user intent
      const relevantAppIds = getRelevantApps(
        lastUserMessage,
        channel.mcpApps
      );

      // Only include apps that exist AND are relevant
      const mcpAppData = relevantAppIds
        .map((appId) => {
          if (!appExists(appId)) return null;
          return {
            id: appId,
            title: appId
              .replace(/^(ghl|n8n|google-ads|meta-ads|gsc|twilio)-/, "")
              .split("-")
              .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
              .join(" "),
            url: `/api/mcp-apps?app=${encodeURIComponent(appId)}`,
            height: 500,
          };
        })
        .filter(Boolean);

      // Only add the mcp_apps chunk if we have relevant apps to show
      if (mcpAppData.length > 0) {
        const encoder = new TextEncoder();
        const stream = new ReadableStream({
          async start(controller) {
            // Send MCP app metadata as first chunk
            controller.enqueue(
              encoder.encode(
                JSON.stringify({ type: "mcp_apps", data: mcpAppData }) + "\n"
              )
            );

            // Stream the text response
            const textResponse = result.toTextStreamResponse();
            if (textResponse.body) {
              const reader = textResponse.body.getReader();
              while (true) {
                const { done, value } = await reader.read();
                if (done) break;
                controller.enqueue(value);
              }
            }
            controller.close();
          },
        });

        return new Response(stream, {
          headers: {
            "Content-Type": "text/plain; charset=utf-8",
            "Cache-Control": "no-cache",
            Connection: "keep-alive",
          },
        });
      }
    }

    // No relevant apps or no channel apps — just stream text
    return result.toTextStreamResponse();
  } catch (error) {
    console.error("[Chat API Error]", error);
    const message =
      error instanceof Error ? error.message : "Internal server error";
    return new Response(JSON.stringify({ error: message }), {
      status: 500,
      headers: { "Content-Type": "application/json" },
    });
  }
}
