{
  "id": "CODWF03bCustomerBrain",
  "name": "COD · WF-03b Customer Message Brain",
  "active": false,
  "nodes": [
    {
      "parameters": {
        "content": "## Layer 3b · Customer Message Brain\nChannel-agnostic conversation state, ownership checks, structured OpenAI intent/sentiment, direct button actions, retention, address changes, escalation, and complete conversation logging.",
        "height": 240,
        "width": 2300,
        "color": 4
      },
      "id": "wf03b-note-layer",
      "name": "Layer 3b · AI Decision Brain",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1400,
        -520
      ]
    },
    {
      "parameters": {
        "inputSource": "passthrough"
      },
      "id": "wf03b-trigger",
      "name": "Customer Message Request",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1.2,
      "position": [
        -1340,
        -40
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "test-inbound",
        "authentication": "none",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "wf03b-test-webhook",
      "name": "Test Inbound Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -1340,
        120
      ],
      "webhookId": "cod-test-inbound-v1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-enabled",
              "leftValue": "={{ $env.ENABLE_TEST_HOOKS }}",
              "rightValue": "true",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "wf03b-test-key",
              "leftValue": "={{ $json.headers['x-api-key'] || '' }}",
              "rightValue": "={{ $env.ORDER_WEBHOOK_KEY }}",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "wf03b-test-gate",
      "name": "Test Hooks Enabled & Authorized?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -1120,
        120
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { accepted: true } }}",
        "options": {
          "responseCode": 202
        }
      },
      "id": "wf03b-test-accepted",
      "name": "Respond Test Accepted",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        -900,
        240
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { error: 'NOT_FOUND' } }}",
        "options": {
          "responseCode": 404
        }
      },
      "id": "wf03b-test-disabled",
      "name": "Respond Test Hook Unavailable",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        -900,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "let __smartCodRun;\n(() => {\n  // n8n/code/inbound.ts\n  var intents = /* @__PURE__ */ new Set([\"confirm\", \"cancel\", \"change_address\", \"question\", \"complaint\", \"unclear\"]);\n  var reasons = /* @__PURE__ */ new Set([\"price\", \"changed_mind\", \"duplicate\", \"delivery_time\", \"other\"]);\n  var sentiments = /* @__PURE__ */ new Set([\"positive\", \"neutral\", \"negative\", \"angry\"]);\n  function object(value) {\n    return value && typeof value === \"object\" ? value : {};\n  }\n  function validateAnalysis(value) {\n    const candidate = typeof value === \"string\" ? object(JSON.parse(value)) : object(value);\n    const intent = String(candidate.intent ?? \"unclear\");\n    const cancelReason = candidate.cancel_reason == null ? null : String(candidate.cancel_reason);\n    const sentiment = String(candidate.sentiment ?? \"neutral\");\n    const confidence = Number(candidate.confidence ?? 0);\n    if (!intents.has(intent) || cancelReason !== null && !reasons.has(cancelReason) || !sentiments.has(sentiment) || !Number.isFinite(confidence)) {\n      throw new Error(\"Invalid AI intent payload\");\n    }\n    return {\n      intent,\n      new_address: candidate.new_address == null ? null : String(candidate.new_address),\n      cancel_reason: cancelReason,\n      sentiment,\n      confidence: Math.max(0, Math.min(1, confidence)),\n      reply_ar: String(candidate.reply_ar ?? \"\")\n    };\n  }\n  function normalizeInbound(payload) {\n    const source = object(payload.body ?? payload);\n    if (source.inbound && typeof source.inbound === \"object\") {\n      return source.inbound;\n    }\n    if (source.chatId) {\n      return {\n        channel: \"TELEGRAM\",\n        chatId: String(source.chatId),\n        username: source.username ? String(source.username) : void 0,\n        text: String(source.text ?? source.transcript ?? \"\"),\n        transcript: source.transcript ? String(source.transcript) : void 0,\n        callbackData: source.callbackData ? String(source.callbackData) : void 0,\n        messageType: String(source.messageType ?? (source.callbackData ? \"BUTTON\" : \"TEXT\")),\n        fileId: source.fileId ? String(source.fileId) : void 0,\n        analysis: source.analysis ? validateAnalysis(source.analysis) : void 0,\n        raw: source\n      };\n    }\n    const message = object(source.message);\n    const callback = object(source.callback_query);\n    const callbackMessage = object(callback.message);\n    const chat = object(message.chat ?? callbackMessage.chat);\n    const from = object(message.from ?? callback.from);\n    const voice = object(message.voice ?? message.audio);\n    const callbackData = callback.data ? String(callback.data) : void 0;\n    const transcript = source.transcript ? String(source.transcript) : void 0;\n    return {\n      channel: \"TELEGRAM\",\n      chatId: String(chat.id ?? \"\"),\n      username: from.username ? String(from.username) : void 0,\n      text: String(message.text ?? message.caption ?? transcript ?? callbackData ?? \"\"),\n      transcript,\n      callbackData,\n      messageType: callbackData ? \"BUTTON\" : voice.file_id ? \"VOICE\" : \"TEXT\",\n      fileId: voice.file_id ? String(voice.file_id) : void 0,\n      raw: source\n    };\n  }\n  function run(items) {\n    return items.map((item) => ({ ...item, json: { inbound: normalizeInbound(item.json) } }));\n  }\n\n  // inbound.bundle-entry.ts\n  __smartCodRun = run;\n})();\nreturn __smartCodRun($input.all(), { now: new Date().toISOString() });"
      },
      "id": "wf03b-normalize",
      "name": "Normalize to InboundMessage",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -880,
        -40
      ]
    },
    {
      "parameters": {
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/customers/by-telegram/{{ encodeURIComponent($json.inbound.chatId) }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-customer",
      "name": "Fetch Customer & Open Order",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -640,
        -40
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/settings",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-settings",
      "name": "Fetch Order & FAQ Settings",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -400,
        -40
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-context-inbound",
              "name": "inbound",
              "value": "={{ $('Normalize to InboundMessage').item.json.inbound }}",
              "type": "object"
            },
            {
              "id": "wf03b-context-customer",
              "name": "customer",
              "value": "={{ $('Fetch Customer & Open Order').item.json.customer }}",
              "type": "object"
            },
            {
              "id": "wf03b-context-order",
              "name": "order",
              "value": "={{ $('Fetch Customer & Open Order').item.json.latestOpenOrder }}",
              "type": "object"
            },
            {
              "id": "wf03b-context-pending",
              "name": "pendingAction",
              "value": "={{ $('Fetch Customer & Open Order').item.json.pendingAction }}",
              "type": "string"
            },
            {
              "id": "wf03b-context-settings",
              "name": "settings",
              "value": "={{ $json }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-context",
      "name": "Merge Conversation & Order Context",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -160,
        -40
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/conversations",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ orderId: $json.order?.id || undefined, customerId: $json.customer.id, channel: 'TELEGRAM', direction: 'IN', messageType: $json.inbound.messageType, content: $json.inbound.text || undefined, transcript: $json.inbound.transcript || undefined, intent: $json.inbound.analysis?.intent || ($json.pendingAction === 'AWAIT_ADDRESS' ? 'change_address' : undefined), sentiment: $json.inbound.analysis?.sentiment || undefined, confidence: $json.inbound.analysis?.confidence, externalRef: $json.inbound.fileId || undefined, raw: $json.inbound.raw }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-log-inbound",
      "name": "Log Conversation Entry",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        80,
        -40
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-restore-inbound",
              "name": "inbound",
              "value": "={{ $('Merge Conversation & Order Context').item.json.inbound }}",
              "type": "object"
            },
            {
              "id": "wf03b-restore-customer",
              "name": "customer",
              "value": "={{ $('Merge Conversation & Order Context').item.json.customer }}",
              "type": "object"
            },
            {
              "id": "wf03b-restore-order",
              "name": "order",
              "value": "={{ $('Merge Conversation & Order Context').item.json.order }}",
              "type": "object"
            },
            {
              "id": "wf03b-restore-pending",
              "name": "pendingAction",
              "value": "={{ $('Merge Conversation & Order Context').item.json.pendingAction }}",
              "type": "string"
            },
            {
              "id": "wf03b-restore-settings",
              "name": "settings",
              "value": "={{ $('Merge Conversation & Order Context').item.json.settings }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-restore",
      "name": "Restore Conversation Context",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        320,
        -40
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-pending-address",
              "leftValue": "={{ $json.pendingAction }}",
              "rightValue": "AWAIT_ADDRESS",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "wf03b-pending-router",
      "name": "Pending-Action Switch",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        560,
        -40
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-pending-address-value",
              "name": "shipping",
              "value": "={{ { address: $json.inbound.text, country: $json.order.country } }}",
              "type": "object"
            },
            {
              "id": "wf03b-pending-address-context",
              "name": "decisionContext",
              "value": "={{ $json }}",
              "type": "object"
            },
            {
              "id": "wf03b-pending-address-settings",
              "name": "settings",
              "value": "={{ $json.settings }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-address-pending",
      "name": "Prepare Pending New Address",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        800,
        -240
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-has-callback",
              "leftValue": "={{ $json.inbound.callbackData || '' }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "wf03b-callback-router",
      "name": "Callback or AI Router",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        800,
        40
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-callback-order",
              "name": "callbackOrderId",
              "value": "={{ ($json.inbound.callbackData.match(/ORD-\\d{13}$/) || [null])[0] }}",
              "type": "string"
            },
            {
              "id": "wf03b-callback-context",
              "name": "decisionContext",
              "value": "={{ $json }}",
              "type": "object"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "wf03b-callback-parse",
      "name": "Process Button Action Direct",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1040,
        -20
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-owned",
              "leftValue": "={{ $json.callbackOrderId }}",
              "rightValue": "={{ $json.order.id }}",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "wf03b-ownership",
      "name": "Callback Owns Open Order?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1280,
        -20
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-forged-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-forged-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-forged-template",
              "name": "template",
              "value": "holding_reply",
              "type": "string"
            },
            {
              "id": "wf03b-forged-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-forged-chat",
              "name": "chatId",
              "value": "={{ $json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-forged-vars",
              "name": "vars",
              "value": "={{ {} }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-forged-payload",
      "name": "Reject Forged Callback",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1520,
        100
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-forged-send",
      "name": "Send Forged Action Rejection",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        1760,
        100
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-callback-analysis",
              "name": "analysis",
              "value": "={{ (() => { const value = $json.inbound.callbackData; if (value.startsWith('act:confirm:') || value.startsWith('ret:accept:')) return { intent: 'confirm', new_address: null, cancel_reason: null, sentiment: 'positive', confidence: 1, reply_ar: 'تم التأكيد' }; if (value.startsWith('act:cancel:') || value.startsWith('ret:decline:')) return { intent: 'cancel', new_address: null, cancel_reason: value.startsWith('ret:decline:') ? 'price' : 'other', sentiment: 'neutral', confidence: 1, reply_ar: 'تم الإلغاء' }; if (value.startsWith('act:addr:')) return { intent: 'change_address', new_address: null, cancel_reason: null, sentiment: 'neutral', confidence: 1, reply_ar: 'أرسل العنوان الجديد' }; return { intent: 'unclear', new_address: null, cancel_reason: null, sentiment: 'neutral', confidence: 0, reply_ar: '' }; })() }}",
              "type": "object"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "wf03b-callback-analysis",
      "name": "Map Callback to Trusted Intent",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1520,
        -80
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-canned",
              "leftValue": "={{ $json.inbound.analysis ? 'yes' : '' }}",
              "rightValue": "yes",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "wf03b-canned-router",
      "name": "Canned Test Analysis?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1040,
        220
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-use-canned",
              "name": "analysis",
              "value": "={{ $json.inbound.analysis }}",
              "type": "object"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "wf03b-canned",
      "name": "Use Canned Structured Analysis",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1280,
        180
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ 'Customer message: ' + $json.inbound.text + '\nOrder data: ' + JSON.stringify($json.order) + '\nStore FAQ: ' + $json.settings.faq }}",
        "options": {
          "systemMessage": "You classify COD customer messages written in Egyptian, Gulf or Modern Standard Arabic, or English. Answer politely in the customer's dialect. Never invent prices, policies, or dates beyond the supplied order data and FAQ. Return only the structured JSON requested by the output parser."
        }
      },
      "id": "wf03b-agent",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        1280,
        320
      ]
    },
    {
      "parameters": {
        "modelName": "={{ $env.OPENAI_MODEL }}",
        "options": {
          "temperature": 0
        }
      },
      "id": "wf03b-model",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        1180,
        500
      ],
      "credentials": {
        "openAiApi": {
          "id": "cred_openai",
          "name": "COD OpenAI"
        }
      }
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\"intent\":\"confirm\",\"new_address\":null,\"cancel_reason\":null,\"sentiment\":\"positive\",\"confidence\":0.95,\"reply_ar\":\"تم\"}"
      },
      "id": "wf03b-parser",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        1420,
        500
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-ai-analysis",
              "name": "analysis",
              "value": "={{ typeof $json.output === 'string' ? JSON.parse($json.output) : $json.output }}",
              "type": "object"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "wf03b-ai-normalize",
      "name": "Normalize Structured AI Output",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1520,
        320
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-decision-inbound",
              "name": "inbound",
              "value": "={{ $('Restore Conversation Context').item.json.inbound }}",
              "type": "object"
            },
            {
              "id": "wf03b-decision-customer",
              "name": "customer",
              "value": "={{ $('Restore Conversation Context').item.json.customer }}",
              "type": "object"
            },
            {
              "id": "wf03b-decision-order",
              "name": "order",
              "value": "={{ $('Restore Conversation Context').item.json.order }}",
              "type": "object"
            },
            {
              "id": "wf03b-decision-settings",
              "name": "settings",
              "value": "={{ $('Restore Conversation Context').item.json.settings }}",
              "type": "object"
            },
            {
              "id": "wf03b-decision-analysis",
              "name": "analysis",
              "value": "={{ $json.analysis }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-decision",
      "name": "Merge Order & AI Intent Context",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1780,
        260
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/conversations",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ orderId: $json.order.id, customerId: $json.customer.id, channel: 'TELEGRAM', direction: 'IN', messageType: $json.inbound.messageType, content: $json.inbound.text, transcript: $json.inbound.transcript || undefined, intent: $json.analysis.intent, sentiment: $json.analysis.sentiment, confidence: $json.analysis.confidence, escalated: $json.analysis.sentiment === 'angry' || $json.analysis.intent === 'complaint' || $json.analysis.intent === 'unclear' || $json.analysis.confidence < 0.6, aiModel: $env.OPENAI_MODEL, raw: { analysis: $json.analysis } }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-log-analysis",
      "name": "Log Intent, Sentiment & Confidence",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2020,
        260
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-after-log-inbound",
              "name": "inbound",
              "value": "={{ $('Merge Order & AI Intent Context').item.json.inbound }}",
              "type": "object"
            },
            {
              "id": "wf03b-after-log-customer",
              "name": "customer",
              "value": "={{ $('Merge Order & AI Intent Context').item.json.customer }}",
              "type": "object"
            },
            {
              "id": "wf03b-after-log-order",
              "name": "order",
              "value": "={{ $('Merge Order & AI Intent Context').item.json.order }}",
              "type": "object"
            },
            {
              "id": "wf03b-after-log-settings",
              "name": "settings",
              "value": "={{ $('Merge Order & AI Intent Context').item.json.settings }}",
              "type": "object"
            },
            {
              "id": "wf03b-after-log-analysis",
              "name": "analysis",
              "value": "={{ $('Merge Order & AI Intent Context').item.json.analysis }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-after-log",
      "name": "Restore Decision Context",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        2260,
        260
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-angry-sentiment",
              "leftValue": "={{ $json.analysis.sentiment }}",
              "rightValue": "angry",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "wf03b-complaint-intent",
              "leftValue": "={{ $json.analysis.intent }}",
              "rightValue": "complaint",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "id": "wf03b-angry",
      "name": "Angry Customer Sentiment Filter",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        2500,
        260
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "wf03b-intent-confirm",
                    "leftValue": "={{ $json.analysis.intent }}",
                    "rightValue": "confirm",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Confirm"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "wf03b-intent-cancel",
                    "leftValue": "={{ $json.analysis.intent }}",
                    "rightValue": "cancel",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Cancel"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "wf03b-intent-address",
                    "leftValue": "={{ $json.analysis.intent }}",
                    "rightValue": "change_address",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Change Address"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "wf03b-intent-question",
                    "leftValue": "={{ $json.analysis.intent }}",
                    "rightValue": "question",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Question"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "wf03b-intent-unclear",
                    "leftValue": "={{ $json.analysis.intent === 'unclear' || $json.analysis.confidence < 0.6 ? 'yes' : '' }}",
                    "rightValue": "yes",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Unclear"
            }
          ]
        },
        "options": {
          "fallbackOutput": "none"
        }
      },
      "id": "wf03b-intent-router",
      "name": "Intent Decision Final Router",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        2740,
        360
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/orders/{{ $json.order.id }}/transition",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ to: 'NEEDS_REVIEW', reason: 'ANGRY_CUSTOMER', actor: 'ai', meta: { transcript: $json.inbound.transcript || $json.inbound.text, sentiment: $json.analysis.sentiment } }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-angry-transition",
      "name": "Flag Angry Customer for Review",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2740,
        80
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/orders/{{ $('Restore Decision Context').item.json.order.id }}/transition",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ to: 'CONFIRMED', actor: 'customer', meta: { channel: 'TELEGRAM', intent: 'confirm' } }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-confirm-transition",
      "name": "Transition CONFIRMED",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3020,
        260
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-retention-reason",
              "leftValue": "={{ $json.analysis.cancel_reason }}",
              "rightValue": "price",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "wf03b-retention-enabled",
              "leftValue": "={{ $json.settings.retention.enabled }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            },
            {
              "id": "wf03b-retention-unused",
              "leftValue": "={{ $json.order.retentionOffered }}",
              "rightValue": false,
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "wf03b-retention-router",
      "name": "Sales Retention Negotiator",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        3020,
        400
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/orders/{{ $json.order.id }}/discount",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ percent: $json.settings.retention.discountPercent }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-retention-discount",
      "name": "Apply Retention Discount",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3260,
        360
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/orders/{{ $json.order.id }}/transition",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ to: 'CANCELLED', reason: $json.analysis.cancel_reason || 'other', actor: 'customer', meta: { channel: 'TELEGRAM' } }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-cancel-transition",
      "name": "Transition CANCELLED",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3260,
        480
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "wf03b-address-inline",
              "leftValue": "={{ $json.analysis.new_address || '' }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "wf03b-address-router",
      "name": "New Address Included?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        3020,
        600
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/customers/{{ $json.customer.id }}/pending-action",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ action: 'AWAIT_ADDRESS', orderId: $json.order.id }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-await-address",
      "name": "Set AWAIT_ADDRESS State",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3260,
        680
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-inline-address-value",
              "name": "shipping",
              "value": "={{ { address: $json.analysis.new_address, country: $json.order.country } }}",
              "type": "object"
            },
            {
              "id": "wf03b-inline-address-context",
              "name": "decisionContext",
              "value": "={{ $json }}",
              "type": "object"
            },
            {
              "id": "wf03b-inline-address-settings",
              "name": "settings",
              "value": "={{ $json.settings }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-address-inline",
      "name": "Prepare Inline New Address",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3260,
        580
      ]
    },
    {
      "parameters": {
        "jsCode": "let __smartCodRun;\n(() => {\n  // shared/data/eg-governorates.json\n  var eg_governorates_default = [\n    {\n      code: \"CAI\",\n      ar: \"\\u0627\\u0644\\u0642\\u0627\\u0647\\u0631\\u0629\",\n      en: \"Cairo\",\n      aliases: [\"\\u0627\\u0644\\u0642\\u0627\\u0647\\u0631\\u0647\", \"\\u0642\\u0627\\u0647\\u0631\\u0629\", \"cairo\", \"al qahirah\", \"nasr city\", \"\\u0645\\u062F\\u064A\\u0646\\u0629 \\u0646\\u0635\\u0631\", \"\\u0645\\u0635\\u0631 \\u0627\\u0644\\u062C\\u062F\\u064A\\u062F\\u0629\", \"heliopolis\", \"\\u0627\\u0644\\u0645\\u0639\\u0627\\u062F\\u064A\", \"maadi\", \"\\u0627\\u0644\\u062A\\u062C\\u0645\\u0639 \\u0627\\u0644\\u062E\\u0627\\u0645\\u0633\", \"new cairo\", \"\\u0634\\u0628\\u0631\\u0627\", \"\\u062D\\u0644\\u0648\\u0627\\u0646\"],\n      zone: \"METRO\"\n    },\n    {\n      code: \"GIZ\",\n      ar: \"\\u0627\\u0644\\u062C\\u064A\\u0632\\u0629\",\n      en: \"Giza\",\n      aliases: [\"\\u0627\\u0644\\u062C\\u064A\\u0632\\u0647\", \"\\u062C\\u064A\\u0632\\u0629\", \"giza\", \"gizeh\", \"6 october\", \"6th of october\", \"\\u0666 \\u0623\\u0643\\u062A\\u0648\\u0628\\u0631\", \"\\u0627\\u0644\\u0633\\u0627\\u062F\\u0633 \\u0645\\u0646 \\u0623\\u0643\\u062A\\u0648\\u0628\\u0631\", \"\\u0627\\u0644\\u0634\\u064A\\u062E \\u0632\\u0627\\u064A\\u062F\", \"sheikh zayed\", \"\\u0627\\u0644\\u0647\\u0631\\u0645\", \"haram\", \"\\u0627\\u0644\\u062F\\u0642\\u064A\", \"dokki\", \"\\u0627\\u0644\\u0645\\u0647\\u0646\\u062F\\u0633\\u064A\\u0646\"],\n      zone: \"METRO\"\n    },\n    {\n      code: \"ALX\",\n      ar: \"\\u0627\\u0644\\u0625\\u0633\\u0643\\u0646\\u062F\\u0631\\u064A\\u0629\",\n      en: \"Alexandria\",\n      aliases: [\"\\u0627\\u0644\\u0627\\u0633\\u0643\\u0646\\u062F\\u0631\\u064A\\u0629\", \"\\u0627\\u0644\\u0625\\u0633\\u0643\\u0646\\u062F\\u0631\\u064A\\u0647\", \"\\u0627\\u0633\\u0643\\u0646\\u062F\\u0631\\u064A\\u0629\", \"alexandria\", \"alex\", \"\\u0633\\u0645\\u0648\\u062D\\u0629\", \"smouha\", \"\\u0633\\u064A\\u062F\\u064A \\u062C\\u0627\\u0628\\u0631\", \"\\u0627\\u0644\\u0645\\u0646\\u062A\\u0632\\u0629\", \"\\u0627\\u0644\\u0639\\u062C\\u0645\\u064A\", \"borg el arab\", \"\\u0628\\u0631\\u062C \\u0627\\u0644\\u0639\\u0631\\u0628\"],\n      zone: \"METRO\"\n    },\n    {\n      code: \"DK\",\n      ar: \"\\u0627\\u0644\\u062F\\u0642\\u0647\\u0644\\u064A\\u0629\",\n      en: \"Dakahlia\",\n      aliases: [\"\\u0627\\u0644\\u062F\\u0642\\u0647\\u0644\\u064A\\u0647\", \"dakahlia\", \"dakhelya\", \"\\u0627\\u0644\\u0645\\u0646\\u0635\\u0648\\u0631\\u0629\", \"mansoura\", \"\\u0637\\u0644\\u062E\\u0627\", \"talkha\", \"\\u0645\\u064A\\u062A \\u063A\\u0645\\u0631\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"BA\",\n      ar: \"\\u0627\\u0644\\u0628\\u062D\\u0631 \\u0627\\u0644\\u0623\\u062D\\u0645\\u0631\",\n      en: \"Red Sea\",\n      aliases: [\"\\u0627\\u0644\\u0628\\u062D\\u0631 \\u0627\\u0644\\u0627\\u062D\\u0645\\u0631\", \"red sea\", \"\\u0627\\u0644\\u063A\\u0631\\u062F\\u0642\\u0629\", \"hurghada\", \"\\u0633\\u0641\\u0627\\u062C\\u0627\", \"\\u0645\\u0631\\u0633\\u0649 \\u0639\\u0644\\u0645\", \"marsa alam\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"BH\",\n      ar: \"\\u0627\\u0644\\u0628\\u062D\\u064A\\u0631\\u0629\",\n      en: \"Beheira\",\n      aliases: [\"\\u0627\\u0644\\u0628\\u062D\\u064A\\u0631\\u0647\", \"beheira\", \"behera\", \"\\u062F\\u0645\\u0646\\u0647\\u0648\\u0631\", \"damanhur\", \"\\u0643\\u0641\\u0631 \\u0627\\u0644\\u062F\\u0648\\u0627\\u0631\", \"\\u0631\\u0634\\u064A\\u062F\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"FYM\",\n      ar: \"\\u0627\\u0644\\u0641\\u064A\\u0648\\u0645\",\n      en: \"Fayoum\",\n      aliases: [\"\\u0627\\u0644\\u0641\\u064A\\u0648\\u0645\", \"\\u0641\\u064A\\u0648\\u0645\", \"fayoum\", \"faiyum\", \"\\u0633\\u0646\\u0648\\u0631\\u0633\", \"\\u0625\\u0637\\u0633\\u0627\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"GH\",\n      ar: \"\\u0627\\u0644\\u063A\\u0631\\u0628\\u064A\\u0629\",\n      en: \"Gharbia\",\n      aliases: [\"\\u0627\\u0644\\u063A\\u0631\\u0628\\u064A\\u0647\", \"gharbia\", \"\\u0637\\u0646\\u0637\\u0627\", \"tanta\", \"\\u0627\\u0644\\u0645\\u062D\\u0644\\u0629 \\u0627\\u0644\\u0643\\u0628\\u0631\\u0649\", \"mahalla\", \"\\u0632\\u0641\\u062A\\u0649\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"IS\",\n      ar: \"\\u0627\\u0644\\u0625\\u0633\\u0645\\u0627\\u0639\\u064A\\u0644\\u064A\\u0629\",\n      en: \"Ismailia\",\n      aliases: [\"\\u0627\\u0644\\u0627\\u0633\\u0645\\u0627\\u0639\\u064A\\u0644\\u064A\\u0629\", \"\\u0627\\u0644\\u0625\\u0633\\u0645\\u0627\\u0639\\u064A\\u0644\\u064A\\u0647\", \"ismailia\", \"\\u0627\\u0644\\u062A\\u0644 \\u0627\\u0644\\u0643\\u0628\\u064A\\u0631\", \"\\u0641\\u0627\\u064A\\u062F\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"MNF\",\n      ar: \"\\u0627\\u0644\\u0645\\u0646\\u0648\\u0641\\u064A\\u0629\",\n      en: \"Monufia\",\n      aliases: [\"\\u0627\\u0644\\u0645\\u0646\\u0648\\u0641\\u064A\\u0647\", \"\\u0627\\u0644\\u0645\\u0646\\u0648\\u0641\\u064A\\u0629\", \"monufia\", \"menofia\", \"\\u0634\\u0628\\u064A\\u0646 \\u0627\\u0644\\u0643\\u0648\\u0645\", \"shebin el kom\", \"\\u0645\\u0646\\u0648\\u0641\", \"\\u0627\\u0644\\u0633\\u0627\\u062F\\u0627\\u062A\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"MN\",\n      ar: \"\\u0627\\u0644\\u0645\\u0646\\u064A\\u0627\",\n      en: \"Minya\",\n      aliases: [\"\\u0627\\u0644\\u0645\\u0646\\u064A\\u0627\", \"\\u0645\\u0646\\u064A\\u0627\", \"minya\", \"\\u0645\\u0644\\u0648\\u064A\", \"mallawi\", \"\\u0633\\u0645\\u0627\\u0644\\u0648\\u0637\", \"\\u0628\\u0646\\u064A \\u0645\\u0632\\u0627\\u0631\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"KB\",\n      ar: \"\\u0627\\u0644\\u0642\\u0644\\u064A\\u0648\\u0628\\u064A\\u0629\",\n      en: \"Qalyubia\",\n      aliases: [\"\\u0627\\u0644\\u0642\\u0644\\u064A\\u0648\\u0628\\u064A\\u0647\", \"qalyubia\", \"qaliubiya\", \"\\u0628\\u0646\\u0647\\u0627\", \"banha\", \"\\u0634\\u0628\\u0631\\u0627 \\u0627\\u0644\\u062E\\u064A\\u0645\\u0629\", \"\\u0627\\u0644\\u0639\\u0628\\u0648\\u0631\", \"\\u0627\\u0644\\u062E\\u0627\\u0646\\u0643\\u0629\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"WAD\",\n      ar: \"\\u0627\\u0644\\u0648\\u0627\\u062F\\u064A \\u0627\\u0644\\u062C\\u062F\\u064A\\u062F\",\n      en: \"New Valley\",\n      aliases: [\"\\u0627\\u0644\\u0648\\u0627\\u062F\\u0649 \\u0627\\u0644\\u062C\\u062F\\u064A\\u062F\", \"new valley\", \"el wadi el gedid\", \"\\u0627\\u0644\\u062E\\u0627\\u0631\\u062C\\u0629\", \"kharga\", \"\\u0627\\u0644\\u062F\\u0627\\u062E\\u0644\\u0629\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"SUZ\",\n      ar: \"\\u0627\\u0644\\u0633\\u0648\\u064A\\u0633\",\n      en: \"Suez\",\n      aliases: [\"\\u0627\\u0644\\u0633\\u0648\\u064A\\u0633\", \"\\u0633\\u0648\\u064A\\u0633\", \"suez\", \"\\u0627\\u0644\\u0639\\u064A\\u0646 \\u0627\\u0644\\u0633\\u062E\\u0646\\u0629\", \"ain sokhna\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"ASN\",\n      ar: \"\\u0623\\u0633\\u0648\\u0627\\u0646\",\n      en: \"Aswan\",\n      aliases: [\"\\u0627\\u0633\\u0648\\u0627\\u0646\", \"aswan\", \"\\u0625\\u062F\\u0641\\u0648\", \"edfu\", \"\\u0643\\u0648\\u0645 \\u0623\\u0645\\u0628\\u0648\", \"\\u0646\\u0635\\u0631 \\u0627\\u0644\\u0646\\u0648\\u0628\\u0629\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"AST\",\n      ar: \"\\u0623\\u0633\\u064A\\u0648\\u0637\",\n      en: \"Assiut\",\n      aliases: [\"\\u0627\\u0633\\u064A\\u0648\\u0637\", \"\\u0623\\u0633\\u064A\\u0648\\u0637\", \"assiut\", \"asyut\", \"\\u062F\\u064A\\u0631\\u0648\\u0637\", \"\\u0645\\u0646\\u0641\\u0644\\u0648\\u0637\", \"\\u0627\\u0644\\u0642\\u0648\\u0635\\u064A\\u0629\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"BNS\",\n      ar: \"\\u0628\\u0646\\u064A \\u0633\\u0648\\u064A\\u0641\",\n      en: \"Beni Suef\",\n      aliases: [\"\\u0628\\u0646\\u0649 \\u0633\\u0648\\u064A\\u0641\", \"beni suef\", \"bani suwayf\", \"\\u0627\\u0644\\u0648\\u0627\\u0633\\u0637\\u0649\", \"\\u0628\\u0628\\u0627\", \"\\u0646\\u0627\\u0635\\u0631 \\u0628\\u0646\\u064A \\u0633\\u0648\\u064A\\u0641\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"PTS\",\n      ar: \"\\u0628\\u0648\\u0631\\u0633\\u0639\\u064A\\u062F\",\n      en: \"Port Said\",\n      aliases: [\"\\u0628\\u0648\\u0631\\u062A \\u0633\\u0639\\u064A\\u062F\", \"port said\", \"portsaid\", \"\\u0628\\u0648\\u0631 \\u0641\\u0624\\u0627\\u062F\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"DT\",\n      ar: \"\\u062F\\u0645\\u064A\\u0627\\u0637\",\n      en: \"Damietta\",\n      aliases: [\"\\u062F\\u0645\\u064A\\u0627\\u0637\", \"damietta\", \"domyat\", \"\\u0631\\u0623\\u0633 \\u0627\\u0644\\u0628\\u0631\", \"ras el bar\", \"\\u062F\\u0645\\u064A\\u0627\\u0637 \\u0627\\u0644\\u062C\\u062F\\u064A\\u062F\\u0629\", \"\\u0643\\u0641\\u0631 \\u0633\\u0639\\u062F\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"SHR\",\n      ar: \"\\u0627\\u0644\\u0634\\u0631\\u0642\\u064A\\u0629\",\n      en: \"Sharqia\",\n      aliases: [\"\\u0627\\u0644\\u0634\\u0631\\u0642\\u064A\\u0647\", \"sharqia\", \"sharkia\", \"\\u0627\\u0644\\u0632\\u0642\\u0627\\u0632\\u064A\\u0642\", \"zagazig\", \"\\u0627\\u0644\\u0639\\u0627\\u0634\\u0631 \\u0645\\u0646 \\u0631\\u0645\\u0636\\u0627\\u0646\", \"10th of ramadan\", \"\\u0628\\u0644\\u0628\\u064A\\u0633\", \"\\u0645\\u0646\\u064A\\u0627 \\u0627\\u0644\\u0642\\u0645\\u062D\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"JS\",\n      ar: \"\\u062C\\u0646\\u0648\\u0628 \\u0633\\u064A\\u0646\\u0627\\u0621\",\n      en: \"South Sinai\",\n      aliases: [\"\\u062C\\u0646\\u0648\\u0628 \\u0633\\u064A\\u0646\\u0627\", \"south sinai\", \"\\u0634\\u0631\\u0645 \\u0627\\u0644\\u0634\\u064A\\u062E\", \"sharm el sheikh\", \"\\u062F\\u0647\\u0628\", \"dahab\", \"\\u0637\\u0648\\u0631 \\u0633\\u064A\\u0646\\u0627\\u0621\", \"\\u0646\\u0648\\u064A\\u0628\\u0639\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"KFS\",\n      ar: \"\\u0643\\u0641\\u0631 \\u0627\\u0644\\u0634\\u064A\\u062E\",\n      en: \"Kafr El Sheikh\",\n      aliases: [\"\\u0643\\u0641\\u0631 \\u0627\\u0644\\u0634\\u064A\\u062E\", \"kafr el sheikh\", \"kafr al shaykh\", \"\\u062F\\u0633\\u0648\\u0642\", \"desouk\", \"\\u0628\\u0644\\u0637\\u064A\\u0645\", \"\\u0641\\u0648\\u0647\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"MT\",\n      ar: \"\\u0645\\u0637\\u0631\\u0648\\u062D\",\n      en: \"Matrouh\",\n      aliases: [\"\\u0645\\u0631\\u0633\\u0649 \\u0645\\u0637\\u0631\\u0648\\u062D\", \"matrouh\", \"marsa matruh\", \"\\u0627\\u0644\\u0633\\u0627\\u062D\\u0644 \\u0627\\u0644\\u0634\\u0645\\u0627\\u0644\\u064A\", \"north coast\", \"\\u0627\\u0644\\u0639\\u0644\\u0645\\u064A\\u0646\", \"alamein\", \"\\u0633\\u064A\\u0648\\u0629\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"LX\",\n      ar: \"\\u0627\\u0644\\u0623\\u0642\\u0635\\u0631\",\n      en: \"Luxor\",\n      aliases: [\"\\u0627\\u0644\\u0627\\u0642\\u0635\\u0631\", \"\\u0623\\u0642\\u0635\\u0631\", \"luxor\", \"\\u0627\\u0644\\u0642\\u0631\\u0646\\u0629\", \"\\u0625\\u0633\\u0646\\u0627\", \"esna\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"KN\",\n      ar: \"\\u0642\\u0646\\u0627\",\n      en: \"Qena\",\n      aliases: [\"\\u0642\\u0646\\u0627\", \"qena\", \"kina\", \"\\u0646\\u062C\\u0639 \\u062D\\u0645\\u0627\\u062F\\u064A\", \"nag hammadi\", \"\\u0642\\u0648\\u0635\", \"\\u062F\\u0634\\u0646\\u0627\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"SIN\",\n      ar: \"\\u0634\\u0645\\u0627\\u0644 \\u0633\\u064A\\u0646\\u0627\\u0621\",\n      en: \"North Sinai\",\n      aliases: [\"\\u0634\\u0645\\u0627\\u0644 \\u0633\\u064A\\u0646\\u0627\", \"north sinai\", \"\\u0627\\u0644\\u0639\\u0631\\u064A\\u0634\", \"arish\", \"\\u0628\\u0626\\u0631 \\u0627\\u0644\\u0639\\u0628\\u062F\", \"\\u0631\\u0641\\u062D\"],\n      zone: \"REGIONAL\"\n    },\n    {\n      code: \"SHG\",\n      ar: \"\\u0633\\u0648\\u0647\\u0627\\u062C\",\n      en: \"Sohag\",\n      aliases: [\"\\u0633\\u0648\\u0647\\u0627\\u062C\", \"sohag\", \"suhag\", \"\\u0623\\u062E\\u0645\\u064A\\u0645\", \"akhmim\", \"\\u0637\\u0647\\u0637\\u0627\", \"\\u062C\\u0631\\u062C\\u0627\"],\n      zone: \"REGIONAL\"\n    }\n  ];\n\n  // shared/data/gulf-countries.json\n  var gulf_countries_default = [\n    {\n      code: \"SA\",\n      dialCode: \"+966\",\n      ar: \"\\u0627\\u0644\\u0645\\u0645\\u0644\\u0643\\u0629 \\u0627\\u0644\\u0639\\u0631\\u0628\\u064A\\u0629 \\u0627\\u0644\\u0633\\u0639\\u0648\\u062F\\u064A\\u0629\",\n      en: \"Saudi Arabia\",\n      aliases: [\"\\u0627\\u0644\\u0633\\u0639\\u0648\\u062F\\u064A\\u0629\", \"\\u0627\\u0644\\u0633\\u0639\\u0648\\u062F\\u064A\\u0647\", \"ksa\", \"saudi\", \"saudi arabia\", \"riyadh\", \"\\u0627\\u0644\\u0631\\u064A\\u0627\\u0636\", \"jeddah\", \"\\u062C\\u062F\\u0629\"],\n      zone: \"GULF\"\n    },\n    {\n      code: \"AE\",\n      dialCode: \"+971\",\n      ar: \"\\u0627\\u0644\\u0625\\u0645\\u0627\\u0631\\u0627\\u062A \\u0627\\u0644\\u0639\\u0631\\u0628\\u064A\\u0629 \\u0627\\u0644\\u0645\\u062A\\u062D\\u062F\\u0629\",\n      en: \"United Arab Emirates\",\n      aliases: [\"\\u0627\\u0644\\u0625\\u0645\\u0627\\u0631\\u0627\\u062A\", \"\\u0627\\u0644\\u0627\\u0645\\u0627\\u0631\\u0627\\u062A\", \"uae\", \"emirates\", \"dubai\", \"\\u062F\\u0628\\u064A\", \"abu dhabi\", \"\\u0623\\u0628\\u0648\\u0638\\u0628\\u064A\", \"sharjah\", \"\\u0627\\u0644\\u0634\\u0627\\u0631\\u0642\\u0629\"],\n      zone: \"GULF\"\n    },\n    {\n      code: \"KW\",\n      dialCode: \"+965\",\n      ar: \"\\u0627\\u0644\\u0643\\u0648\\u064A\\u062A\",\n      en: \"Kuwait\",\n      aliases: [\"\\u0627\\u0644\\u0643\\u0648\\u064A\\u062A\", \"kuwait\", \"kuwait city\", \"\\u0645\\u062F\\u064A\\u0646\\u0629 \\u0627\\u0644\\u0643\\u0648\\u064A\\u062A\"],\n      zone: \"GULF\"\n    },\n    {\n      code: \"QA\",\n      dialCode: \"+974\",\n      ar: \"\\u0642\\u0637\\u0631\",\n      en: \"Qatar\",\n      aliases: [\"\\u0642\\u0637\\u0631\", \"qatar\", \"doha\", \"\\u0627\\u0644\\u062F\\u0648\\u062D\\u0629\"],\n      zone: \"GULF\"\n    },\n    {\n      code: \"BH\",\n      dialCode: \"+973\",\n      ar: \"\\u0627\\u0644\\u0628\\u062D\\u0631\\u064A\\u0646\",\n      en: \"Bahrain\",\n      aliases: [\"\\u0627\\u0644\\u0628\\u062D\\u0631\\u064A\\u0646\", \"bahrain\", \"manama\", \"\\u0627\\u0644\\u0645\\u0646\\u0627\\u0645\\u0629\"],\n      zone: \"GULF\"\n    },\n    {\n      code: \"OM\",\n      dialCode: \"+968\",\n      ar: \"\\u0633\\u0644\\u0637\\u0646\\u0629 \\u0639\\u0645\\u0627\\u0646\",\n      en: \"Oman\",\n      aliases: [\"\\u0639\\u0645\\u0627\\u0646\", \"\\u0633\\u0644\\u0637\\u0646\\u0629 \\u0639\\u0645\\u0627\\u0646\", \"oman\", \"muscat\", \"\\u0645\\u0633\\u0642\\u0637\"],\n      zone: \"GULF\"\n    }\n  ];\n\n  // n8n/code/sanitize.ts\n  var arabicIndic = \"\\u0660\\u0661\\u0662\\u0663\\u0664\\u0665\\u0666\\u0667\\u0668\\u0669\";\n  var easternArabicIndic = \"\\u06F0\\u06F1\\u06F2\\u06F3\\u06F4\\u06F5\\u06F6\\u06F7\\u06F8\\u06F9\";\n  function toAsciiDigits(value) {\n    return [...value].map((character) => {\n      const arabicIndex = arabicIndic.indexOf(character);\n      if (arabicIndex >= 0) return String(arabicIndex);\n      const easternIndex = easternArabicIndic.indexOf(character);\n      return easternIndex >= 0 ? String(easternIndex) : character;\n    }).join(\"\");\n  }\n\n  // n8n/code/geo.ts\n  function searchable(value) {\n    return toAsciiDigits(String(value ?? \"\")).toLowerCase().normalize(\"NFKD\").replace(/[\\u064b-\\u065f\\u0670]/g, \"\").replace(/[إأآ]/g, \"\\u0627\").replace(/ى/g, \"\\u064A\").replace(/ة/g, \"\\u0647\").replace(/[^\\p{L}\\p{N}]+/gu, \" \").replace(/\\s+/g, \" \").trim();\n  }\n  function containsTerm(haystack, term) {\n    const normalizedTerm = searchable(term);\n    return normalizedTerm.length > 0 && ` ${haystack} `.includes(` ${normalizedTerm} `);\n  }\n  function explicitCountryCode(value) {\n    const raw = String(value ?? \"\").trim();\n    if (/^[a-z]{2}$/i.test(raw)) return raw.toUpperCase();\n    const normalized = searchable(raw);\n    if (!normalized) return void 0;\n    if (normalized === \"eg\" || normalized === \"egypt\" || normalized === \"\\u0645\\u0635\\u0631\") return \"EG\";\n    return gulf_countries_default.find(\n      (country) => normalized === country.code.toLowerCase() || normalized === searchable(country.ar) || normalized === searchable(country.en) || country.aliases.some((alias) => normalized === searchable(alias))\n    )?.code;\n  }\n  function countryFromText(text) {\n    if ([\"\\u0645\\u0635\\u0631\", \"egypt\", \"cairo\", \"\\u0627\\u0644\\u0642\\u0627\\u0647\\u0631\\u0647\", \"giza\", \"\\u0627\\u0644\\u062C\\u064A\\u0632\\u0647\", \"alexandria\", \"\\u0627\\u0644\\u0627\\u0633\\u0643\\u0646\\u062F\\u0631\\u064A\\u0647\"].some((term) => containsTerm(text, term))) return \"EG\";\n    return gulf_countries_default.find(\n      (country) => [country.ar, country.en, ...country.aliases].some((term) => containsTerm(text, term))\n    )?.code;\n  }\n  function countryFromPhone(phone) {\n    const value = String(phone ?? \"\").replace(/\\s/g, \"\");\n    if (value.startsWith(\"+20\")) return \"EG\";\n    return gulf_countries_default.find((country) => value.startsWith(country.dialCode))?.code;\n  }\n  function parseGeo(input) {\n    const locationText = searchable([input.governorate, input.city, input.address].filter(Boolean).join(\" \"));\n    const country = explicitCountryCode(input.country) ?? countryFromText(locationText) ?? countryFromPhone(input.phoneE164) ?? \"EG\";\n    const governorateMatch = country === \"EG\" ? eg_governorates_default.flatMap((candidate) => [candidate.ar, candidate.en, ...candidate.aliases].map((term) => ({ candidate, term }))).sort((left, right) => searchable(right.term).length - searchable(left.term).length).find(({ term }) => containsTerm(locationText, term)) : void 0;\n    const governorate = governorateMatch?.candidate;\n    const inferredCity = governorate ? [...governorate.aliases].filter((alias) => searchable(alias) !== searchable(governorate.ar) && searchable(alias) !== searchable(governorate.en)).sort((left, right) => searchable(right).length - searchable(left).length).find((alias) => containsTerm(locationText, alias)) : void 0;\n    const gulfCountry = gulf_countries_default.find((candidate) => candidate.code === country);\n    const zone = governorate?.zone ?? (gulfCountry ? \"GULF\" : country === \"EG\" ? \"REGIONAL\" : \"INTL\");\n    return {\n      country,\n      governorate: governorate ? { code: governorate.code, ar: governorate.ar, en: governorate.en } : null,\n      city: String(input.city ?? \"\").trim() || inferredCity || governorateMatch?.term || null,\n      zone\n    };\n  }\n  function run(items) {\n    return items.map((item) => {\n      const customer = item.json.customer ?? {};\n      const shipping = item.json.shipping ?? {};\n      const geo = parseGeo({\n        address: shipping.address ?? item.json.address,\n        city: shipping.city ?? item.json.city,\n        governorate: shipping.governorate ?? item.json.governorate,\n        country: shipping.country ?? item.json.country,\n        phoneE164: customer.phoneE164 ?? item.json.phoneE164\n      });\n      return { ...item, json: { ...item.json, geo } };\n    });\n  }\n\n  // geo.bundle-entry.ts\n  __smartCodRun = run;\n})();\nreturn __smartCodRun($input.all(), { now: new Date().toISOString() });"
      },
      "id": "wf03b-address-geo",
      "name": "Parse New Address Geo-Location",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3520,
        580
      ]
    },
    {
      "parameters": {
        "jsCode": "let __smartCodRun;\n(() => {\n  // n8n/code/carrier-route.ts\n  var DEFAULT_ZONE_RULES = {\n    METRO: { carrier: \"BOSTA\", service: \"BOSTA EXPRESS METRO\" },\n    REGIONAL: { carrier: \"ARAMEX\", service: \"ARAMEX REGIONAL\" },\n    GULF: { carrier: \"DHL\", service: \"DHL GULF EXPRESS\" },\n    INTL: { carrier: \"DHL\", service: \"DHL INTERNATIONAL\" }\n  };\n  function routeCarrier(zone, rules = DEFAULT_ZONE_RULES) {\n    const route = rules[zone];\n    if (!route) throw new Error(`No carrier route configured for zone ${zone}`);\n    return { zone, ...route };\n  }\n  function run(items) {\n    return items.map((item) => {\n      const geo = item.json.geo ?? {};\n      const settings = item.json.settings ?? {};\n      const rules = settings.zoneRules ?? DEFAULT_ZONE_RULES;\n      const route = routeCarrier(String(geo.zone ?? item.json.zone), rules);\n      return { ...item, json: { ...item.json, route } };\n    });\n  }\n\n  // carrier-route.bundle-entry.ts\n  __smartCodRun = run;\n})();\nreturn __smartCodRun($input.all(), { now: new Date().toISOString() });"
      },
      "id": "wf03b-address-route",
      "name": "Re-Route Carrier for New Address",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3760,
        580
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/orders/{{ $json.decisionContext.order.id }}/address",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ addressLine: $json.shipping.address, city: $json.geo.city, governorate: $json.geo.governorate?.ar || $json.geo.city, country: $json.geo.country, zone: $json.geo.zone, carrier: $json.route.carrier, carrierService: $json.route.service }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-address-update",
      "name": "Update Order Address",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        4000,
        580
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/customers/{{ $('Restore Conversation Context').item.json.customer.id }}/pending-action",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ action: 'NONE' }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-address-reset",
      "name": "Clear Address Conversation State",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        4240,
        580
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.INTERNAL_API_URL }}/api/internal/orders/{{ $json.order.id }}/transition",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ to: 'NEEDS_REVIEW', reason: 'AI_UNCLEAR', actor: 'ai', meta: { transcript: $json.inbound.transcript || $json.inbound.text, confidence: $json.analysis.confidence } }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "wf03b-unclear-transition",
      "name": "Flag Unclear Message for Review",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3020,
        800
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "credentials": {
        "httpHeaderAuth": {
          "id": "cred_internal_api",
          "name": "COD Internal API Bearer"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-escalate-audience",
              "name": "audience",
              "value": "admin",
              "type": "string"
            },
            {
              "id": "wf03b-escalate-channel",
              "name": "channel",
              "value": "auto",
              "type": "string"
            },
            {
              "id": "wf03b-escalate-template",
              "name": "template",
              "value": "review_alert",
              "type": "string"
            },
            {
              "id": "wf03b-escalate-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-escalate-vars",
              "name": "vars",
              "value": "={{ { orderId: $('Restore Decision Context').item.json.order.id, riskScore: $('Restore Decision Context').item.json.order.riskScore, transcript: $('Restore Decision Context').item.json.inbound.transcript || $('Restore Decision Context').item.json.inbound.text } }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-escalate-payload",
      "name": "Escalate Frustrated Customer to CS",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3260,
        40
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-escalate-send",
      "name": "Send Escalation to Admin",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3500,
        40
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-holding-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-holding-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-holding-template",
              "name": "template",
              "value": "holding_reply",
              "type": "string"
            },
            {
              "id": "wf03b-holding-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-holding-chat",
              "name": "chatId",
              "value": "={{ $('Restore Decision Context').item.json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-holding-order",
              "name": "orderId",
              "value": "={{ $('Restore Decision Context').item.json.order.id }}",
              "type": "string"
            },
            {
              "id": "wf03b-holding-vars",
              "name": "vars",
              "value": "={{ {} }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-holding-payload",
      "name": "Prepare Calm Holding Reply",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3260,
        120
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-holding-send",
      "name": "Send Calm Holding Reply",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3500,
        120
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-receipt-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-receipt-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-receipt-template",
              "name": "template",
              "value": "receipt",
              "type": "string"
            },
            {
              "id": "wf03b-receipt-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-receipt-chat",
              "name": "chatId",
              "value": "={{ $('Restore Decision Context').item.json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-receipt-order",
              "name": "orderId",
              "value": "={{ $('Restore Decision Context').item.json.order.id }}",
              "type": "string"
            },
            {
              "id": "wf03b-receipt-vars",
              "name": "vars",
              "value": "={{ { orderId: $('Restore Decision Context').item.json.order.id } }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-receipt-payload",
      "name": "Prepare Confirmation Receipt",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3260,
        220
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-receipt-send",
      "name": "Send Receipt",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3500,
        220
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-warehouse-audience",
              "name": "audience",
              "value": "admin",
              "type": "string"
            },
            {
              "id": "wf03b-warehouse-channel",
              "name": "channel",
              "value": "auto",
              "type": "string"
            },
            {
              "id": "wf03b-warehouse-template",
              "name": "template",
              "value": "warehouse_packing_slip",
              "type": "string"
            },
            {
              "id": "wf03b-warehouse-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-warehouse-vars",
              "name": "vars",
              "value": "={{ { orderId: $('Restore Decision Context').item.json.order.id, items: $('Restore Decision Context').item.json.order.items.map(item => item.sku + ' × ' + item.qty).join('، '), labelUrl: $env.APP_PUBLIC_URL + '/awb/' + $('Restore Decision Context').item.json.order.id } }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-warehouse-payload",
      "name": "Alert Warehouse Packing Slip",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3260,
        280
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-warehouse-send",
      "name": "Send Warehouse Alert",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3500,
        280
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-retention-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-retention-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-retention-template",
              "name": "template",
              "value": "retention_offer",
              "type": "string"
            },
            {
              "id": "wf03b-retention-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-retention-chat",
              "name": "chatId",
              "value": "={{ $('Restore Decision Context').item.json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-retention-order",
              "name": "orderId",
              "value": "={{ $('Restore Decision Context').item.json.order.id }}",
              "type": "string"
            },
            {
              "id": "wf03b-retention-vars",
              "name": "vars",
              "value": "={{ { orderId: $('Restore Decision Context').item.json.order.id, discountPercent: $('Restore Decision Context').item.json.settings.retention.discountPercent } }}",
              "type": "object"
            },
            {
              "id": "wf03b-retention-buttons",
              "name": "buttons",
              "value": "={{ [{ text: 'موافق', callbackData: 'ret:accept:' + $('Restore Decision Context').item.json.order.id }, { text: 'لا، إلغاء', callbackData: 'ret:decline:' + $('Restore Decision Context').item.json.order.id }] }}",
              "type": "array"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-retention-payload",
      "name": "Dispatch Discount Offer",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3500,
        360
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-retention-send",
      "name": "Send Retention Offer",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3740,
        360
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-cancel-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-cancel-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-cancel-template",
              "name": "template",
              "value": "cancellation",
              "type": "string"
            },
            {
              "id": "wf03b-cancel-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-cancel-chat",
              "name": "chatId",
              "value": "={{ $('Restore Decision Context').item.json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-cancel-order",
              "name": "orderId",
              "value": "={{ $('Restore Decision Context').item.json.order.id }}",
              "type": "string"
            },
            {
              "id": "wf03b-cancel-vars",
              "name": "vars",
              "value": "={{ { orderId: $('Restore Decision Context').item.json.order.id } }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-cancel-payload",
      "name": "Prepare Cancellation Notice",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3500,
        480
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-cancel-send",
      "name": "Send Cancellation Notice",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3740,
        480
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-request-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-request-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-request-template",
              "name": "template",
              "value": "address_request",
              "type": "string"
            },
            {
              "id": "wf03b-request-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-request-chat",
              "name": "chatId",
              "value": "={{ $('Restore Decision Context').item.json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-request-order",
              "name": "orderId",
              "value": "={{ $('Restore Decision Context').item.json.order.id }}",
              "type": "string"
            },
            {
              "id": "wf03b-request-vars",
              "name": "vars",
              "value": "={{ { orderId: $('Restore Decision Context').item.json.order.id } }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-address-request-payload",
      "name": "Prepare Address Request",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3500,
        700
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-address-request-send",
      "name": "Send Address Request",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3740,
        700
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-address-confirm-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-address-confirm-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-address-confirm-template",
              "name": "template",
              "value": "address_confirmation",
              "type": "string"
            },
            {
              "id": "wf03b-address-confirm-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-address-confirm-chat",
              "name": "chatId",
              "value": "={{ $('Restore Conversation Context').item.json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-address-confirm-order",
              "name": "orderId",
              "value": "={{ $('Restore Conversation Context').item.json.order.id }}",
              "type": "string"
            },
            {
              "id": "wf03b-address-confirm-vars",
              "name": "vars",
              "value": "={{ { orderId: $('Restore Conversation Context').item.json.order.id, address: $('Update Order Address').item.json.order.addressLine } }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-address-confirm-payload",
      "name": "Prepare Address Confirmation",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        4480,
        580
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-address-confirm-send",
      "name": "Send Address Confirmation",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        4720,
        580
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "wf03b-question-audience",
              "name": "audience",
              "value": "customer",
              "type": "string"
            },
            {
              "id": "wf03b-question-channel",
              "name": "channel",
              "value": "telegram",
              "type": "string"
            },
            {
              "id": "wf03b-question-template",
              "name": "template",
              "value": "question_reply",
              "type": "string"
            },
            {
              "id": "wf03b-question-language",
              "name": "language",
              "value": "ar",
              "type": "string"
            },
            {
              "id": "wf03b-question-chat",
              "name": "chatId",
              "value": "={{ $json.inbound.chatId }}",
              "type": "string"
            },
            {
              "id": "wf03b-question-order",
              "name": "orderId",
              "value": "={{ $json.order.id }}",
              "type": "string"
            },
            {
              "id": "wf03b-question-vars",
              "name": "vars",
              "value": "={{ { reply: $json.analysis.reply_ar } }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "wf03b-question-payload",
      "name": "Prepare FAQ-Grounded Reply",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3020,
        720
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "CODWF00SendNotification",
          "mode": "id"
        },
        "mode": "once",
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "id": "wf03b-question-send",
      "name": "Send Customer Question Reply",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        3260,
        760
      ]
    }
  ],
  "connections": {
    "Customer Message Request": {
      "main": [
        [
          {
            "node": "Normalize to InboundMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Test Inbound Webhook": {
      "main": [
        [
          {
            "node": "Test Hooks Enabled & Authorized?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Test Hooks Enabled & Authorized?": {
      "main": [
        [
          {
            "node": "Normalize to InboundMessage",
            "type": "main",
            "index": 0
          },
          {
            "node": "Respond Test Accepted",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Test Hook Unavailable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize to InboundMessage": {
      "main": [
        [
          {
            "node": "Fetch Customer & Open Order",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Customer & Open Order": {
      "main": [
        [
          {
            "node": "Fetch Order & FAQ Settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Order & FAQ Settings": {
      "main": [
        [
          {
            "node": "Merge Conversation & Order Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Conversation & Order Context": {
      "main": [
        [
          {
            "node": "Log Conversation Entry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Conversation Entry": {
      "main": [
        [
          {
            "node": "Restore Conversation Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Restore Conversation Context": {
      "main": [
        [
          {
            "node": "Pending-Action Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pending-Action Switch": {
      "main": [
        [
          {
            "node": "Prepare Pending New Address",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Callback or AI Router",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Pending New Address": {
      "main": [
        [
          {
            "node": "Parse New Address Geo-Location",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Callback or AI Router": {
      "main": [
        [
          {
            "node": "Process Button Action Direct",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Canned Test Analysis?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Button Action Direct": {
      "main": [
        [
          {
            "node": "Callback Owns Open Order?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Callback Owns Open Order?": {
      "main": [
        [
          {
            "node": "Map Callback to Trusted Intent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Reject Forged Callback",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Reject Forged Callback": {
      "main": [
        [
          {
            "node": "Send Forged Action Rejection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Callback to Trusted Intent": {
      "main": [
        [
          {
            "node": "Merge Order & AI Intent Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Canned Test Analysis?": {
      "main": [
        [
          {
            "node": "Use Canned Structured Analysis",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Use Canned Structured Analysis": {
      "main": [
        [
          {
            "node": "Merge Order & AI Intent Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Normalize Structured AI Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Structured AI Output": {
      "main": [
        [
          {
            "node": "Merge Order & AI Intent Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Order & AI Intent Context": {
      "main": [
        [
          {
            "node": "Log Intent, Sentiment & Confidence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Intent, Sentiment & Confidence": {
      "main": [
        [
          {
            "node": "Restore Decision Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Restore Decision Context": {
      "main": [
        [
          {
            "node": "Angry Customer Sentiment Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Angry Customer Sentiment Filter": {
      "main": [
        [
          {
            "node": "Flag Angry Customer for Review",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Intent Decision Final Router",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flag Angry Customer for Review": {
      "main": [
        [
          {
            "node": "Escalate Frustrated Customer to CS",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Calm Holding Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Escalate Frustrated Customer to CS": {
      "main": [
        [
          {
            "node": "Send Escalation to Admin",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Calm Holding Reply": {
      "main": [
        [
          {
            "node": "Send Calm Holding Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Intent Decision Final Router": {
      "main": [
        [
          {
            "node": "Transition CONFIRMED",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Sales Retention Negotiator",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "New Address Included?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare FAQ-Grounded Reply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Flag Unclear Message for Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transition CONFIRMED": {
      "main": [
        [
          {
            "node": "Prepare Confirmation Receipt",
            "type": "main",
            "index": 0
          },
          {
            "node": "Alert Warehouse Packing Slip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Confirmation Receipt": {
      "main": [
        [
          {
            "node": "Send Receipt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alert Warehouse Packing Slip": {
      "main": [
        [
          {
            "node": "Send Warehouse Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sales Retention Negotiator": {
      "main": [
        [
          {
            "node": "Apply Retention Discount",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Transition CANCELLED",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Apply Retention Discount": {
      "main": [
        [
          {
            "node": "Dispatch Discount Offer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dispatch Discount Offer": {
      "main": [
        [
          {
            "node": "Send Retention Offer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transition CANCELLED": {
      "main": [
        [
          {
            "node": "Prepare Cancellation Notice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Cancellation Notice": {
      "main": [
        [
          {
            "node": "Send Cancellation Notice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Address Included?": {
      "main": [
        [
          {
            "node": "Prepare Inline New Address",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set AWAIT_ADDRESS State",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set AWAIT_ADDRESS State": {
      "main": [
        [
          {
            "node": "Prepare Address Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Address Request": {
      "main": [
        [
          {
            "node": "Send Address Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Inline New Address": {
      "main": [
        [
          {
            "node": "Parse New Address Geo-Location",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse New Address Geo-Location": {
      "main": [
        [
          {
            "node": "Re-Route Carrier for New Address",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Re-Route Carrier for New Address": {
      "main": [
        [
          {
            "node": "Update Order Address",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Order Address": {
      "main": [
        [
          {
            "node": "Clear Address Conversation State",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clear Address Conversation State": {
      "main": [
        [
          {
            "node": "Prepare Address Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Address Confirmation": {
      "main": [
        [
          {
            "node": "Send Address Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare FAQ-Grounded Reply": {
      "main": [
        [
          {
            "node": "Send Customer Question Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flag Unclear Message for Review": {
      "main": [
        [
          {
            "node": "Escalate Frustrated Customer to CS",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Calm Holding Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "errorWorkflow": "CODWF99ErrorHandler",
    "timezone": "Africa/Cairo"
  },
  "versionId": "f03b0000-0000-4000-8000-000000000000",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "tags": []
}
