{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "webhook/lead-capture",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "0871978b-9eb6-460d-825a-18b60062bb59",
      "name": "Lead Capture Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -1008,
        128
      ]
    },
    {
      "parameters": {
        "jsCode": "// Extract and normalize lead data from webhook\nconst webhookData = $input.first().json;\nconsole.log('Raw webhook data:', JSON.stringify(webhookData, null, 2));\n\n// Handle different possible data structures\nlet leadData;\nif (webhookData.body) {\n  // Data is in body property (common with webhooks)\n  leadData = webhookData.body;\n} else if (webhookData.lead_id || webhookData.id) {\n  // Data is directly in the root\n  leadData = webhookData;\n} else {\n  // Fallback - use webhook data as is\n  leadData = webhookData;\n}\n\nconsole.log('Extracted lead data:', JSON.stringify(leadData, null, 2));\n\n// Ensure we have all required fields with fallbacks\nconst normalizedLead = {\n  lead_id: leadData.lead_id || leadData.id || 'unknown-' + Date.now(),\n  name: leadData.name || 'Unknown Lead',\n  email: leadData.email || 'unknown@example.com',\n  company: leadData.company || '',\n  website: leadData.website || '',\n  problem_text: leadData.problem_text || 'No problem description provided'\n};\n\nconsole.log('Normalized lead data:', JSON.stringify(normalizedLead, null, 2));\n\nreturn {\n  json: normalizedLead\n};"
      },
      "id": "f0394eac-37fa-4452-bbfb-3d39aec7bd2d",
      "name": "Extract Lead Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -784,
        128
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT openai_api_key FROM settings ORDER BY created_at DESC LIMIT 1",
        "options": {}
      },
      "id": "fetch-openai-key",
      "name": "Fetch OpenAI Key",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        -784,
        224
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Merge the original lead data with the OpenAI key from database\nconst originalData = $('Extract Lead Data').item.json;\nconst openaiData = $input.first().json;\n\nreturn [{\n  json: {\n    ...originalData,\n    openai_api_key: openaiData.openai_api_key\n  }\n}];"
      },
      "id": "merge-openai-data-lead",
      "name": "Merge Data for OpenAI",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -576,
        224
      ]
    },
    {
      "parameters": {
        "resource": "text",
        "operation": "complete",
        "model": "gpt-3.5-turbo-instruct",
        "prompt": "=Analyze this lead and provide a JSON response with the following structure:\n\nLead Information:\n- Name: {{ $json.name }}\n- Email: {{ $json.email }}\n- Company: {{ $json.company }}\n- Problem: {{ $json.problem_text }}\n\nPlease analyze this lead and return ONLY a JSON object with:\n{\n  \"use_case_label\": \"Marketing Automation\" | \"Sales CRM\" | \"Customer Support\" | \"Analytics\" | \"Other\",\n  \"fit_score\": 85,\n  \"fit_band\": \"High\" | \"Medium\" | \"Low\",\n  \"rationale\": \"Brief explanation of why this score was assigned\"\n}\n\nConsider:\n- How well does their problem match our solutions?\n- Company size and industry relevance\n- Urgency and budget indicators\n- Quality of the inquiry\n\nReturn ONLY the JSON, no other text.",
        "options": {
          "maxTokens": 300,
          "temperature": 0.3
        },
        "requestOptions": {},
        "apiKey": "={{ $json.openai_api_key }}"
      },
      "id": "f33b8706-bbb7-4a42-b4cc-dad86a88d10d",
      "name": "AI Lead Scoring",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1,
      "position": [
        -576,
        128
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Parse AI response and extract JSON\nconst aiInput = $input.first().json;\nconst leadData = $('Extract Lead Data').item.json;\n\nconsole.log('AI Input:', JSON.stringify(aiInput, null, 2));\nconsole.log('Lead Data:', JSON.stringify(leadData, null, 2));\n\n// Get AI response text - handle different response structures\nlet aiResponse;\nif (aiInput.choices && aiInput.choices[0] && aiInput.choices[0].message) {\n  aiResponse = aiInput.choices[0].message.content;\n} else if (aiInput.text) {\n  aiResponse = aiInput.text;\n} else {\n  aiResponse = 'No valid response found';\n}\n\nconsole.log('AI Response:', aiResponse);\n\n// Try to extract JSON from the response\nlet parsedData;\ntry {\n  // Look for JSON in the response\n  const jsonMatch = aiResponse.match(/\\{[\\s\\S]*\\}/);\n  if (jsonMatch) {\n    parsedData = JSON.parse(jsonMatch[0]);\n    console.log('Parsed JSON:', parsedData);\n  } else {\n    // Fallback if no JSON found - use simple analysis\n    parsedData = {\n      use_case_label: 'Other',\n      fit_score: 50,\n      fit_band: 'Medium',\n      rationale: 'AI analysis completed - no JSON found in response'\n    };\n  }\n} catch (error) {\n  console.log('Error parsing JSON:', error);\n  // Fallback on error\n  parsedData = {\n    use_case_label: 'Other',\n    fit_score: 50,\n    fit_band: 'Medium',\n    rationale: 'AI analysis completed - parsing error'\n  };\n}\n\n// Combine lead data with AI analysis\nconst result = {\n  ...leadData,\n  ...parsedData,\n  original_response: aiResponse\n};\n\nconsole.log('Final result:', JSON.stringify(result, null, 2));\n\nreturn {\n  json: result\n};"
      },
      "id": "f3989ef0-63cd-46ac-b88b-967e1e2f7740",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -352,
        128
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO leads (id, name, email, company, website, problem_text, use_case_label, fit_score, fit_band, ai_rationale, status, created_at) VALUES ('{{ $json.lead_id }}', '{{ $json.name }}', '{{ $json.email }}', '{{ $json.company }}', '{{ $json.website }}', '{{ $json.problem_text }}', '{{ $json.use_case_label }}', {{ $json.fit_score }}, '{{ $json.fit_band }}', '{{ $json.rationale.replace(/'/g, \"''\") }}', 'scored', NOW()) ON CONFLICT (id) DO UPDATE SET use_case_label = EXCLUDED.use_case_label, fit_score = EXCLUDED.fit_score, fit_band = EXCLUDED.fit_band, ai_rationale = EXCLUDED.ai_rationale, status = 'scored', updated_at = NOW()",
        "options": {}
      },
      "id": "6e97ed04-a189-492b-bc9e-542195bc364c",
      "name": "Upsert Lead to DB",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        -128,
        128
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO events (lead_id, event_type, event_data, created_at) VALUES ('{{ $json.lead_id }}', 'lead_scored', '{{ JSON.stringify({use_case_label: $json.use_case_label, fit_score: $json.fit_score, fit_band: $json.fit_band, rationale: $json.rationale, timestamp: new Date().toISOString()}).replace(/'/g, \"''\") }}', NOW())",
        "options": {}
      },
      "id": "8cd8a253-302c-4cc3-9099-d10088d50062",
      "name": "Log Lead Scored Event",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        -128,
        224
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT slack_webhook FROM settings ORDER BY created_at DESC LIMIT 1",
        "options": {}
      },
      "id": "fetch-slack-webhook",
      "name": "Fetch Slack Webhook",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        96,
        16
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Merge the original lead data with the Slack webhook from database\nconst originalData = $('Parse AI Response').item.json;\nconst slackData = $input.first().json;\n\nconsole.log('Slack webhook from database:', slackData.slack_webhook);\n\n// Check if Slack webhook exists\nif (!slackData.slack_webhook || slackData.slack_webhook.trim() === '') {\n  console.log('No Slack webhook configured, skipping Slack notification');\n  return [];\n}\n\nreturn [{\n  json: {\n    ...originalData,\n    slack_webhook: slackData.slack_webhook\n  }\n}];"
      },
      "id": "merge-slack-data-lead",
      "name": "Merge Data for Slack",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        192,
        16
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.slack_webhook }}",
        "method": "POST",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"text\": \"\ud83c\udfaf New Lead: {{ $json.name }}\",\n  \"blocks\": [\n    {\n      \"type\": \"header\",\n      \"text\": {\n        \"type\": \"plain_text\",\n        \"text\": \"\ud83c\udfaf New Lead: {{ $json.name }}\"\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"fields\": [\n        {\n          \"type\": \"mrkdwn\",\n          \"text\": \"*Email:* {{ $json.email }}\"\n        },\n        {\n          \"type\": \"mrkdwn\",\n          \"text\": \"*Company:* {{ $json.company || 'Not provided' }}\"\n        },\n        {\n          \"type\": \"mrkdwn\",\n          \"text\": \"*Score:* {{ $json.fit_score }}/100 ({{ $json.fit_band }})\"\n        },\n        {\n          \"type\": \"mrkdwn\",\n          \"text\": \"*Use Case:* {{ $json.use_case_label }}\"\n        }\n      ]\n    },\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*Message:* {{ $json.problem_text.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n') }}\"\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*AI Rationale:* {{ $json.rationale.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n') }}\"\n      }\n    },\n    {\n      \"type\": \"actions\",\n      \"elements\": [\n        {\n          \"type\": \"button\",\n          \"text\": {\n            \"type\": \"plain_text\",\n            \"text\": \"View in Dashboard\"\n          },\n          \"url\": \"{{ $env.FRONTEND_URL || 'http://localhost:5173' }}/dashboard\",\n          \"style\": \"primary\"\n        }\n      ]\n    }\n  ]\n}",
        "options": {}
      },
      "id": "d0cc030f-c187-4e0f-9398-a2ebe525ba0a",
      "name": "Send Slack Notification",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        320,
        16
      ]
    },
    {
      "parameters": {
        "fromEmail": "={{ $env.SMTP_FROM || 'noreply@pulsecapture.com' }}",
        "toEmail": "admin@leadcapture.com",
        "subject": "New Lead: {{ $json.name }} ({{ $json.fit_band }} Priority)",
        "options": {}
      },
      "id": "a26b5ed6-64c6-4e9d-9b34-3031fa005294",
      "name": "Send Email Notification",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2,
      "position": [
        544,
        224
      ],
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\n  \"success\": true,\n  \"message\": \"Lead processed successfully\",\n  \"lead_id\": \"{{ $json.lead_id }}\",\n  \"fit_score\": {{ $json.fit_score || 50 }},\n  \"fit_band\": \"{{ $json.fit_band || 'Medium' }}\"\n}",
        "options": {}
      },
      "id": "ec068781-9b6a-4451-8df0-cc7c410c935d",
      "name": "Webhook Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        752,
        128
      ]
    }
  ],
  "connections": {
    "Lead Capture Webhook": {
      "main": [
        [
          {
            "node": "Extract Lead Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Lead Data": {
      "main": [
        [
          {
            "node": "Fetch OpenAI Key",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch OpenAI Key": {
      "main": [
        [
          {
            "node": "Merge Data for OpenAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Data for OpenAI": {
      "main": [
        [
          {
            "node": "AI Lead Scoring",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Lead Scoring": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Upsert Lead to DB",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert Lead to DB": {
      "main": [
        [
          {
            "node": "Log Lead Scored Event",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Slack Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Slack Webhook": {
      "main": [
        [
          {
            "node": "Merge Data for Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Data for Slack": {
      "main": [
        [
          {
            "node": "Send Slack Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Slack Notification": {
      "main": [
        [
          {
            "node": "Send Email Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Notification": {
      "main": [
        [
          {
            "node": "Webhook Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}