{
  "name": "MercadoChat - Fluxo Principal",
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message",
          "photo"
        ],
        "additionalFields": {}
      },
      "id": "telegram-trigger",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [
        250,
        400
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Extrai dados da mensagem do Telegram\nconst message = $input.first().json;\n\nconst telegramId = message?.message?.from?.id || message?.message?.chat?.id;\nconst username = message?.message?.from?.username || null;\nconst firstName = message?.message?.from?.first_name || 'usu\u00e1rio';\nconst messageText = message?.message?.text || '';\nconst hasPhoto = !!(message?.message?.photo);\nconst chatId = message?.message?.chat?.id;\nconst messageId = message?.message?.message_id;\n\n// Pega a maior foto dispon\u00edvel\nlet photoFileId = null;\nif (hasPhoto) {\n  const photos = message.message.photo;\n  photoFileId = photos[photos.length - 1].file_id;\n}\n\nreturn [{\n  json: {\n    telegramId,\n    username,\n    firstName,\n    messageText,\n    hasPhoto,\n    photoFileId,\n    chatId,\n    messageId\n  }\n}];"
      },
      "id": "extract-message",
      "name": "Extrair Dados da Mensagem",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        470,
        400
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://lhybdghiuafcsvytxhdp.supabase.co/rest/v1/users",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "<redacted-credential>"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "telegram_id",
              "value": "=eq.{{ $json.telegramId }}"
            },
            {
              "name": "select",
              "value": "*"
            }
          ]
        }
      },
      "id": "check-user",
      "name": "Verificar Usu\u00e1rio no Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        690,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "// Verifica o estado do usu\u00e1rio e define o pr\u00f3ximo passo\nconst msg = $('Extrair Dados da Mensagem').first().json;\nconst users = $input.first().json;\n\nconst userList = Array.isArray(users) ? users : [];\nconst user = userList.length > 0 ? userList[0] : null;\n\nlet routeTo = 'intent';\nlet context = {\n  isNewUser: !user,\n  isRegistered: user?.is_registered || false,\n  registrationStep: user?.registration_step || 'start',\n  userId: user?.id || null,\n  userPoints: user?.points || 0,\n  userName: user?.full_name || msg.firstName\n};\n\n// Verifica se est\u00e1 no fluxo de cadastro ou se \u00e9 novo usu\u00e1rio\nif (!user || !user.is_registered) {\n  routeTo = 'registration';\n} else if (msg.hasPhoto) {\n  routeTo = 'photo';\n} else {\n  routeTo = 'intent';\n}\n\nreturn [{ json: { ...msg, ...context, routeTo } }];"
      },
      "id": "check-registration",
      "name": "Verificar Estado do Usu\u00e1rio",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        910,
        400
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": false
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.routeTo }}",
                    "rightValue": "registration",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 0
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.routeTo }}",
                    "rightValue": "photo",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 1
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.routeTo }}",
                    "rightValue": "intent",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "outputIndex": 2
            }
          ]
        }
      },
      "id": "router-main",
      "name": "Roteador Principal",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        1130,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "// L\u00f3gica de cadastro por etapas\nconst data = $input.first().json;\nconst step = data.registrationStep || 'start';\nconst message = data.messageText?.trim() || '';\nconst telegramId = data.telegramId;\nconst chatId = data.chatId;\n\nlet response = '';\nlet nextStep = step;\nlet updateData = {};\nlet shouldUpdate = false;\n\nswitch (step) {\n  case 'start':\n    // Novo usu\u00e1rio - criar registro e pedir nome\n    response = `Ol\u00e1, ${data.firstName}! \ud83d\udc4b Bem-vindo ao *MercadoBot*! \ud83d\uded2\\n\\nVou precisar de alguns dados para criar sua conta.\\n\\n\ud83d\udcdd Qual \u00e9 o seu *nome completo*?`;\n    nextStep = 'waiting_name';\n    shouldUpdate = true;\n    updateData = { registration_step: 'waiting_name' };\n    break;\n    \n  case 'waiting_name':\n    if (message.length < 3) {\n      response = '\u274c Nome muito curto. Por favor, informe seu nome completo.';\n    } else {\n      response = `Obrigado, *${message}*! \ud83d\ude0a\\n\\n\ud83d\udd22 Agora informe seu *CPF* (apenas n\u00fameros):`;\n      nextStep = 'waiting_cpf';\n      shouldUpdate = true;\n      updateData = { full_name: message, registration_step: 'waiting_cpf' };\n    }\n    break;\n    \n  case 'waiting_cpf':\n    const cpfClean = message.replace(/\\D/g, '');\n    if (cpfClean.length !== 11) {\n      response = '\u274c CPF inv\u00e1lido. Por favor, informe os 11 d\u00edgitos do CPF.';\n    } else {\n      response = '\ud83d\udcc5 \u00d3timo! Agora informe sua *data de nascimento* no formato DD/MM/AAAA:';\n      nextStep = 'waiting_birthdate';\n      shouldUpdate = true;\n      updateData = { cpf: cpfClean, registration_step: 'waiting_birthdate' };\n    }\n    break;\n    \n  case 'waiting_birthdate':\n    const dateparts = message.split('/');\n    if (dateparts.length !== 3 || dateparts[2].length !== 4) {\n      response = '\u274c Formato inv\u00e1lido. Por favor use DD/MM/AAAA (ex: 15/03/1990):';\n    } else {\n      const birthDate = `${dateparts[2]}-${dateparts[1].padStart(2,'0')}-${dateparts[0].padStart(2,'0')}`;\n      response = `\u2705 *Cadastro conclu\u00eddo!*\\n\\nSeja bem-vindo ao MercadoBot! \ud83c\udf89\\n\\nAgora voc\u00ea pode:\\n\u2022 \ud83d\uded2 Consultar pre\u00e7os de produtos\\n\u2022 \ud83d\udcca Comparar pre\u00e7os entre mercados\\n\u2022 \ud83d\udcf8 Enviar fotos de notas fiscais para ganhar *pontos*\\n\u2022 \ud83c\udf81 Trocar pontos por cashback e sorteios!\\n\\nEnvie /ajuda para ver todos os comandos.`;\n      nextStep = 'completed';\n      shouldUpdate = true;\n      updateData = { birth_date: birthDate, registration_step: 'completed', is_registered: true };\n    }\n    break;\n    \n  default:\n    response = '\u26a0\ufe0f Ocorreu um erro no cadastro. Por favor, entre em contato com o suporte.';\n}\n\nreturn [{ json: { response, nextStep, updateData, shouldUpdate, telegramId, chatId, registrationStep: step, isNewUser: data.isNewUser } }];"
      },
      "id": "registration-logic",
      "name": "L\u00f3gica de Cadastro",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1350,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {},
          "conditions": [
            {
              "leftValue": "={{ $json.isNewUser }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ]
        }
      },
      "id": "is-new-user",
      "name": "\u00c9 Novo Usu\u00e1rio?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1570,
        200
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://lhybdghiuafcsvytxhdp.supabase.co/rest/v1/users",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "<redacted-credential>"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "telegram_id",
              "value": "={{ $('L\u00f3gica de Cadastro').first().json.telegramId }}"
            },
            {
              "name": "registration_step",
              "value": "waiting_name"
            }
          ]
        }
      },
      "id": "create-user",
      "name": "Criar Usu\u00e1rio no Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1790,
        100
      ]
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://lhybdghiuafcsvytxhdp.supabase.co/rest/v1/users?telegram_id=eq.{{ $('L\u00f3gica de Cadastro').first().json.telegramId }}",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "<redacted-credential>"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "=body",
              "value": "={{ JSON.stringify($('L\u00f3gica de Cadastro').first().json.updateData) }}"
            }
          ]
        }
      },
      "id": "update-user-registration",
      "name": "Atualizar Registro no Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1790,
        300
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $('L\u00f3gica de Cadastro').first().json.chatId }}",
        "text": "={{ $('L\u00f3gica de Cadastro').first().json.response }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "send-registration-response",
      "name": "Enviar Resposta de Cadastro",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2010,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=<redacted-credential>",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "=body",
              "value": "={{ JSON.stringify({ contents: [{ parts: [{ text: `Voc\u00ea \u00e9 um assistente de compras de supermercado. Analise a mensagem do usu\u00e1rio e retorne APENAS um JSON com a inten\u00e7\u00e3o identificada. Sem texto adicional, sem markdown.\\n\\nInten\u00e7\u00f5es: buy_item, price_history, find_item, nearby_markets, price_comparison, send_receipt, points_balance, points_redeem, help, greeting, unknown\\n\\nFormato:\\n{\\\"intent\\\": \\\"<intent>\\\", \\\"entities\\\": {\\\"product\\\": \\\"<produto ou null>\\\", \\\"market\\\": \\\"<mercado ou null>\\\", \\\"cep\\\": \\\"<cep ou null>\\\"}, \\\"confidence\\\": <0.0 a 1.0>}\\n\\nMensagem: ${$json.messageText}` }] }] }) }}"
            }
          ]
        }
      },
      "id": "gemini-intent",
      "name": "Gemini - Identificar Inten\u00e7\u00e3o",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1350,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "// Parse a resposta do Gemini\nconst geminiResponse = $input.first().json;\nconst msgData = $('Verificar Estado do Usu\u00e1rio').first().json;\n\nlet intentData = { intent: 'unknown', entities: {}, confidence: 0 };\n\ntry {\n  const rawText = geminiResponse?.candidates?.[0]?.content?.parts?.[0]?.text || '{}';\n  const cleanText = rawText.replace(/```json/g, '').replace(/```/g, '').trim();\n  intentData = JSON.parse(cleanText);\n} catch(e) {\n  intentData = { intent: 'unknown', entities: {}, confidence: 0 };\n}\n\nreturn [{ json: {\n  ...msgData,\n  intent: intentData.intent || 'unknown',\n  entities: intentData.entities || {},\n  confidence: intentData.confidence || 0\n}}];"
      },
      "id": "parse-intent",
      "name": "Parse Inten\u00e7\u00e3o do Gemini",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1570,
        400
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "outputIndex": 0,
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "price_history",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputIndex": 1,
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "find_item",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputIndex": 1,
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "buy_item",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputIndex": 2,
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "nearby_markets",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputIndex": 3,
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "price_comparison",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputIndex": 4,
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "points_balance",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            }
          ]
        },
        "fallbackOutput": 5
      },
      "id": "intent-switch",
      "name": "Switch de Inten\u00e7\u00f5es",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        1790,
        400
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://lhybdghiuafcsvytxhdp.supabase.co/rest/v1/purchase_items",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "<redacted-credential>"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "select",
              "value": "unit_price,total_price,quantity,created_at,products(name),purchases!inner(purchase_date,user_id,markets(name,city))"
            },
            {
              "name": "purchases.user_id",
              "value": "=eq.{{ $json.userId }}"
            },
            {
              "name": "products.name_normalized",
              "value": "=ilike.*{{ $json.entities?.product?.toLowerCase() || \"\" }}*"
            },
            {
              "name": "order",
              "value": "purchases.purchase_date.desc"
            },
            {
              "name": "limit",
              "value": "10"
            }
          ]
        }
      },
      "id": "query-price-history",
      "name": "Buscar Hist\u00f3rico de Pre\u00e7os",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2010,
        200
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://lhybdghiuafcsvytxhdp.supabase.co/rest/v1/price_records",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "<redacted-credential>"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "select",
              "value": "price,recorded_at,markets(name,city,address),products(name)"
            },
            {
              "name": "products.name_normalized",
              "value": "=ilike.*{{ $json.entities?.product?.toLowerCase() || \"\" }}*"
            },
            {
              "name": "markets.name_normalized",
              "value": "=ilike.*{{ $json.entities?.market?.toLowerCase() || \"\" }}*"
            },
            {
              "name": "order",
              "value": "price.asc,recorded_at.desc"
            },
            {
              "name": "limit",
              "value": "15"
            }
          ]
        }
      },
      "id": "query-find-item",
      "name": "Buscar Onde Encontrar Item",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2010,
        340
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://lhybdghiuafcsvytxhdp.supabase.co/rest/v1/markets",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "<redacted-credential>"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "select",
              "value": "*"
            },
            {
              "name": "cep",
              "value": "=ilike.{{ ($json.entities?.cep || \"\").replace(/\\D/g, \"\") }}*"
            },
            {
              "name": "limit",
              "value": "10"
            }
          ]
        }
      },
      "id": "query-nearby-markets",
      "name": "Buscar Mercados Pr\u00f3ximos",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2010,
        480
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://lhybdghiuafcsvytxhdp.supabase.co/rest/v1/price_records",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "=sb_publishable_omUBTYHoL5mxrpNe_AlNbQ_DS7FeBQt"
            },
            {
              "name": "Authorization",
              "value": "=<redacted-credential>"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "select",
              "value": "price,recorded_at,markets(name,city),products(name)"
            },
            {
              "name": "products.name_normalized",
              "value": "=ilike.*{{ $json.entities?.product?.toLowerCase() || \"\" }}*"
            },
            {
              "name": "order",
              "value": "price.asc,recorded_at.desc"
            },
            {
              "name": "limit",
              "value": "20"
            }
          ]
        }
      },
      "id": "query-price-comparison",
      "name": "Buscar Comparativo de Pre\u00e7os",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2010,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "// Monta resposta de saldo de pontos\nconst data = $('Parse Inten\u00e7\u00e3o do Gemini').first().json;\nconst points = data.userPoints || 0;\nconst pointsConfig = {\n  cashbackRate: 100,   // pontos por real\n  raffleTicket: 500    // pontos por cupom\n};\n\nconst cashbackValue = (points / pointsConfig.cashbackRate).toFixed(2);\nconst raffleTickets = Math.floor(points / pointsConfig.raffleTicket);\nconst pointsToNextTicket = pointsConfig.raffleTicket - (points % pointsConfig.raffleTicket);\n\nconst response = `\ud83c\udfaf *Seus Pontos MercadoBot*\\n\\n\ud83d\udcb0 Saldo atual: *${points} pontos*\\n\ud83d\udcb5 Equivale a: *R$ ${cashbackValue}* em cashback\\n\ud83c\udf9f\ufe0f Cupons de sorteio: *${raffleTickets}*\\n\\n\ud83d\udcc8 Faltam *${pointsToNextTicket} pontos* para o pr\u00f3ximo cupom!\\n\\n\ud83d\udcf8 Envie fotos de notas fiscais para acumular mais pontos!`;\n\nreturn [{ json: { response, chatId: data.chatId } }];"
      },
      "id": "points-balance-response",
      "name": "Resposta de Saldo de Pontos",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2010,
        720
      ]
    },
    {
      "parameters": {
        "jsCode": "// Resposta para inten\u00e7\u00f5es n\u00e3o reconhecidas ou ajuda\nconst data = $('Parse Inten\u00e7\u00e3o do Gemini').first().json;\nconst intent = data.intent;\nconst name = data.userName || 'usu\u00e1rio';\n\nlet response = '';\n\nif (intent === 'greeting') {\n  response = `Ol\u00e1, ${name}! \ud83d\udc4b\\n\\nSou o *MercadoBot*, seu assistente de compras! \ud83d\uded2\\n\\nPosso ajudar com:\\n\u2022 \ud83d\udcb0 Hist\u00f3rico de pre\u00e7os de produtos\\n\u2022 \ud83d\udd0d Onde encontrar itens\\n\u2022 \ud83d\udcca Comparar pre\u00e7os\\n\u2022 \ud83c\udfea Mercados pr\u00f3ximos\\n\u2022 \ud83d\udcf8 Notas fiscais (ganhe pontos!)\\n\u2022 \ud83c\udf81 Consultar seus pontos\\n\\nComo posso ajudar?`;\n} else if (intent === 'help') {\n  response = `\ud83d\udcd6 *O que posso fazer por voc\u00ea:*\\n\\n\u2022 _Quanto paguei no arroz?_\\n\u2022 _Onde tem leite mais barato?_\\n\u2022 _Mercados pr\u00f3ximos ao CEP 01310-100_\\n\u2022 _Comparar pre\u00e7o do azeite_\\n\u2022 _Meus pontos_\\n\u2022 \ud83d\udcf8 Envie uma foto de nota fiscal!`;\n} else {\n  response = `Hmm, n\u00e3o entendi muito bem. \ud83e\udd14\\n\\nTente perguntar de outra forma, por exemplo:\\n\u2022 _Quanto paguei no leite no Carrefour?_\\n\u2022 _Onde tem arroz?_\\n\u2022 _Meus pontos_\\n\\nOu envie /ajuda para ver todos os comandos.`;\n}\n\nreturn [{ json: { response, chatId: data.chatId } }];"
      },
      "id": "fallback-response",
      "name": "Resposta Padr\u00e3o / Ajuda",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2010,
        850
      ]
    },
    {
      "parameters": {
        "jsCode": "// Formata os dados do Supabase e gera resposta via Gemini\nconst intentData = $('Parse Inten\u00e7\u00e3o do Gemini').first().json;\nconst dbData = $input.first().json;\nconst intent = intentData.intent;\nconst entities = intentData.entities || {};\n\n// Prepara o texto para o Gemini gerar a resposta\nconst systemPrompt = `Voc\u00ea \u00e9 o MercadoBot, assistente de compras. Responda em portugu\u00eas de forma amig\u00e1vel e clara, m\u00e1ximo 500 caracteres. Use emojis com modera\u00e7\u00e3o.`;\n\nconst userPrompt = `Intent: ${intent}\\nProduto buscado: ${entities.product || 'n\u00e3o informado'}\\nMercado: ${entities.market || 'n\u00e3o informado'}\\nDados: ${JSON.stringify(dbData).substring(0, 2000)}\\n\\nGere uma resposta \u00fatil para o usu\u00e1rio baseada nesses dados.`;\n\nreturn [{ json: { systemPrompt, userPrompt, chatId: intentData.chatId, intent } }];"
      },
      "id": "prepare-gemini-response",
      "name": "Preparar Dados para Gemini",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2230,
        400
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=<redacted-credential>",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "=body",
              "value": "={{ JSON.stringify({ contents: [{ parts: [{ text: $json.systemPrompt + '\\n\\n' + $json.userPrompt }] }] }) }}"
            }
          ]
        }
      },
      "id": "gemini-response",
      "name": "Gemini - Gerar Resposta",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2450,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const geminiResp = $input.first().json;\nconst prepData = $('Preparar Dados para Gemini').first().json;\n\nlet responseText = '';\ntry {\n  responseText = geminiResp?.candidates?.[0]?.content?.parts?.[0]?.text || '\u274c Erro ao gerar resposta.';\n} catch(e) {\n  responseText = '\u274c Erro ao processar sua solicita\u00e7\u00e3o. Tente novamente.';\n}\n\nreturn [{ json: { response: responseText, chatId: prepData.chatId } }];"
      },
      "id": "parse-gemini-response",
      "name": "Parse Resposta Gemini",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2670,
        400
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ $json.response }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "send-final-response",
      "name": "Enviar Resposta Final",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2890,
        400
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=COLE_AQUI_A_URL_DO_WEBHOOK_DO_FLUXO_2_DEPOIS_DE_SALVAR_E_ATIVAR_ELE",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "=body",
              "value": "={{ JSON.stringify({ telegramId: $json.telegramId, userId: $json.userId, chatId: $json.chatId, photoFileId: $json.photoFileId, firstName: $json.firstName, telegramBotToken: '8733282592:AAF7232MFeMdRcV6HyHUeKvyTKe71cv8oNw', geminiApiKey: '<redacted-credential>', supabaseUrl: 'https://lhybdghiuafcsvytxhdp.supabase.co', supabaseKey: 'sb_publishable_omUBTYHoL5mxrpNe_AlNbQ_DS7FeBQt' }) }}"
            }
          ]
        }
      },
      "id": "call-receipt-workflow",
      "name": "Chamar Fluxo de Nota Fiscal",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1350,
        620
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "jsCode": "const receiptResult = $input.first().json || {};\nconst upstream = $('Verificar Estado do Usu?rio').first().json;\n\nconst responseText =\n  receiptResult.response ||\n  receiptResult.message ||\n  receiptResult.body?.response ||\n  'Recebi sua nota fiscal, mas ocorreu um erro no processamento. Tente novamente em alguns minutos.';\n\nreturn [{\n  json: {\n    chatId: upstream.chatId,\n    response: responseText,\n  },\n}];"
      },
      "id": "parse-receipt-response",
      "name": "Parse Retorno Nota Fiscal",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1570,
        620
      ]
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Extrair Dados da Mensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extrair Dados da Mensagem": {
      "main": [
        [
          {
            "node": "Verificar Usu\u00e1rio no Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar Usu\u00e1rio no Supabase": {
      "main": [
        [
          {
            "node": "Verificar Estado do Usu\u00e1rio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar Estado do Usu\u00e1rio": {
      "main": [
        [
          {
            "node": "Roteador Principal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Roteador Principal": {
      "main": [
        [
          {
            "node": "L\u00f3gica de Cadastro",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Chamar Fluxo de Nota Fiscal",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Gemini - Identificar Inten\u00e7\u00e3o",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "L\u00f3gica de Cadastro": {
      "main": [
        [
          {
            "node": "\u00c9 Novo Usu\u00e1rio?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u00c9 Novo Usu\u00e1rio?": {
      "main": [
        [
          {
            "node": "Criar Usu\u00e1rio no Supabase",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Atualizar Registro no Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Criar Usu\u00e1rio no Supabase": {
      "main": [
        [
          {
            "node": "Enviar Resposta de Cadastro",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Atualizar Registro no Supabase": {
      "main": [
        [
          {
            "node": "Enviar Resposta de Cadastro",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini - Identificar Inten\u00e7\u00e3o": {
      "main": [
        [
          {
            "node": "Parse Inten\u00e7\u00e3o do Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Inten\u00e7\u00e3o do Gemini": {
      "main": [
        [
          {
            "node": "Switch de Inten\u00e7\u00f5es",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch de Inten\u00e7\u00f5es": {
      "main": [
        [
          {
            "node": "Buscar Hist\u00f3rico de Pre\u00e7os",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar Onde Encontrar Item",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar Mercados Pr\u00f3ximos",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar Comparativo de Pre\u00e7os",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Resposta de Saldo de Pontos",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Resposta Padr\u00e3o / Ajuda",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar Hist\u00f3rico de Pre\u00e7os": {
      "main": [
        [
          {
            "node": "Preparar Dados para Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar Onde Encontrar Item": {
      "main": [
        [
          {
            "node": "Preparar Dados para Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar Mercados Pr\u00f3ximos": {
      "main": [
        [
          {
            "node": "Preparar Dados para Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar Comparativo de Pre\u00e7os": {
      "main": [
        [
          {
            "node": "Preparar Dados para Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preparar Dados para Gemini": {
      "main": [
        [
          {
            "node": "Gemini - Gerar Resposta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini - Gerar Resposta": {
      "main": [
        [
          {
            "node": "Parse Resposta Gemini",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Resposta Gemini": {
      "main": [
        [
          {
            "node": "Enviar Resposta Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resposta de Saldo de Pontos": {
      "main": [
        [
          {
            "node": "Enviar Resposta Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resposta Padr\u00e3o / Ajuda": {
      "main": [
        [
          {
            "node": "Enviar Resposta Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Chamar Fluxo de Nota Fiscal": {
      "main": [
        [
          {
            "node": "Parse Retorno Nota Fiscal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Retorno Nota Fiscal": {
      "main": [
        [
          {
            "node": "Enviar Resposta Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    "mercado-chat"
  ],
  "triggerCount": 1,
  "updatedAt": "2026-03-06T00:00:00.000Z",
  "versionId": "1"
}