{
  "name": "Brokeria-v20",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "waha",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -656,
        -96
      ],
      "id": "dd67499f-0c0b-4690-a5fb-a4a0ffa5fc19",
      "name": "Webhook"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "78415b90-064b-46f3-8a36-8489bd14f43a",
              "name": "event",
              "value": "={{ $json.body.event || $json.body.action }}",
              "type": "string"
            },
            {
              "id": "6d70d6a1-58d7-416a-a388-7b2aeabd4b85",
              "name": "session",
              "value": "={{ ($json.body.session || $json.body.session_id || 'default').trim() }}",
              "type": "string"
            },
            {
              "id": "ff0bd58d-efa1-4e49-9c9c-602aed25a290",
              "name": "payload_id",
              "value": "={{ $json.body.payload.id || $json.body.id || 'web_' + $now }}",
              "type": "string"
            },
            {
              "id": "0c990094-4206-417a-be86-008c8156acf8",
              "name": "from",
              "value": "={{ $json.body.payload.from || $json.body.telefone || $json.body.target }}",
              "type": "string"
            },
            {
              "id": "d33eb4cc-078e-40b7-9c9c-8fbba1e2aa76",
              "name": "to",
              "value": "={{ $json.body.payload.to || $json.body.target }}",
              "type": "string"
            },
            {
              "id": "457f7c13-bf6f-4171-80bc-75620cfda604",
              "name": "source",
              "value": "={{ $json.body.payload.source || $json.body.origem }}",
              "type": "string"
            },
            {
              "id": "8ce79aa1-5408-48c9-8226-9ac6f875df12",
              "name": "body",
              "value": "={{ $json.body.payload?.body || $json.body.message || $json.body.pergunta_cliente }}",
              "type": "string"
            },
            {
              "id": "3fc1bd24-4960-40a3-9a52-5e1fa4365813",
              "name": "hasMedia",
              "value": "={{ $json.body.payload.hasMedia }}",
              "type": "boolean"
            },
            {
              "id": "7437da46-cfce-4e5b-909a-5daf06dfd2ad",
              "name": "type",
              "value": "={{ $json.body.payload._data.type }}",
              "type": "string"
            },
            {
              "id": "f8f215f3-ba00-485e-be98-354baa181f28",
              "name": "name",
              "value": "={{ $json.body.payload?._data?.notifyName || $json.body.client_name || $json.body.nome }}",
              "type": "string"
            },
            {
              "id": "6508b08d-4b94-4352-8a94-c55ffd11cc91",
              "name": "fromMe",
              "value": "={{ $json.body.payload.fromMe || false }}",
              "type": "boolean"
            },
            {
              "id": "3ada40ac-45a0-440a-9e4b-44417caadf9c",
              "name": "to",
              "value": "={{ $json.body.payload.to || $json.body.target }}",
              "type": "string"
            },
            {
              "id": "0096fa37-d92b-43ca-8c98-269cc5e1899f",
              "name": "id",
              "value": "={{ $json.body.payload?.id || $json.body.id || 'web_' + $now }}",
              "type": "string"
            },
            {
              "id": "30a509ba-e3aa-4e6a-b3ce-4f7d1fcbf46f",
              "name": "session_id",
              "value": "={{ ($json.body.session || 'portal') + ' ' + ($json.body.payload.from || $json.body.telefone || $json.body.identifier) + ' chats' }}",
              "type": "string"
            },
            {
              "id": "72d18f99-83a5-4bfb-8621-6af03d231409",
              "name": "from",
              "value": "={{ $json.body.payload.from || $json.body.telefone || $json.body.target }}",
              "type": "string"
            },
            {
              "id": "72d18f99-83a5-4bfb-8621-6af03d231410",
              "name": "pn",
              "value": "={{ $json.body.payload.from || $json.body.telefone }}",
              "type": "string"
            },
            {
              "id": "72d18f99-83a5-4bfb-8621-6af03d231409",
              "name": "user_text",
              "value": "={{ $json.body.payload.body || $json.body.message || $json.body.pergunta_cliente }}",
              "type": "string"
            },
            {
              "id": "d1a86623-555b-4571-b71d-b7dc69e0b763",
              "name": "media_url",
              "value": "={{ $json.body.payload.media.url || $json.body.payload.url || \"\" }}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -464,
        -96
      ],
      "id": "858a403f-0b79-471d-9c93-066b6bf306eb",
      "name": "Dados"
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Send Seen",
        "session": "={{ $('Padronizar Output').first().json.target_session || 'default' }}",
        "chatId": "={{ $('Padronizar Output').first().json.target_chat_id }}",
        "messageId": "",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        2800,
        896
      ],
      "id": "575c26cf-b26a-4cd1-ba01-405dd1e499e3",
      "name": "Send Seen",
      "alwaysOutputData": true,
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Start Typing",
        "session": "={{ $('Padronizar Output').first().json.target_session || 'default' }}",
        "chatId": "={{ $('Padronizar Output').first().json.target_chat_id }}",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        2944,
        896
      ],
      "id": "e3a76892-860a-47a6-b36e-411f7deb1b3f",
      "name": "Start Typing",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        3088,
        896
      ],
      "id": "83c21e59-e1b2-438a-add8-58cabddca665",
      "name": "Wait"
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Send Text",
        "session": "={{ $('Padronizar Output').first().json.target_session || 'default' }}",
        "chatId": "={{ $('Padronizar Output').first().json.target_chat_id }}",
        "reply_to": "=",
        "text": "={{ $json.text }}",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        3392,
        896
      ],
      "id": "bcc3a72f-fa00-4643-a156-96f6a2c56df0",
      "name": "Send a text message",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "={{ ('http://waha:3000/api/' + $json.session + '/lids/' + encodeURIComponent(($json.from || '').trim())).trim() }}\n\n",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            },
            {
              "name": "X-Api-Key",
              "value": "GR15VC0m5ueLygSMQPM6In4A8qfnrLT31ECnIEmZvnfyovsGxjUSfaFcMi1YQ3E1VvR9WjdJijFKGllhKAhkQ6yNYzYstzwtlQODhb06lknx3j8JlfxA7UCbzKCe61nbb"
            }
          ]
        },
        "options": {}
      },
      "id": "d0c6e226-75d7-4121-b51e-189f2c749c5d",
      "name": "Consultar WAHA Direto",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        320,
        -288
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "custom-field",
              "name": "PhoneNumber",
              "value": "={{ $json.pn ? $json.pn.split('@')[0] : undefined }}",
              "type": "string"
            },
            {
              "id": "835b86bc-37d1-4742-a421-3247982275a9",
              "name": "LidNumber",
              "value": "={{ $json.lid ? $json.lid.split('@')[0] : undefined }}",
              "type": "string"
            },
            {
              "id": "92fd4ba6-2d13-4ff9-b215-8895fd828fa2",
              "name": "isGroup",
              "value": "={{ ($json.pn || '').endsWith('@g.us') }}",
              "type": "boolean"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "4575405f-68cb-4ebe-a937-ca0b67c9a886",
      "name": "Limpar Telefone",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        480,
        -288
      ]
    },
    {
      "parameters": {
        "jsCode": "// BUSCA DOS DADOS: Pegamos o input que vem do CheckOrigem (o dado 'fresco' da execu\u00e7\u00e3o)\nconst input = $(\"CheckOrigem\").first().json;\nconst wa = input.wa || {}; \n\nlet mensagens = [];\ntry {\n  const redisNode = $(\"Recuperar_Buffer\").first();\n  const redis = (redisNode && redisNode.json) ? redisNode.json : {};\n  // O Redis GET retorna o buffer em Redis_Check_Buffer ou value\n  const conteudo = redis.Redis_Check_Buffer || redis.value;\n  if (conteudo) {\n      const parsed = typeof conteudo === 'string' ? JSON.parse(conteudo) : conteudo;\n      mensagens = (parsed && parsed.msgs) ? parsed.msgs : (Array.isArray(parsed) ? parsed : []);\n  }\n} catch (e) { mensagens = []; }\n\n// Garante que temos um id \u00fanico para esta mensagem\nconst messageId = wa.messageId || (\"wa_\" + Date.now());\n// Pega o texto real que o NormalizeInbound capturou\nconst textoAtual = wa.text || input.user_text || input.message || \"\";\n\n// Adiciona ao hist\u00f3rico se n\u00e3o existir\nif (!mensagens.some(m => m.id === messageId)) {\n    mensagens.push({ id: messageId, texto: textoAtual, exec_id: $execution.id });\n}\n\nreturn [{\n    json: {\n        ...input,\n        wa: {\n            ...wa,\n            messageId: messageId,\n            text: textoAtual\n        },\n        texto_combinado: mensagens.map(m => m.texto).join(' \\n '),\n        msgs: mensagens,\n        minha_execucao: $execution.id\n    }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        32,
        496
      ],
      "id": "a385b8dc-b279-49ce-be12-b8cb49b691b5",
      "name": "Agrupar_Texto"
    },
    {
      "parameters": {
        "operation": "set",
        "key": "=buffer:{{ $('CheckOrigem').first().json.wa.chatId }}",
        "value": "={{ JSON.stringify($json) }}",
        "expire": true,
        "ttl": 10
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        176,
        592
      ],
      "id": "0cde3c3a-85d4-4c3f-a6ab-0a45760dc563",
      "name": "Atualizar_Buffer",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "amount": 3
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        336,
        496
      ],
      "id": "6639e308-e336-4025-bc1a-2a771ea4e122",
      "name": "Espera_3_Segundos"
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "Redis_Check_Final",
        "key": "=buffer:{{ $('CheckOrigem').first().json.wa.chatId }}",
        "options": {}
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        480,
        576
      ],
      "id": "852c54e0-ef5b-45bd-87ed-a8957d7762ec",
      "name": "Check_Pos_Espera",
      "alwaysOutputData": true,
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "Redis_Check_Buffer",
        "key": "=buffer:{{ $('CheckOrigem').first().json.wa.chatId }}",
        "options": {}
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        -128,
        608
      ],
      "id": "519dc24e-9d82-4b8f-8464-3827a8ee9b64",
      "name": "Recuperar_Buffer",
      "alwaysOutputData": true,
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "{{ $json.tecnico.isGroup }}",
                    "rightValue": "false",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "9d8b45b5-c151-4e99-bdaf-6306764ea594"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "27953cd9-b238-4be3-9db8-7f15b5635ba4",
                    "leftValue": "{{ $json.tecnico.source }}",
                    "rightValue": "api",
                    "operator": {
                      "type": "string",
                      "operation": "notContains"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "ffff129c-9a55-4c12-a18f-e84e087b7a88",
                    "leftValue": "{{ $json.tecnico.fromMe }}",
                    "rightValue": "false",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        1008,
        480
      ],
      "id": "196540f4-21a8-4596-9a03-c77ae2fbfc45",
      "name": "SwitchOrigem"
    },
    {
      "parameters": {
        "jsCode": "// 1. Limpeza de Newlines e Normaliza\u00e7\u00e3o de Input\nconst rawInput = $input.first().json;\nconst input = {};\nfor (const key in rawInput) {\n    if (typeof rawInput[key] === 'string') {\n        input[key] = rawInput[key].trim();\n    } else {\n        input[key] = rawInput[key];\n    }\n}\n\nlet wa = input.wa || {};\nlet perguntaCliente = input.pergunta_cliente || input.message || \"\";\n\ntry {\n    const nodeInbound = $(\"NormalizeInbound\").first().json;\n    if (nodeInbound) {\n        if (nodeInbound.wa && nodeInbound.wa.provider) {\n             wa = { ...nodeInbound.wa, ...wa };\n        }\n        if (!perguntaCliente) perguntaCliente = nodeInbound.pergunta_cliente || \"\";\n    }\n} catch(e) {}\n\n// 2. Detecta Origem Real (Detectamos se \u00e9 Portal ou Chat P\u00fablico da Home)\nconst isPortal = (wa.provider === 'portal') || \n                 (input.source === 'PORTAL_WEB') || \n                 (input.origem === 'PORTAL_WEB') || \n                 (input.event && input.event.includes('dashboard')) || \n                 !!input.identifier || \n                 !!input.session_id; // Identifica o chat da Home\n\nconst isWhatsApp = !isPortal;\n\nif (isWhatsApp) {\n    const pn = (input.PhoneNumber || (wa.chatId ? wa.chatId.split('@')[0] : (input.from || \"\"))).toString().trim();\n    return [{\n        json: {\n            wa: {\n                ...wa,\n                provider: \"waha\",\n                session: (wa.session || input.session || \"default\").trim(),\n                chatId: (wa.chatId || (pn + \"@c.us\")).trim(),\n                name: (wa.name || input.name || \"\").trim(),\n                messageId: (wa.messageId || input.payload_id || (\"wa_\" + Date.now())).trim(),\n                text: (wa.text || perguntaCliente || \"\").trim()\n            },\n            pergunta_cliente: (perguntaCliente || wa.text || \"\").trim(),\n            cliente: {\n                phoneNumber: pn,\n                nome_whatsapp: (wa.name || input.name || \"\").trim()\n            },\n            ...input \n        }\n    }];\n} else {\n    // L\u00d3GICA PORTAL / HOME\n    const portalId = (input.session_id || input.identifier || input.cpf || \"portal_user\").toString().trim();\n    \n    return [{\n        json: {\n            wa: {\n                ...wa,\n                provider: \"portal\",\n                session: (input.session_id) ? portalId : (wa.session || portalId + \"_v2\").trim(),\n                chatId: (wa.chatId || input.chat_id || portalId).trim(),\n                name: (input.client_name || input.name || \"\").trim(),\n                messageId: (wa.messageId || \"web_\" + Date.now()).trim(),\n                text: (perguntaCliente || wa.text || \"\").trim()\n            },\n            pergunta_cliente: (perguntaCliente || wa.text || \"\").trim(),\n            ...input\n        }\n    }];\n}\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -304,
        496
      ],
      "id": "074849fb-1ea8-43a5-992f-68a9d3a82777",
      "name": "CheckOrigem"
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "sessaoExistente",
        "key": "=status_2fa:{{ $('CheckOrigem').first().json.wa.chatId }}",
        "options": {
          "dotNotation": true
        }
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        1344,
        496
      ],
      "id": "65bfc741-9977-4ef4-9985-c37b35b53b55",
      "name": "Buscar_Sessao_Existente",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "let cliente = {};\ntry { \n    const busca = $(\"Busca_Cliente\").first();\n    if (busca && busca.json && busca.json.id_cliente) { cliente = busca.json; }\n} catch(e) {}\n\nconst wa = $json.wa || {};\nconst chatId = wa.chatId || \"\";\nconst phoneNumber = (chatId.replace(\"@c.us\", \"\") || $json.PhoneNumber || $json.telefone || \"\").toString();\n\nlet consolidado = {};\ntry { consolidado = $(\"ConsolidarMensagem\").first().json || {}; } catch(e) {}\n\nlet perguntaAgente = consolidado.mensagem_final || wa.text || $json.pergunta_cliente || \"\";\n\n// VERIFICA\u00c7\u00c3O DE SEGURAN\u00c7A\nlet isValid = false;\ntry {\n    const nodeRedis = $(\"Buscar_Sessao_Existente\").first();\n    if (nodeRedis && nodeRedis.json && nodeRedis.json.sessaoExistente === \"VALIDADO\") { isValid = true; }\n    \n    if (wa.authenticated === true || $json.authenticated === true || $json.token_validado === \"SIM\") { \n        isValid = true; \n    }\n} catch (e) { isValid = false; }\n\n// INSTRU\u00c7\u00c3O DIN\u00c2MICA DE ACESSO\nconst isPortal = wa.provider === 'portal' || $json.origem === 'PORTAL_WEB';\nlet instrucaoAcesso = \"\";\nif (isPortal && isValid) {\n    instrucaoAcesso = \"Como voc\u00ea j\u00e1 est\u00e1 logado, voc\u00ea pode acessar todos os detalhes de suas ap\u00f3lices e baixar documentos diretamente no menu lateral esquerdo do portal! \ud83d\ude0a\";\n} else {\n    instrucaoAcesso = \"Para acessar seus dados e documentos com seguran\u00e7a, acesse nosso portal:\\n\ud83d\udd17 https://brokeria-api-brokeriaweb.cx0m9g.easypanel.host/login.html\\n\\nL\u00e1 voc\u00ea encontra todas as suas informa\u00e7\u00f5es e pode baixar seus documentos! \ud83d\ude0a\";\n}\n\n// =========================================================\n// PROCESSAMENTO DE AP\u00d3LICES\n// =========================================================\nlet todasApolices = (cliente.apolices_detalhadas || []);\n\n// LISTA PARA RESPOSTAS GERAIS\nlet listaFormatada = todasApolices.map(ap => {\n    const status = String(ap.status_apolice || 'INDEFINIDO').toUpperCase();\n    const vigencia = (ap.vigencia_inicio && ap.vigencia_fim) \n        ? `${new Date(ap.vigencia_inicio).toLocaleDateString('pt-BR')} at\u00e9 ${new Date(ap.vigencia_fim).toLocaleDateString('pt-BR')}`\n        : 'Vig\u00eancia n\u00e3o informada';\n    \n    return `- ${ap.seguradora || 'Seguradora N/A'} | Ramo: ${ap.ramo || 'Seguro'} | Status: ${status} | Vig\u00eancia: ${vigencia} | Placa: ${ap.placa || 'N/A'} | Assist\u00eancia 24h: ${ap.telefone_0800 || 'N\u00e3o informado'} / ${ap.telefone_capital || 'N\u00e3o informado'} | Site: ${ap.site_url || 'N\u00e3o informado'}`;\n}).join('\\n');\n\n// DADOS CR\u00cdTICOS PARA SINISTRO (Garantia de Match)\nlet dadosSinistroCritico = todasApolices.filter(ap => \n    String(ap.status_apolice).toUpperCase() === 'ATIVA'\n).map(ap => {\n    return `[DADOS DE EMERG\u00caNCIA] Seguradora: ${ap.seguradora.toUpperCase()} | Ramo: ${ap.ramo} | Assist\u00eancia 24h: ${ap.telefone_0800} / ${ap.telefone_capital} | Site para Sinistro: ${ap.site_url}`;\n}).join('\\n');\n\nif (todasApolices.length === 0) {\n    listaFormatada = \"Nenhuma ap\u00f3lice encontrada.\";\n    dadosSinistroCritico = \"CLIENTE SEM AP\u00d3LICES ATIVAS NO SISTEMA.\";\n}\n\nlet apolicesAtivas = todasApolices.filter(ap => \n    ap && ap.status_apolice && String(ap.status_apolice).toUpperCase() === 'ATIVA'\n);\n\nconst apolicesSeguras = apolicesAtivas.map(ap => ({\n    seguradora: ap.seguradora,\n    ramo: ap.ramo,\n    status: ap.status_apolice,\n    numero_apolice: isValid ? ap.numero_apolice : \"(Bloqueado)\",\n    vencimento: isValid ? ap.vigencia_fim : \"(Bloqueado)\",\n    placa: (ap.placa && isValid) ? ap.placa : (ap.placa ? \"***-****\" : \"N/A\"),\n    link_download: isValid ? (ap.link_url_apolice || \"Nao disponivel\") : \"(Oculto)\",\n    telefone_0800: ap.telefone_0800 || \"Nao informado\",\n    telefone_capital: ap.telefone_capital || \"Nao informado\",\n    site_seguradora: ap.site_url || \"Nao informado\"\n}));\n\nreturn [{\n    json: {\n        pergunta_cliente: perguntaAgente,\n        contexto: {\n            nome: (cliente.nome_identificado || cliente.nome_completo || wa.name || $json.client_name || \"\").trim(),\n            cpf_real: (cliente.cpf || $json.cpf || \"\").toString().replace(/\\D/g, ''), \n            cpf_exibicao: (cliente.cpf || $json.cpf) ? `***.***.***-${(cliente.cpf || $json.cpf).toString().slice(-2)}` : \"Nao informado\",\n            telefone: (cliente.celular || phoneNumber || $json.telefone || \"\").toString(),\n            email_cadastrado: (cliente.email || $json.email || \"\").toString(),\n            token_validado: isValid ? \"SIM\" : \"NAO\",\n            instrucao_acesso: instrucaoAcesso,\n            cadastrado: !!cliente.id_cliente,\n            id_cliente: cliente.id_cliente || null,\n            resumo_apolices: apolicesSeguras,\n            lista_apolices_texto: listaFormatada,\n            dados_sinistro_critico: dadosSinistroCritico,\n            tipo_cliente: cliente.id_cliente ? \"CADASTRADO\" : \"NOVO\",\n            origem: wa.provider || $json.origem || \"WHATSAPP\"\n        }\n    }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2592,
        544
      ],
      "id": "e18193c3-0e64-494f-ad07-ee8e0e9c90ae",
      "name": "DefinirContextoAI",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.wa?.type || 'chat' }}",
                    "rightValue": "audio|ptt",
                    "operator": {
                      "type": "string",
                      "operation": "regex"
                    },
                    "id": "0dc49c03-4595-4987-ac0a-3fc9d3a6155c"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "6b2eacf3-4648-4f87-855c-274503889af2",
                    "leftValue": "={{ $json.wa?.type || 'chat' }}",
                    "rightValue": "image",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "7102c9ec-2c9e-4121-856c-7e44d524cbb7",
                    "leftValue": "={{ $json.wa?.type || 'chat' }}",
                    "rightValue": "chat",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.3,
      "position": [
        1552,
        480
      ],
      "id": "18f8c15c-68d3-44a5-b7a5-f4145d0178bf",
      "name": "SwitchMidia"
    },
    {
      "parameters": {
        "url": "={{ ($json.wa?.media_url || \"\").replace(/https?:\\/\\/[^\\/]+/, 'http://waha:3000') }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wahaApi",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        1824,
        128
      ],
      "id": "0c9ce326-b51f-4022-a475-e0c311be403d",
      "name": "DownloadMidia",
      "alwaysOutputData": false,
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "audio",
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.0-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.0-flash"
        },
        "inputType": "binary",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        2000,
        128
      ],
      "id": "65ca2c1e-8e55-4a58-809f-d4f009d0ea02",
      "name": "IA_Processar_Audio",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput",
      "notes": "Em caso de erro, prossiga o chat."
    },
    {
      "parameters": {
        "url": "={{ ($json.wa?.media_url || \"\").replace(/https?:\\/\\/[^\\/]+/, 'http://waha:3000') }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wahaApi",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        1824,
        288
      ],
      "id": "aa40f9ea-14e5-4bc2-8e53-ee78d44cc899",
      "name": "ImageDownload",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "image",
        "operation": "analyze",
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.0-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.0-flash"
        },
        "text": "=Analise a imagem e d\u00c3\u00aa detalhes do que tem nela:\n  - Se for a imagem de um documento, procure fazer o reconhecimento atrav\u00c3\u00a9s do t\u00c3\u00adtulo ou qualquer coisa permita a correta identifica\u00c3\u00a7\u00c3\u00a3o\n  - Se for a imagem de um veiculo, procure identifica-lo (moto, carro ou caminh\u00c3\u00a3o), al\u00c3\u00a9m de modelo, cor e principalmente se identificado alguma batida etc. \n  - Se for qualquer outro tipo de imagem, analise de forma geral\n\nA pessoa que enviou essa imagem mencionou: {{ $node[\"CheckOrigem\"].json.input_bruto.user_text || \"N\u00c3\u00a3o mencionou nada\" }}",
        "inputType": "binary",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        2000,
        288
      ],
      "id": "0e6d0742-2385-4771-a3ca-3dba2b1172d8",
      "name": "IA_Processar_Imagem",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput",
      "notes": "Em caso de erro, prossiga o chat."
    },
    {
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst wa = input.wa || {};\n\n// Busca em TODAS as fontes poss\u00edveis, com \u00e2ncoras fixas\nlet textoFinal = \"\";\n\ntry {\n    // 1. Tenta pegar o texto j\u00e1 agrupado (Melhor fonte para o Bot)\n    textoFinal = $(\"Agrupar_Texto\").first().json.texto_combinado;\n} catch(e) {\n    try {\n        // 2. Tenta pegar o texto que passou pelo CheckOrigem\n        textoFinal = $(\"CheckOrigem\").first().json.wa.text;\n    } catch(e2) {\n        // 3. Fallback para o input atual\n        textoFinal = wa.text || input.message || input.user_text || \"\";\n    }\n}\n\n// Verifica se houve erro em n\u00f3s de m\u00eddia anteriores (Audio/Imagem)\nconst erroMidia = !!input.houve_erro_midia;\n\nif (textoFinal) {\n    textoFinal = textoFinal.replace(/\\[\\d{2}:\\d{2}, \\d{2}\\/\\d{2}\\/\\d{4}\\] .*?: /g, \"\");\n}\n\n\nreturn [{\n    json: {\n        ...input,\n        wa: {\n            ...wa,\n            text: textoFinal || wa.text || \"\"\n        },\n        mensagem_final: (textoFinal || \"\").trim(),\n        pergunta_cliente: (textoFinal || \"\").trim(),\n        tipo_entrada: input.tipo_entrada || wa.mediaType || \"chat\",\n        teve_erro_ia: erroMidia,\n        houve_erro_midia: erroMidia // <-- AGORA O SWITCH VAI FUNCIONAR!\n    }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2256,
        528
      ],
      "id": "f9d2844f-fb00-4f82-a59f-7c705ffe1e79",
      "name": "ConsolidarMensagem",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.houve_erro_midia }}",
                    "rightValue": "",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "id": "5280c04a-9876-4f53-a252-2e8fff6d4d73"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "63991c1f-d6e5-45f5-a188-beca30f15b0c",
                    "leftValue": "={{ $json.houve_erro_midia }}",
                    "rightValue": "If Boolean is False: Conecte ao n\u00c3\u00b3 DefinirContextoAI.",
                    "operator": {
                      "type": "boolean",
                      "operation": "false",
                      "singleValue": true
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        2400,
        528
      ],
      "id": "5caeeced-2fa4-4b6e-aaf7-317e84f07f7a",
      "name": "TratamentoErroMidia"
    },
    {
      "parameters": {
        "model": "google/gemini-2.5-flash",
        "options": {
          "maxTokens": 2048
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "typeVersion": 1,
      "position": [
        1232,
        1504
      ],
      "id": "17e213a9-e427-4400-b935-37aaac786030",
      "name": "OpenRouter Chat Model1",
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ (() => { try { const tel = $('DefinirContextoAI').first().json.contexto.telefone; if (tel) return tel + '_v2'; } catch(e) {} try { return $('MontarContextoPortal').first().json.session_key; } catch(e) {} return 'FALLBACK_' + Date.now(); })() }}",
        "contextWindowLength": 6
      },
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "typeVersion": 1.3,
      "position": [
        1424,
        1504
      ],
      "id": "4a4153cc-90c0-410f-85ff-4910398285cf",
      "name": "PostgresChatMemory",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "NOME: Validador_Cliente_Brokeria\n\nQUANDO USAR:\n1. Quando um usu\u00c3\u00a1rio desconhecido (telefone n\u00c3\u00a3o cadastrado) afirma ser cliente e fornece o documento ou e-mail.\n2. Quando um usu\u00c3\u00a1rio j\u00c3\u00a1 identificado solicita acesso a dados sens\u00c3\u00adveis (ap\u00c3\u00b3lices, altera\u00c3\u00a7\u00c3\u00b5es cadastrais) e precisa revalidar a identidade.\n\nINPUT:\nO cliente deve fornecer o CPF (11 d\u00c3\u00adgitos), CNPJ (14 d\u00c3\u00adgitos) OU o E-mail cadastrado.\nExemplo JSON: { \"documento\": \"12345678900\" } ou { \"documento\": \"teste@email.com\" }\n\nRETORNO:\nRetorna os dados cadastrais completos do cliente. Retorna vazio se n\u00c3\u00a3o encontrar.",
        "operation": "executeQuery",
        "query": "SELECT * FROM public.clientes_brokeria\nWHERE cpf = '{{\n  (() => {\n    const val = $json.documento ? $json.documento.toString() : \"\";\n    if (val.includes(\"@\")) return \"EMAIL_QUERY_BYPASS\";\n    const doc = val.replace(/\\D/g, \"\");\n    if (doc.length !== 11 && doc.length !== 14) return \"000\";\n    return doc;\n  })()\n}}' OR email = '{{ $json.documento }}';",
        "options": {}
      },
      "type": "n8n-nodes-base.postgresTool",
      "typeVersion": 2.6,
      "position": [
        1616,
        1504
      ],
      "id": "2a8d694c-c721-4a2f-ac00-df0c74785cfa",
      "name": "QueryPostgresClientes",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "f13f09b9-af26-4aa3-9761-edc7d76ff32e",
              "name": "wa.chatId",
              "value": "={{ $json.PhoneNumber ? $json.PhoneNumber + '@c.us' : $json.wa.chatId }}",
              "type": "string"
            },
            {
              "id": "fdb1c7bb-c3a8-4a98-a52e-563720599d08",
              "name": "wa.session",
              "value": "={{ $json.session || 'default' }}",
              "type": "string"
            },
            {
              "id": "178fd429-e3cb-4404-ba2e-bb9a4878ec3f",
              "name": "wa.name",
              "value": "={{ $json.wa?.name || $json.name || $json.pushName || '' }}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        688,
        -288
      ],
      "id": "590f7ca2-9a76-40ee-a9ed-e4c6af67a262",
      "name": "FinalizeChatId"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "final_text",
              "name": "response_text",
              "value": "={{ $json.mensagem_final || $json.mensagem || $json.output || \"Erro: N\u00c3\u00a3o foi poss\u00c3\u00advel recuperar a mensagem.\" }}",
              "type": "string"
            },
            {
              "id": "target_chat",
              "name": "target_chat_id",
              "value": "={{ $('CheckOrigem').first().json.wa.chatId }}",
              "type": "string"
            },
            {
              "id": "target_session",
              "name": "target_session",
              "value": "={{ $('CheckOrigem').first().json.wa.session }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        2640,
        896
      ],
      "id": "1aeef07f-9af3-4858-b8ac-bb3d449b4e10",
      "name": "Padronizar Output"
    },
    {
      "parameters": {
        "jsCode": "// Este n\u00c3\u00b3 apenas coleta o que chegar e passa adiante\nreturn $input.all();"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1744,
        976
      ],
      "id": "60cdd828-f544-4fa9-99d9-63b772f626ea",
      "name": "FunilRespostas"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO public.brokeria_registros_brokeria (\n  telefone_whatsapp, \n  nome_cliente, \n  resumo_conversa, \n  assunto_principal,\n  subtipo_solicitacao,\n  tipo_seguro,\n  prioridade,\n  tipo_cliente,\n  status_atendimento, \n  data_atendimento,\n  canal,\n  qtde_mensagens\n)\nVALUES (\n  '{{ $(\"DefinirContextoAI\").first().json.contexto.telefone }}',\n  '{{ $(\"DefinirContextoAI\").first().json.contexto.nome }}',\n  E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || '{{ $(\"DefinirContextoAI\").first().json.contexto.nome }}' || E': ' || '{{ ($(\"DefinirContextoAI\").first().json.contexto.input_user || \"\").replace(/'/g, \"''\") }}' || E'\\n' ||\n  E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] BrokerIA: ' || '{{ ($json.text || $json.output || \"\").replace(/'/g, \"''\") }}' || E'\\n',\n  '{{ $json.tipo_solicitacao || \"Informa\u00c3\u00a7\u00c3\u00b5es Gerais\" }}',\n  '{{ $json.subtipo_solicitacao || \"D\u00c3\u00bavidas gerais\" }}',\n  '{{ $json.tipo_seguro || \"OUTROS\" }}',\n  '{{ $json.prioridade || \"M\u00c3\u00a9dia\" }}',\n  '{{ $json.tipo_cliente || \"N\u00c3\u00a3o cliente\" }}',\n  'PENDENTE',\n  CURRENT_DATE,\n  '{{ $(\"DefinirContextoAI\").first().json.contexto.origem || \"WHATSAPP\" }}',\n  1\n)\nON CONFLICT (telefone_whatsapp, data_atendimento) \nDO UPDATE SET \n  resumo_conversa = brokeria_registros_brokeria.resumo_conversa || \n         E'\\n' ||\n         E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || EXCLUDED.nome_cliente || E': ' || '{{ ($(\"DefinirContextoAI\").first().json.contexto.input_user || \"\").replace(/'/g, \"''\") }}' || E'\\n' ||\n         E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] BrokerIA: ' || '{{ ($json.text || $json.output || \"\").replace(/'/g, \"''\") }}' || E'\\n',\n  qtde_mensagens = COALESCE(brokeria_registros_brokeria.qtde_mensagens, 0) + 1,\n  assunto_principal = EXCLUDED.assunto_principal,\n  subtipo_solicitacao = EXCLUDED.subtipo_solicitacao,\n  prioridade = EXCLUDED.prioridade,\n  data_ultima_atualizacao = NOW();",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        2448,
        896
      ],
      "id": "4c10015b-1bb8-46af-be6b-af2a82231c19",
      "name": "Registrar_Interacao",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "// 1. Coleta a mensagem de todas as fontes poss\u00edveis\nlet mensagem = $json.response_text || $json.mensagem_final || $json.output || $json.text || \"\";\n\n// 2. Se a mensagem ainda estiver vazia, tenta buscar diretamente no n\u00f3 do Agente\nif (!mensagem || mensagem === \"\") {\n    try {\n        mensagem = $(\"BrokerIA_Master\").first().json.output;\n    } catch(e) {}\n}\n\n// 3. Limpeza de logs t\u00e9cnicos\nmensagem = mensagem.replace(/\\[Used tools:.*?\\]/gis, '')\n                   .replace(/Tool:.*?(?=\\n|$)/gi, '')\n                   .replace(/Input:.*?(?=\\n|$)/gi, '')\n                   .replace(/Result:.*?(?=\\n|$)/gi, '')\n                   .replace(/\\{.*?\"accepted\".*?\\}/gs, '')\n                   .replace(/\\n{3,}/g, '\\n\\n').trim();\n\n// 4. RETORNAR APENAS A MENSAGEM (SEM FALLBACK DE OL\u00c1)\nreturn {\n  json: {\n    ...$json,\n    text: mensagem\n  }\n};\n\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3232,
        896
      ],
      "id": "c7f10e80-0c1f-4d7c-9237-8e0bf822535a",
      "name": "FiltrarResposta"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.pergunta_cliente }}\n\n",
        "options": {
          "systemMessage": "======================================================================\n\ud83d\udcf1 FORMATO DE RESPOSTA (ESTILO MENU/URA) - CR\u00cdTICO\n==================================================================\nPara melhorar a experi\u00eancia do usu\u00e1rio, sempre que o cliente solicitar algo que tenha categorias ou variantes, APRESENTE AS OP\u00c7\u00d5ES EM LISTA NUMERADA.\nO objetivo \u00e9 permitir que o cliente responda de forma r\u00e1pida e simples (apenas digitando o n\u00famero).\n\nEXEMPLO DE INTERA\u00c7\u00c3O OBRIGAT\u00d3RIA:\nCliente: \"Quero uma cota\u00e7\u00e3o\"\nVoc\u00ea: \"\u00d3timo! Para qual tipo de seguro voc\u00ea deseja cota\u00e7\u00e3o?\n1. Autom\u00f3vel \ud83d\ude97\n2. Residencial \ud83c\udfe0\n3. Vida \u2764\ufe0f\n4. Empresarial \ud83c\udfe2\n5. Outros Assist\u00eancias\"\n\nPRIORIZE SEMPRE esse formato de \"URA Inteligente/Menu\" em vez de perguntas abertas.\n\n=================================================================\n\ud83d\udea8 SINISTROS E EMERG\u00caNCIAS - PROTOCOLO \"FONTE DE VERDADE\" \ud83d\udea8\n=================================================================\nSe o cliente relatar um sinistro (acidente, roubo, furto, colis\u00e3o) ou precisar de assist\u00eancia:\n1. Demonstre empatia imediata (ex: \"Sinto muito pelo ocorrido, vou te ajudar agora.\").\n2. VOC\u00ca DEVE BUSCAR OS DADOS DE CONTATO E AP\u00d3LICE EXCLUSIVAMENTE NESTE CAMPO:\n   \ud83d\udc49 {{ $json.contexto.dados_sinistro_critico }}\n3. REGRAS DE OURO PARA SINISTRO:\n   - APRESENTE SEMPRE o n\u00famero da ap\u00f3lice (mesmo que mascarado) para facilitar a identifica\u00e7\u00e3o do cliente perante a seguradora.\n   - NUNCA mencione seguradoras que n\u00e3o estejam na lista acima.\n   - Forne\u00e7a os telefones de assist\u00eancia (0800 e Capital) e o site EXATAMENTE como constam no campo cr\u00edtico.\n   - Se a lista estiver vazia ou disser \"SEM AP\u00d3LICES ATIVAS\", diga que n\u00e3o localizou uma ap\u00f3lice ativa e pe\u00e7a o CPF para confer\u00eancia.\n\n=================================================================\n\ud83c\udf10 PORTAL DO CLIENTE vs WHATSAPP - L\u00d3GICA DE RESPOSTA\n=================================================================\nVoc\u00ea deve identificar onde o cliente est\u00e1 falando (Origem: {{ $json.contexto.origem }}).\n\n\ud83d\ude80 CEN\u00c1RIO A: CLIENTE NO PORTAL (origem: portal)\n- O cliente J\u00c1 EST\u00c1 LOGADO e SEGURO.\n- N\u00c3O ENVIE links de login ou instru\u00e7\u00f5es de acesso ao portal.\n- Responda DIRETAMENTE \u00e0s perguntas sobre ap\u00f3lices, vencimentos e dados usando o resumo dispon\u00edvel.\n- Se ele pedir documentos, diga: \"Voc\u00ea pode baixar seus documentos clicando no menu lateral esquerdo aqui no portal! \ud83d\ude0a\"\n\n\ud83d\udcf1 CEN\u00c1RIO B: CLIENTE NO WHATSAPP (origem: waha)\n- Redirecione para o portal para: COTA\u00c7\u00d5ES, Documentos detalhados ou altera\u00e7\u00f5es cadastrais.\n- Use a RESPOSTA PADR\u00c3O: \"{{ $json.contexto.instrucao_acesso }}\"\n\n=================================================================\n\ud83d\udccb REGISTRO DE COTA\u00c7\u00d5ES - REGRA OBRIGAT\u00d3RIA\n=================================================================\nQuando o cliente solicitar uma cota\u00e7\u00e3o:\n1. Primeiro, ofere\u00e7a a cota\u00e7\u00e3o pelo portal (especialmente no WhatsApp):\n\ud83d\udd17 https://brokeria-api-brokeriaweb.cx0m9g.easypanel.host/cotacao.html\n\n\u274c N\u00c3O pe\u00e7a telefone ou e-mail.\n\u274c N\u00c3O diga que vai passar para o corretor Washington para fazer a cota\u00e7\u00e3o.\nOriente sempre o autoatendimento pelo link acima.\n\n-----------------------------------------------------------------\n\ud83d\udd0d CONTEXTO DIN\u00c2MICO\n-----------------------------------------------------------------\n- Cliente: {{ $json.contexto.nome }}\n- CPF: {{ $json.contexto.cpf_exibicao }}\n- Telefone: {{ $json.contexto.telefone }}\n- Email Cadastrado: {{ $json.contexto.email_cadastrado }}\n\nREGRAS DE OURO:\n1. Sempre use o nome do cliente: {{ $json.contexto.nome.split(' ')[0] }}.\n2. Se o cliente perguntar sobre seguros, ofere\u00e7a uma cota\u00e7\u00e3o usando o formato de lista e o link do portal.\n\nINSTRUCAO DE RESPOSTA:\nResponda de forma curta e objetiva. Nao invente informacoes. Se nao souber algo fora do escopo de cota\u00e7\u00f5es, diga que vai transferir para o corretor Washington.\n\n\ud83d\udcca RESUMO COMPLETO DE AP\u00d3LICES:\n{{ $json.contexto.lista_apolices_texto }}\n\n=================================================================\n\ud83d\udccb INFORMA\u00c7\u00d5ES INSTITUCIONAIS\n=================================================================\nRespons\u00e1vel: Washington William de Oliveira | Susep: 10.2028529.9\nWebsite: https://www.dwfseguros.com.br\n\n=================================================================\n\ud83d\udeab LIMITES E LGPD\n=================================================================\n- COTA\u00c7\u00d5ES: NUNCA forne\u00e7a valores de pr\u00eamio e NUNCA pe\u00e7a dados de contato. Encaminhe ao link de cota\u00e7\u00e3o.\n- CPF/CNPJ: SEMPRE mascarado.\n- Seja formal, consultivo e simp\u00e1tico. Saude sempre pelo primeiro nome.\n\n\n\n",
          "maxIterations": 10
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        1440,
        976
      ],
      "id": "8cb54808-2c3b-44a5-bf9c-39188751c7db",
      "name": "BrokerIA_Master",
      "executeOnce": false,
      "alwaysOutputData": false,
      "notesInFlow": false
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.contexto.tipo_cliente }}",
                    "rightValue": "=NOVO",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "75010c00-aec1-42d3-ae87-3d67526f7c3b"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "d4159ee7-e43a-477d-90f3-a5e7ac29d9d5",
                    "leftValue": "={{ $json.contexto.tipo_cliente }}",
                    "rightValue": "=CADASTRADO",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        2976,
        544
      ],
      "id": "6ca5643e-f13d-41d4-a8f3-2f48782bf5f2",
      "name": "Check_Cliente_Novo"
    },
    {
      "parameters": {
        "jsCode": "// RECUPERA DADOS\nconst contexto = $json.contexto || {};\nconst pergunta = $json.pergunta_cliente || \"\";\nconst perguntaLower = pergunta.toLowerCase();\n\n// ==========================================\n// 1. RAMO DO SEGURO (Mapeamento Inteligente)\n// ==========================================\nlet ramoSeguro = \"OUTROS\";\nif (perguntaLower.match(/auto|carro|veic|moto|placa/)) ramoSeguro = \"AUTOMOVEL\";\nelse if (perguntaLower.match(/casa|resid|apart|lar|home/)) ramoSeguro = \"RESIDENCIAL\";\nelse if (perguntaLower.match(/vida|falec|morte|funeral/)) ramoSeguro = \"VIDA\";\nelse if (perguntaLower.match(/saude|m\u00c3\u00a9dic|plano|hospit/)) ramoSeguro = \"SAUDE\";\nelse if (perguntaLower.match(/empresa|pj|comercial/)) ramoSeguro = \"EMPRESARIAL\";\n\n// ==========================================\n// 2. N\u00c3\u008dVEL 1 E N\u00c3\u008dVEL 2 (Classifica\u00c3\u00a7\u00c3\u00a3o)\n// ==========================================\nlet nivel1 = \"Informa\u00c3\u00a7\u00c3\u00b5es Gerais\";\nlet nivel2 = \"D\u00c3\u00bavidas gerais sobre seguros\";\nlet prioridade = \"M\u00c3\u00a9dia\";\n\n// L\u00c3\u00b3gica de Classifica\u00c3\u00a7\u00c3\u00a3o Hier\u00c3\u00a1rquica\nif (perguntaLower.match(/cota\u00c3\u00a7\u00c3\u00a3o|cotacao|quanto custa|valor|pre\u00c3\u00a7o|contratar/)) {\n    nivel1 = \"Vendas e Cota\u00c3\u00a7\u00c3\u00b5es\";\n    nivel2 = \"Cota\u00c3\u00a7\u00c3\u00a3o de seguro novo\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/sinistro|bati|acidente|roubo|furto|colis\u00c3\u00a3o/)) {\n    nivel1 = \"Sinistros\";\n    nivel2 = \"Aviso de sinistro\";\n    prioridade = \"Cr\u00c3\u00adtica\";\n} else if (perguntaLower.match(/boleto|pagar|parcela|paguei|segunda via|2 via/)) {\n    nivel1 = \"Financeiro\";\n    nivel2 = \"Segunda via de boleto\";\n} else if (perguntaLower.match(/renovar|renova\u00c3\u00a7\u00c3\u00a3o|vencimento|venceu/)) {\n    nivel1 = \"Renova\u00c3\u00a7\u00c3\u00a3o\";\n    nivel2 = \"Renova\u00c3\u00a7\u00c3\u00a3o autom\u00c3\u00a1tica\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/cancelar|cancelamento|desistir/)) {\n    nivel1 = \"Cancelamento\";\n    nivel2 = \"Cancelamento a pedido do cliente\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/apolice|ap\u00c3\u00b3lice|documento|certificado|carta/)) {\n    nivel1 = \"Documentos\";\n    nivel2 = \"Segunda via de ap\u00c3\u00b3lice\";\n} else if (perguntaLower.match(/mudei|endere\u00c3\u00a7o|troquei|dados|alterar/)) {\n    nivel1 = \"Altera\u00c3\u00a7\u00c3\u00b5es de Ap\u00c3\u00b3lice (Endossos)\";\n    nivel2 = \"Atualiza\u00c3\u00a7\u00c3\u00a3o de dados cadastrais\";\n}\n\n// ==========================================\n// 3. RETORNO FORMATADO PARA O POSTGRES\n// ==========================================\nreturn {\n    json: {\n        telefone: (contexto.telefone || \"\").replace(/\\D/g, ''),\n        nome_whatsapp: (contexto.nome || \"Cliente\"),\n        mensagem_inicial: pergunta,\n        \n        // Padroniza\u00c3\u00a7\u00c3\u00a3o solicitada\n        tipo_solicitacao: nivel1,          // N\u00c3\u00advel 1\n        subtipo_solicitacao: nivel2,       // N\u00c3\u00advel 2\n        tipo_seguro: ramoSeguro,           // Ramo\n        prioridade: prioridade,            // Prioridade\n        tipo_cliente: contexto.cadastrado ? \"Cliente existente\" : \"N\u00c3\u00a3o cliente\",\n        \n        status_atendimento: \"PENDENTE\",\n        origem: \"WHATSAPP\",\n        data_contato: new Date()\n    }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3104,
        384
      ],
      "id": "fb4f8474-f7ae-4217-b471-dc4f8967b85f",
      "name": "Preparar_Registro_Cliente"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT \n    id_atendimento,\n    telefone_whatsapp,\n    nome_cliente,\n    resumo_conversa,\n    assunto_principal,\n    status_atendimento,\n    qtde_mensagens,\n    data_atendimento\nFROM public.brokeria_registros_brokeria\nWHERE telefone_whatsapp = '{{ $json.telefone }}'\n  AND data_atendimento > NOW() - INTERVAL '24 hours'\nORDER BY data_atendimento DESC\nLIMIT 1;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        3312,
        384
      ],
      "id": "784420cc-6f1d-4b30-a75e-b9406b8a3921",
      "name": "Verificar_Registro_Existente",
      "alwaysOutputData": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.id_atendimento ? String($json.id_atendimento) : '' }}",
                    "rightValue": "",
                    "operator": {
                      "type": "string",
                      "operation": "empty",
                      "singleValue": true
                    },
                    "id": "f21a439a-8d76-455e-8135-20ce8961a9cd"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "32739ffd-b920-42b7-91e3-cc77369defd7",
                    "leftValue": "={{ $json.id_atendimento ? String($json.id_atendimento) : '' }}",
                    "rightValue": "",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty",
                      "singleValue": true
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        3520,
        384
      ],
      "id": "7ffab47d-1d20-484b-b510-5224a0374a7c",
      "name": "Switch_Registro_Existe"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO public.brokeria_registros_brokeria (\n    telefone_whatsapp,\n    nome_cliente,\n    resumo_conversa,    -- Ajustado para o padr\u00c3\u00a3o do Dashboard\n    assunto_principal,\n    canal,\n    status_atendimento,\n    qtde_mensagens,\n    recebeu_arquivos,\n    tipos_documentos,\n    etapa_funil,\n    data_atendimento,\n    hora_inicio\n) VALUES (\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.telefone }}',\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.nome_whatsapp }}',\n    -- Inicia o log j\u00c3\u00a1 formatado\n    E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.nome_whatsapp }}' || E': ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.mensagem_inicial.replace(/'/g, \"''\") }}' || E'\\n',\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.tipo_solicitacao }}',\n    'WHATSAPP',\n    'PENDENTE',\n    1,\n    {{ $(\"Preparar_Registro_Cliente\").first().json.recebeu_arquivos || false }},\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.tipos_documentos || \"\" }}',\n    'PRIMEIRO_CONTATO',\n    NOW(),\n    NOW()\n)\nRETURNING *;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        3728,
        192
      ],
      "id": "fc4264c9-7192-4ab9-b637-1983a330c3ee",
      "name": "Inserir_Novo_Registro",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE public.brokeria_registros_brokeria\nSET \n    -- Adiciona a nova mensagem do cliente mantendo o formato [HH:MM]\n    resumo_conversa = resumo_conversa || \n        E'\\n' ||\n        E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.nome_whatsapp }}' || E': ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.mensagem_inicial.replace(/'/g, \"''\") }}' || E'\\n',\n    assunto_principal = '{{ $(\"Preparar_Registro_Cliente\").first().json.tipo_solicitacao }}',\n    qtde_mensagens = COALESCE(qtde_mensagens, 0) + 1,\n    data_ultima_atualizacao = NOW()\nWHERE id_atendimento = {{ $json.id_atendimento }}\nRETURNING *;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        3744,
        400
      ],
      "id": "82b55d26-3a55-4df4-af0e-c8d59a93ed8b",
      "name": "Atualizar_Registro_Existente",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "numberInputs": 3
      },
      "alwaysOutputData": true,
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        4000,
        512
      ],
      "id": "e5d65d84-74fb-4b4b-8f7b-a2ac62fe4d0e",
      "name": "Merge_Registro"
    },
    {
      "parameters": {
        "description": "Use esta ferramenta OBRIGATORIAMENTE quando o cliente solicitar uma cota\u00c3\u00a7\u00c3\u00a3o de seguro E fornecer nome e-mail e tipo de seguro. Esta tool registra a solicita\u00c3\u00a7\u00c3\u00a3o no sistema para que o corretor Washington entre em contato. IMPORTANTE: S\u00c3\u00b3 chame esta tool APOS coletar nome e-mail e tipo de seguro do cliente.",
        "workflowId": {
          "__rl": true,
          "value": "jzIUf4Qlnf2bunJx599mp",
          "mode": "list",
          "cachedResultUrl": "/workflow/jzIUf4Qlnf2bunJx599mp",
          "cachedResultName": "EspecialistaRegistroCotacao"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "telefone": "={{ $('NormalizarEntrada').first().json.contexto.telefone }}",
            "nome": "={{ $json.nome || $('NormalizarEntrada').first().json.contexto.nome }}",
            "email": "={{ $json.email }}",
            "tipo_seguro": "={{ $json.tipo_seguro }}",
            "mensagem": "={{ $('NormalizarEntrada').first().json.pergunta_cliente || $json.mensagem || 'Solicita\u00c3\u00a7\u00c3\u00a3o de cota\u00c3\u00a7\u00c3\u00a3o via WhatsApp' }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "telefone",
              "displayName": "telefone",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "nome",
              "displayName": "nome",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "email",
              "displayName": "email",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "tipo_seguro",
              "displayName": "tipo_seguro",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "mensagem",
              "displayName": "mensagem",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        1808,
        1504
      ],
      "id": "73212f12-7944-4d82-a573-c9114a1598b5",
      "name": "EspecialistaRegistroCotacao"
    },
    {
      "parameters": {
        "jsCode": "// RECUPERA DADOS (Tenta buscar de v\u00c3\u00a1rias fontes comuns no seu fluxo)\nconst contexto = $json.contexto || {};\nconst inputUser = contexto.input_user || $json.pergunta_cliente || \"\";\nconst perguntaLower = inputUser.toLowerCase();\n\n// ==========================================\n// 1. RAMO DO SEGURO (Mapeamento Inteligente)\n// ==========================================\n// Para clientes existentes, se j\u00c3\u00a1 tivermos o ramo no contexto, usamos ele.\nlet ramoSeguro = contexto.ramo_seguro || \"OUTROS\";\n\nif (ramoSeguro === \"OUTROS\") {\n    if (perguntaLower.match(/auto|carro|veic|moto|placa/)) ramoSeguro = \"AUTOMOVEL\";\n    else if (perguntaLower.match(/casa|resid|apart|lar|home/)) ramoSeguro = \"RESIDENCIAL\";\n    else if (perguntaLower.match(/vida|falec|morte|funeral/)) ramoSeguro = \"VIDA\";\n    else if (perguntaLower.match(/saude|m\u00c3\u00a9dic|plano|hospit/)) ramoSeguro = \"SAUDE\";\n    else if (perguntaLower.match(/empresa|pj|comercial/)) ramoSeguro = \"EMPRESARIAL\";\n}\n\n// ==========================================\n// 2. N\u00c3\u008dVEL 1 E N\u00c3\u008dVEL 2 (Classifica\u00c3\u00a7\u00c3\u00a3o de Chamado)\n// ==========================================\nlet nivel1 = \"Informa\u00c3\u00a7\u00c3\u00b5es Gerais\";\nlet nivel2 = \"D\u00c3\u00bavidas gerais sobre seguros\";\nlet prioridade = \"M\u00c3\u00a9dia\";\n\n// L\u00c3\u00b3gica para Clientes Existentes (Foco em P\u00c3\u00b3s-Venda/Servi\u00c3\u00a7o)\nif (perguntaLower.match(/sinistro|bati|acidente|roubo|furto|colis\u00c3\u00a3o/)) {\n    nivel1 = \"Sinistros\";\n    nivel2 = \"Aviso de sinistro\";\n    prioridade = \"Cr\u00c3\u00adtica\";\n} else if (perguntaLower.match(/boleto|pagar|parcela|paguei|segunda via|2 via/)) {\n    nivel1 = \"Financeiro\";\n    nivel2 = \"Segunda via de boleto\";\n} else if (perguntaLower.match(/renovar|renova\u00c3\u00a7\u00c3\u00a3o|vencimento|venceu/)) {\n    nivel1 = \"Renova\u00c3\u00a7\u00c3\u00a3o\";\n    nivel2 = \"Revis\u00c3\u00a3o de valor\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/apolice|ap\u00c3\u00b3lice|documento|certificado|carta/)) {\n    nivel1 = \"Documentos\";\n    nivel2 = \"Segunda via de ap\u00c3\u00b3lice\";\n} else if (perguntaLower.match(/mudei|endere\u00c3\u00a7o|troquei|dados|alterar/)) {\n    nivel1 = \"Altera\u00c3\u00a7\u00c3\u00b5es de Ap\u00c3\u00b3lice (Endossos)\";\n    nivel2 = \"Atualiza\u00c3\u00a7\u00c3\u00a3o de dados cadastrais\";\n} else if (perguntaLower.match(/cancelar|cancelamento|desistir/)) {\n    nivel1 = \"Cancelamento\";\n    nivel2 = \"Cancelamento a pedido do cliente\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/reclama\u00c3\u00a7\u00c3\u00a3o|ruim|errado|elogio|queixa/)) {\n    nivel1 = \"P\u00c3\u00b3s-venda e Relacionamento\";\n    nivel2 = \"Reclama\u00c3\u00a7\u00c3\u00a3o geral\";\n} else if (perguntaLower.match(/cota\u00c3\u00a7\u00c3\u00a3o|cotacao|seguro novo|outro carro/)) {\n    nivel1 = \"Vendas e Cota\u00c3\u00a7\u00c3\u00b5es\";\n    nivel2 = \"Cota\u00c3\u00a7\u00c3\u00a3o de seguro novo\";\n    prioridade = \"Alta\";\n}\n\n// ==========================================\n// 3. RETORNO PARA O REGISTRO (Com \"Spread\" para manter dados da IA)\n// ==========================================\nreturn [{\n    json: {\n        ...$json, // Mant\u00e9m a resposta da IA\n        tipo_solicitacao: nivel1,\n        subtipo_solicitacao: nivel2,\n        tipo_seguro: ramoSeguro,\n        prioridade: prioridade,\n        tipo_cliente: \"Cliente existente\",\n        telefone: (contexto.telefone || \"\").replace(/\\D/g, ''),\n        nome_whatsapp: (contexto.nome || \"Cliente\")\n    }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2256,
        896
      ],
      "id": "73982131-0f06-4194-b0cf-ee063e24e5e0",
      "name": "Preparar_Registro_Cliente_Existente"
    },
    {
      "parameters": {
        "jsCode": "// Captura o input do n\u00c3\u00b3 anterior\nconst input = $input.first().json;\n\n// Se o webhook agora envia apenas o body, o 'input' j\u00c3\u00a1 \u00c3\u00a9 o conte\u00c3\u00bado direto\nconst data = input;\n\nlet perguntaFinal = data.pergunta_cliente || data.pergunta || \"Ol\u00c3\u00a1\";\nlet contextoFinal = data.contexto || {};\n\n// Identifica\u00c3\u00a7\u00c3\u00a3o robusta: Se tiver 'action' ou 'token' e n\u00c3\u00a3o tiver 'contexto' estruturado, tratamos como Portal Web Inicial\nconst isPortalWebInicial = (data.action || data.token) && (!data.contexto || Object.keys(data.contexto).length === 0);\n\nif (isPortalWebInicial) {\n    const rawIdentifier = data.cpf || data.identifier || data.cpf_cnpj || \"\";\n    const cpfLimpo = rawIdentifier.toString().replace(/\\D/g, '');\n\n    contextoFinal = {\n        nome: data.client_name || data.nome || \"Visitante Web\",\n        email_cadastrado: data.target || data.email || null,\n        cpf_real: cpfLimpo || null, \n        origem: \"PORTAL_WEB\",\n        token_portal: data.token || null, \n        action: data.action || null,\n        tipo_cliente: \"CADASTRADO\",\n        token_validado: \"N\u00c3\u0192O\"\n    };\n\n    if (data.action === \"SEND_2FA_TOKEN\") {\n        if (!contextoFinal.cpf_real) {\n            perguntaFinal = `[PROTOCOLO DE SEGURAN\u00c3\u2021A]: O cliente ${contextoFinal.nome} deseja receber seu c\u00c3\u00b3digo no e-mail ${contextoFinal.email_cadastrado}.\\n\\n### ATEN\u00c3\u2021\u00c3\u0192O AGENTE ###\\nO CPF n\u00c3\u00a3o foi enviado pelo portal. Voc\u00c3\u00aa \u00c3\u00a9 OBRIGADO a seguir estes passos:\\n1. Use a tool 'Validador_Cliente_Brokeria' passando o e-mail '${contextoFinal.email_cadastrado}' no campo 'documento'.\\n2. Identifique o CPF retornado pelo banco.\\n3. Agora sim, chame 'AgentEnviaToken' informando o E-mail, o CPF localizado e o Token: ${contextoFinal.token_portal}.`;\n        } else {\n            perguntaFinal = `[PROTOCOLO DE SEGURAN\u00c3\u2021A]: O cliente ${contextoFinal.nome} deseja receber seu c\u00c3\u00b3digo de acesso.\\n- E-mail: ${contextoFinal.email_cadastrado}\\n- CPF: ${contextoFinal.cpf_real}\\n- C\u00c3\u00b3digo (Token): ${contextoFinal.token_portal}\\n\\nChame a ferramenta AgentEnviaToken IMEDIATAMENTE.`;\n        }\n    } else {\n        contextoFinal.token_validado = \"SIM\";\n    }\n} else {\n    // Fluxo normal (WhatsApp ou Contexto j\u00c3\u00a1 pronto)\n    contextoFinal.token_validado = contextoFinal.token_validado || \"N\u00c3\u0192O\";\n}\n\nlet telefoneDb = contextoFinal.telefone || data.telefone || \"VISITANTE_WEB\";\nif (contextoFinal.cpf_real) {\n    telefoneDb = \"WEB_\" + contextoFinal.cpf_real;\n}\n\ncontextoFinal.tipo_cliente = contextoFinal.tipo_cliente || \"CADASTRADO\";\n// CERTO (Ajustado)\n// Se n\u00c3\u00a3o for Portal Web Inicial, e n\u00c3\u00a3o tiver origem, assume WHATSAPP\ncontextoFinal.origem = contextoFinal.origem || \"WHATSAPP\"; \nreturn [{\n    json: {\n        pergunta_cliente: perguntaFinal,\n        contexto: contextoFinal,\n        telefone: telefoneDb,\n        nome_whatsapp: contextoFinal.nome || \"Visitante Web\",\n        origem: contextoFinal.origem // Preserve o valor definido acima\n    }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2800,
        544
      ],
      "id": "4ddfc72d-7d06-4ffe-9099-28b7d355afb1",
      "name": "NormalizarEntrada"
    },
    {
      "parameters": {
        "jsCode": "const inputData = $input.first().json;\nlet contexto = inputData.contexto || {};\nlet perguntaCliente = \"\";\n\ntry {\n    const nodeContexto = $(\"DefinirContextoAI\").first().json;\n    contexto = nodeContexto.contexto || {};\n    perguntaCliente = nodeContexto.pergunta_cliente || \"\";\n} catch(e) {\n    perguntaCliente = inputData.pergunta_cliente || inputData.pergunta || \"\";\n}\n\nlet dadosRegistro = {};\ntry {\n    const mergeNode = $(\"Merge_Registro\").first().json;\n    dadosRegistro = mergeNode || {};\n} catch(e) {}\n\nif (!perguntaCliente && dadosRegistro.resumo_conversa) {\n    const mensagens = dadosRegistro.resumo_conversa.split('---');\n    perguntaCliente = mensagens[mensagens.length - 1].trim();\n}\n\nreturn [{\n    json: {\n        pergunta_cliente: perguntaCliente || \"\",\n        contexto: contexto,\n        id_atendimento: dadosRegistro.id_atendimento || null,\n        origem_tecnica: contexto.origem || \"WHATSAPP\"\n    }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1248,
        832
      ],
      "id": "4d0a31e9-4bcb-40e1-9b1d-4dccefc36228",
      "name": "Preparar_Input_Agent"
    },
    {
      "parameters": {
        "operation": "delete",
        "key": "==buffer:{{ $('CheckOrigem').first().json.wa.chatId }}"
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        832,
        576
      ],
      "id": "71d1203e-ad6e-42ec-8bfd-2dd78cecc961",
      "name": "Limpar_Buffer_Pos_Execucao",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "portal-web-chat",
        "responseMode": "lastNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -656,
        112
      ],
      "id": "69b6368a-2a00-4a46-8c8f-1a23d6b50642",
      "name": "WebhookPortal"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{ $('CheckOrigem').first().json.wa.provider === 'portal' ? 'PORTAL' : 'WHATSAPP' }}",
              "rightValue": "PORTAL",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1936,
        976
      ],
      "id": "ede710ac-d3d8-44df-a610-8b5edd76826a",
      "name": "IF_Portal_Origem"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.wa.provider }}",
                    "rightValue": "waha",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "provider-waha"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "provider-portal",
                    "leftValue": "={{ $json.wa.provider }}",
                    "rightValue": "portal",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        -16,
        -96
      ],
      "id": "4f4c2ac5-7897-4a56-8923-842c07f666eb",
      "name": "Switch"
    },
    {
      "parameters": {
        "jsCode": "const input = $input.first().json;\n\n// 1. Limpeza de Newlines (Previne o erro do n8n UI)\nconst data = {};\nfor (const key in input) {\n    if (typeof input[key] === 'string') {\n        data[key] = input[key].trim();\n    } else {\n        data[key] = input[key];\n    }\n}\n\n// 2. Detecta Origem (WhatsApp vs Portal)\n// Usamos marcadores que o n\u00f3 'Dados' gerou e que s\u00e3o exclusivos do Portal.\nconst isPortal = (data.source === 'PORTAL_WEB') || (data.event && data.event.includes('dashboard')) || !!data.identifier;\nconst isWhatsApp = !isPortal;\n\nif (isWhatsApp) {\n    const messageText = data.body || \"\";\n    const senderName = data.name || \"\"; // Removido \"Cliente WhatsApp\"\n    const chatId = data.from || \"\";\n\n    return [{\n        json: {\n            wa: {\n                provider: \"waha\",\n                session: data.session || \"default\",\n                messageId: data.payload_id || \"wa_\" + Date.now(),\n                chatId: chatId,\n                name: senderName,\n                authenticated: false,\n                text: messageText\n            },\n            pergunta_cliente: messageText,\n            ...data\n        }\n    }];\n}\n\n// 3. Trata como Portal\nconst portalText = data.body || data.message || data.pergunta_cliente || data.user_text || \"\";\nconst portalName = data.client_name || data.nome || data.name || \"\"; // Removido \"Cliente Portal\"\nconst portalId = (data.identifier || data.cpf || \"portal_user\").toString().trim();\n\nreturn [{\n    json: {\n        wa: {\n            provider: \"portal\",\n            session: (data.session_id || portalId + \"_v2\").trim(),\n            messageId: (\"web_\" + Date.now()).trim(),\n            chatId: (data.chat_id || portalId).trim(),\n            name: portalName.trim(),\n            authenticated: data.token_validado === 'SIM' || !!data.authenticated,\n            token_validado: data.token_validado || (data.authenticated ? 'SIM' : 'NAO'),\n            text: portalText.trim()\n        },\n        pergunta_cliente: portalText.trim(),\n        ...data\n    }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -208,
        -96
      ],
      "id": "1b706021-dfe4-4e12-b5c3-34c4f7387e58",
      "name": "NormalizeInbound"
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {
          "includeUnpaired": true
        }
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        880,
        48
      ],
      "id": "f1a016a4-a242-4021-9e26-2f13c550dc1a",
      "name": "Merge"
    },
    {
      "parameters": {
        "jsCode": "let redisData = {};\ntry {\n    const redisRaw = $json.Redis_Check_Final || \"{}\";\n    redisData = typeof redisRaw === 'string' ? JSON.parse(redisRaw) : redisRaw;\n} catch(e) { redisData = {}; }\n\nconst ultimaExecId = String(redisData.minha_execucao || \"\").trim();\nconst idExecAtual = String($execution.id).trim();\nconst wa = $json.wa || {}; // <-- LINHA ADICIONADA\n\nif (!ultimaExecId || idExecAtual === ultimaExecId) {\n    return [{\n        json: {\n            ...$json, \n            ...redisData, \n            pergunta_cliente: redisData.texto_combinado || wa.text || $json.pergunta_cliente || \"\"\n        }\n    }];\n} else {\n    return []; // Para execu\u00e7\u00f5es duplicadas\n}\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        656,
        496
      ],
      "id": "3d7c0f05-99ca-4347-8fbb-32c1a035fefd",
      "name": "Filtro_Ultima_Execucao"
    },
    {
      "parameters": {
        "jsCode": "const dadosBanco = $input.first().json;\nconst metadados = $('NormalizeInbound').first().json;\n\n// Garante que o objeto 'wa' seja mergeado corretamente para N\u00c3O PERDER o 'name'\nconst waMerged = {\n    ...(metadados.wa || {}),\n    ...(dadosBanco.wa || {})\n};\n\n// Se o banco n\u00e3o retornou nome (ex: cliente novo), mantemos o nome do WhatsApp no wa.name\nif (metadados.wa && metadados.wa.name && (!waMerged.name)) {\n    waMerged.name = metadados.wa.name;\n}\n\nreturn [{\n    json: {\n        ...metadados,\n        ...dadosBanco,\n        wa: waMerged, // <-- Aqui unimos os metadados do zap com os dados do banco\n        cliente_encontrado: !!dadosBanco.id_cliente\n    }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1296,
        48
      ],
      "id": "932afc25-d564-4370-8b8a-0f9eb2d651d2",
      "name": "Consolidar_Identidade"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT \n  c.*, \n  CASE \n    WHEN ($1 ~ '^[0-9 .-]+$') AND (REPLACE(REPLACE(REPLACE($1, '.', ''), '-', ''), ' ', ''))::BIGINT = c.responsavel_celular::BIGINT THEN c.responsavel_nome\n    WHEN ($1 ~ '^[0-9 .-]+$') AND (REPLACE(REPLACE(REPLACE($1, '.', ''), '-', ''), ' ', ''))::BIGINT = c.condutor_celular::BIGINT THEN c.condutor_nome\n    ELSE c.nome_completo \n  END as nome_identificado,\n  (\n    SELECT json_agg(json_build_object(\n      'seguradora', a.seguradora,\n      'ramo', a.ramo,\n      'numero_apolice', a.numero_apolice,\n      'vigencia_inicio', a.vigencia_inicio,\n      'vigencia_fim', a.vigencia_fim,\n      'status_apolice', a.status_apolice,\n      'link_url_apolice', a.link_url_apolice,\n      'placa', a.placa,\n      'telefone_capital', COALESCE(NULLIF(a.telefone_capital, ''), s.telefone_capital),\n      'telefone_0800', COALESCE(NULLIF(a.telefone_0800, ''), s.telefone_0800),\n      'site_url', COALESCE(NULLIF(a.site_url, ''), s.site_url)\n    ))\n    FROM public.apolices_brokeria a\n    LEFT JOIN public.seguradoras s ON s.nome = a.seguradora\n    WHERE a.id_cliente::text = c.id_cliente::text\n  ) as apolices_detalhadas\nFROM public.clientes_brokeria c\nWHERE ($1 ~ '^[0-9 .-]+$') AND (REPLACE(REPLACE(REPLACE($1, '.', ''), '-', ''), ' ', ''))::BIGINT IN (\n      c.celular::BIGINT, c.telefone::BIGINT, c.cpf::BIGINT,\n      c.responsavel_celular::BIGINT, c.responsavel_cpf::BIGINT,\n      c.condutor_celular::BIGINT, c.condutor_cpf::BIGINT\n    )\nLIMIT 1;\n\n",
        "options": {
          "queryReplacement": "={{ $json.body?.cpf || $json.body?.telefone || $json.PhoneNumber || $json.wa?.chatId }}"
        }
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1088,
        48
      ],
      "id": "fabeab10-3a25-4cf8-8497-fd2b00ab0d9f",
      "name": "Busca_Cliente",
      "alwaysOutputData": true,
      "executeOnce": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const aiOutput = $json.output || $json.text || \"\";\nconst context = ($('DefinirContextoAI').first().json.contexto) || {};\n\nreturn [{\n    json: {\n        response: aiOutput,\n        client_name: (context.nome || \"\").trim()\n    }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2256,
        1072
      ],
      "id": "52c5a8a4-e8fa-4f77-a080-81c41f8176d6",
      "name": "FormatarRespostaPortal"
    },
    {
      "parameters": {
        "jsCode": "let cliente = {};\ntry { \n    const busca = $(\"Busca_Cliente\").first();\n    if (busca && busca.json && busca.json.id_cliente) { cliente = busca.json; }\n} catch(e) {}\n\nconst wa = $json.wa || {};\nconst chatId = wa.chatId || \"\";\nconst phoneNumber = (chatId.replace(\"@c.us\", \"\") || $json.PhoneNumber || $json.telefone || \"\").toString();\n\nlet consolidado = {};\ntry { consolidado = $(\"ConsolidarMensagem\").first().json || {}; } catch(e) {}\n\nlet perguntaAgente = consolidado.mensagem_final || wa.text || $json.pergunta_cliente || \"\";\n\n// VERIFICA\u00c7\u00c3O DE SEGURAN\u00c7A\nlet isValid = false;\ntry {\n    const nodeRedis = $(\"Buscar_Sessao_Existente\").first();\n    if (nodeRedis && nodeRedis.json && nodeRedis.json.sessaoExistente === \"VALIDADO\") { isValid = true; }\n    \n    // Verifica autentica\u00e7\u00e3o vinda do Portal ou WhatsApp\n    if (wa.authenticated === true || $json.authenticated === true || $json.token_validado === \"SIM\") { \n        isValid = true; \n    }\n} catch (e) { isValid = false; }\n\n// INSTRU\u00c7\u00c3O DIN\u00c2MICA DE ACESSO\nconst isPortal = wa.provider === 'portal' || $json.origem === 'PORTAL_WEB';\nlet instrucaoAcesso = \"\";\nif (isPortal && isValid) {\n    instrucaoAcesso = \"Como voc\u00ea j\u00e1 est\u00e1 logado, voc\u00ea pode acessar todos os detalhes de suas ap\u00f3lices e baixar documentos diretamente no menu lateral esquerdo do portal! \ud83d\ude0a\";\n} else {\n    instrucaoAcesso = \"Para acessar seus dados e documentos com seguran\u00e7a, acesse nosso portal:\\n\ud83d\udd17 https://brokeria-api-brokeriaweb.cx0m9g.easypanel.host/login.html\\n\\nL\u00e1 voc\u00ea encontra todas as suas informa\u00e7\u00f5es e pode baixar seus documentos! \ud83d\ude0a\";\n}\n\n// =========================================================\n// MASCARAMENTO RADICAL (Prote\u00e7\u00e3o de Dados Pessoais)\n// =========================================================\nlet apolicesAtivas = (cliente.apolices_detalhadas || []).filter(ap => \n    ap && ap.status_apolice && String(ap.status_apolice).toUpperCase() === 'ATIVA'\n);\n\nconst apolicesSeguras = apolicesAtivas.map(ap => ({\n    seguradora: ap.seguradora,\n    ramo: ap.ramo,\n    status: ap.status_apolice,\n    numero_apolice: isValid ? ap.numero_apolice : \"(Bloqueado)\",\n    vencimento: isValid ? ap.vigencia_fim : \"(Bloqueado)\",\n    placa: (ap.placa && isValid) ? ap.placa : (ap.placa ? \"***-****\" : \"N/A\"),\n    link_download: isValid ? (ap.link_url_apolice || \"Nao disponivel\") : \"(Oculto)\",\n    telefone_0800: ap.telefone_0800 || \"Nao informado\",\n    telefone_capital: ap.telefone_capital || \"Nao informado\",\n    site_seguradora: ap.site_url || \"Nao informado\"\n}));\n\nreturn [{\n    json: {\n        pergunta_cliente: perguntaAgente,\n        contexto: {\n            // AQUI EST\u00c1 A MUDAN\u00c7A: Prioridade Total na Identifica\u00e7\u00e3o\n            nome: (cliente.nome_identificado || cliente.nome_completo || wa.name || $json.client_name || \"\").trim(),\n            \n            cpf_real: (cliente.cpf || $json.cpf || \"\").toString().replace(/\\D/g, ''), \n            cpf_exibicao: (cliente.cpf || $json.cpf) ? `***.***.***-${(cliente.cpf || $json.cpf).toString().slice(-2)}` : \"Nao informado\",\n            telefone: (cliente.celular || phoneNumber || $json.telefone || \"\").toString(),\n            email_cadastrado: (cliente.email || $json.email || \"\").toString(),\n            \n            token_validado: isValid ? \"SIM\" : \"NAO\",\n            instrucao_acesso: instrucaoAcesso,\n            cadastrado: !!cliente.id_cliente,\n            id_cliente: cliente.id_cliente || null,\n            resumo_apolices: apolicesSeguras,\n            tipo_cliente: cliente.id_cliente ? \"CADASTRADO\" : \"NOVO\",\n            origem: wa.provider || $json.origem || \"WHATSAPP\"\n        }\n    }\n}];\n\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2736,
        672
      ],
      "id": "00cb2c17-3d63-473e-9fdd-d58e4ced1f40",
      "name": "DefinirContextoAI1",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "jsCode": "let cliente = {};\ntry { \n    const busca = $(\"Busca_Cliente\").first();\n    if (busca && busca.json && busca.json.id_cliente) { cliente = busca.json; }\n} catch(e) {}\n\nconst wa = $json.wa || {};\nconst chatId = wa.chatId || \"\";\nconst phoneNumber = (chatId.replace(\"@c.us\", \"\") || $json.PhoneNumber || $json.telefone || \"\").toString();\n\nlet consolidado = {};\ntry { consolidado = $(\"ConsolidarMensagem\").first().json || {}; } catch(e) {}\n\nlet perguntaAgente = consolidado.mensagem_final || wa.text || $json.pergunta_cliente || \"\";\n\n// VERIFICA\u00c7\u00c3O DE SEGURAN\u00c7A\nlet isValid = false;\ntry {\n    const nodeRedis = $(\"Buscar_Sessao_Existente\").first();\n    if (nodeRedis && nodeRedis.json && nodeRedis.json.sessaoExistente === \"VALIDADO\") { isValid = true; }\n    \n    // Verifica autentica\u00e7\u00e3o vinda do Portal ou WhatsApp\n    if (wa.authenticated === true || $json.authenticated === true || $json.token_validado === \"SIM\") { \n        isValid = true; \n    }\n} catch (e) { isValid = false; }\n\n// INSTRU\u00c7\u00c3O DIN\u00c2MICA DE ACESSO\nconst isPortal = wa.provider === 'portal' || $json.origem === 'PORTAL_WEB';\nlet instrucaoAcesso = \"\";\nif (isPortal && isValid) {\n    instrucaoAcesso = \"Como voc\u00ea j\u00e1 est\u00e1 logado, voc\u00ea pode acessar todos os detalhes de suas ap\u00f3lices e baixar documentos diretamente no menu lateral esquerdo do portal! \ud83d\ude0a\";\n} else {\n    instrucaoAcesso = \"Para acessar seus dados e documentos com seguran\u00e7a, acesse nosso portal:\\n\ud83d\udd17 https://brokeria-api-brokeriaweb.cx0m9g.easypanel.host/login.html\\n\\nL\u00e1 voc\u00ea encontra todas as suas informa\u00e7\u00f5es e pode baixar seus documentos! \ud83d\ude0a\";\n}\n\n// =========================================================\n// MASCARAMENTO RADICAL (Prote\u00e7\u00e3o de Dados Pessoais)\n// =========================================================\nlet apolicesAtivas = (cliente.apolices_detalhadas || []).filter(ap => \n    ap && ap.status_apolice && String(ap.status_apolice).toUpperCase() === 'ATIVA'\n);\n\nconst apolicesSeguras = apolicesAtivas.map(ap => ({\n    seguradora: ap.seguradora,\n    ramo: ap.ramo,\n    status: ap.status_apolice,\n    numero_apolice: isValid ? ap.numero_apolice : \"(Bloqueado)\",\n    vencimento: isValid ? ap.vigencia_fim : \"(Bloqueado)\",\n    placa: (ap.placa && isValid) ? ap.placa : (ap.placa ? \"***-****\" : \"N/A\"),\n    link_download: isValid ? (ap.link_url_apolice || \"Nao disponivel\") : \"(Oculto)\",\n    telefone_0800: ap.telefone_0800 || \"Nao informado\",\n    telefone_capital: ap.telefone_capital || \"Nao informado\",\n    site_seguradora: ap.site_url || \"Nao informado\"\n}));\n\nreturn [{\n    json: {\n        pergunta_cliente: perguntaAgente,\n        contexto: {\n            // AQUI EST\u00c1 A MUDAN\u00c7A: Prioridade Total na Identifica\u00e7\u00e3o\n            nome: (cliente.nome_identificado || cliente.nome_completo || wa.name || $json.client_name || \"\").trim(),\n            \n            cpf_real: (cliente.cpf || $json.cpf || \"\").toString().replace(/\\D/g, ''), \n            cpf_exibicao: (cliente.cpf || $json.cpf) ? `***.***.***-${(cliente.cpf || $json.cpf).toString().slice(-2)}` : \"Nao informado\",\n            telefone: (cliente.celular || phoneNumber || $json.telefone || \"\").toString(),\n            email_cadastrado: (cliente.email || $json.email || \"\").toString(),\n            \n            token_validado: isValid ? \"SIM\" : \"NAO\",\n            instrucao_acesso: instrucaoAcesso,\n            cadastrado: !!cliente.id_cliente,\n            id_cliente: cliente.id_cliente || null,\n            resumo_apolices: apolicesSeguras,\n            tipo_cliente: cliente.id_cliente ? \"CADASTRADO\" : \"NOVO\",\n            origem: wa.provider || $json.origem || \"WHATSAPP\"\n        }\n    }\n}];\n\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2560,
        96
      ],
      "id": "96366d16-23cb-4822-b5e8-194b8647fc07",
      "name": "DefinirContextoAI2",
      "alwaysOutputData": true
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Dados",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dados": {
      "main": [
        [
          {
            "node": "NormalizeInbound",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Seen": {
      "main": [
        [
          {
            "node": "Start Typing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Typing": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "FiltrarResposta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Consultar WAHA Direto": {
      "main": [
        [
          {
            "node": "Limpar Telefone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limpar Telefone": {
      "main": [
        [
          {
            "node": "FinalizeChatId",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Agrupar_Texto": {
      "main": [
        [
          {
            "node": "Atualizar_Buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Atualizar_Buffer": {
      "main": [
        [
          {
            "node": "Espera_3_Segundos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Espera_3_Segundos": {
      "main": [
        [
          {
            "node": "Check_Pos_Espera",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check_Pos_Espera": {
      "main": [
        [
          {
            "node": "Filtro_Ultima_Execucao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recuperar_Buffer": {
      "main": [
        [
          {
            "node": "Agrupar_Texto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CheckOrigem": {
      "main": [
        [
          {
            "node": "Recuperar_Buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SwitchOrigem": {
      "main": [
        [
          {
            "node": "Buscar_Sessao_Existente",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar_Sessao_Existente",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar_Sessao_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar_Sessao_Existente": {
      "main": [
        [
          {
            "node": "SwitchMidia",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SwitchMidia": {
      "main": [
        [
          {
            "node": "DownloadMidia",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ImageDownload",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DownloadMidia": {
      "main": [
        [
          {
            "node": "IA_Processar_Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ImageDownload": {
      "main": [
        [
          {
            "node": "IA_Processar_Imagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DefinirContextoAI": {
      "main": [
        [
          {
            "node": "NormalizarEntrada",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IA_Processar_Audio": {
      "main": [
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IA_Processar_Imagem": {
      "main": [
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ConsolidarMensagem": {
      "main": [
        [
          {
            "node": "TratamentoErroMidia",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TratamentoErroMidia": {
      "main": [
        [],
        [
          {
            "node": "DefinirContextoAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "PostgresChatMemory": {
      "ai_memory": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "QueryPostgresClientes": {
      "ai_tool": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Padronizar Output": {
      "main": [
        [
          {
            "node": "Send Seen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FunilRespostas": {
      "main": [
        [
          {
            "node": "IF_Portal_Origem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FiltrarResposta": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BrokerIA_Master": {
      "main": [
        [
          {
            "node": "FunilRespostas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check_Cliente_Novo": {
      "main": [
        [
          {
            "node": "Preparar_Registro_Cliente",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge_Registro",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Preparar_Registro_Cliente": {
      "main": [
        [
          {
            "node": "Verificar_Registro_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar_Registro_Existente": {
      "main": [
        [
          {
            "node": "Switch_Registro_Existe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch_Registro_Existe": {
      "main": [
        [
          {
            "node": "Inserir_Novo_Registro",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Atualizar_Registro_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Inserir_Novo_Registro": {
      "main": [
        [
          {
            "node": "Merge_Registro",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Atualizar_Registro_Existente": {
      "main": [
        [
          {
            "node": "Merge_Registro",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge_Registro": {
      "main": [
        [
          {
            "node": "Preparar_Input_Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EspecialistaRegistroCotacao": {
      "ai_tool": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Preparar_Registro_Cliente_Existente": {
      "main": [
        [
          {
            "node": "Registrar_Interacao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NormalizarEntrada": {
      "main": [
        [
          {
            "node": "Check_Cliente_Novo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FinalizeChatId": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preparar_Input_Agent": {
      "main": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limpar_Buffer_Pos_Execucao": {
      "main": [
        [
          {
            "node": "SwitchOrigem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WebhookPortal": {
      "main": [
        [
          {
            "node": "Dados",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF_Portal_Origem": {
      "main": [
        [
          {
            "node": "FormatarRespostaPortal",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Preparar_Registro_Cliente_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch": {
      "main": [
        [
          {
            "node": "Consultar WAHA Direto",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "NormalizeInbound": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Busca_Cliente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filtro_Ultima_Execucao": {
      "main": [
        [
          {
            "node": "Limpar_Buffer_Pos_Execucao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Consolidar_Identidade": {
      "main": [
        [
          {
            "node": "CheckOrigem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Busca_Cliente": {
      "main": [
        [
          {
            "node": "Consolidar_Identidade",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Registrar_Interacao": {
      "main": [
        [
          {
            "node": "Padronizar Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "versionId": "1a93088d-5a2a-440d-85c0-595f686d66a6",
  "id": "bzXTwRM9kF2f8LO5",
  "tags": []
}