{
  "name": "AI Trial Manager (Gmail \u2192 Gemini \u2192 HITL \u2192 Calendar)",
  "nodes": [
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "authentication": "serviceAccount",
        "filters": {
          "readStatus": "unread"
        }
      },
      "id": "node-gmail-trigger",
      "name": "Gmail Trigger \u2014 Poll Inbox",
      "type": "n8n-nodes-base.gmailTrigger",
      "typeVersion": 1.2,
      "position": [
        -832,
        -192
      ],
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "cfg-app-url",
              "name": "app_url",
              "value": "https://YOUR_APP_DOMAIN",
              "type": "string"
            },
            {
              "id": "cfg-secret",
              "name": "webhook_secret",
              "value": "YOUR_WEBHOOK_SECRET",
              "type": "string"
            },
            {
              "id": "cfg-admin-email",
              "name": "admin_email",
              "value": "YOUR_ADMIN_EMAIL",
              "type": "string"
            },
            {
              "id": "cfg-telegram-admin-chat",
              "name": "telegram_admin_chat_id",
              "value": "YOUR_ADMIN_TELEGRAM_CHAT_ID",
              "type": "string"
            },
            {
              "id": "cfg-telegram-group-chat",
              "name": "telegram_group_chat_id",
              "value": "YOUR_TELEGRAM_GROUP_CHAT_ID",
              "type": "string"
            },
            {
              "id": "cfg-bot-token",
              "name": "telegram_bot_token",
              "value": "YOUR_TELEGRAM_BOT_TOKEN",
              "type": "string"
            },
            {
              "id": "cfg-gemini-key",
              "name": "gemini_api_key",
              "value": "YOUR_GEMINI_API_KEY",
              "type": "string"
            },
            {
              "id": "cfg-coaches-topic",
              "name": "coaches_topic_id",
              "value": "YOUR_COACHES_TOPIC_ID",
              "type": "string"
            },
            {
              "id": "cfg-tournament-topic",
              "name": "tournament_topic_id",
              "value": "YOUR_TOURNAMENT_TOPIC_ID",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "node-config",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -608,
        -192
      ]
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "sendTo": "={{ $json.from.value[0].address }}",
        "subject": "RE: {{ $json.subject }}",
        "message": "Thank you for contacting us!\n\nWe have received your message and our team will review it shortly. You will receive a follow-up within 24 hours.\n\nBest regards,\n[YOUR ORGANIZATION NAME]",
        "options": {}
      },
      "id": "node-autoreply",
      "name": "Auto-Reply \u2014 Acknowledge",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        -400,
        -352
      ],
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "x-goog-api-key",
              "value": "={{ $('Config').item.json.gemini_api_key }}"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ contents: [{ parts: [{ text: 'Analyze the following email and extract structured data.\\n\\nEmail Subject: ' + $('Gmail Trigger \u2014 Poll Inbox').item.json.subject + '\\nEmail From: ' + $('Gmail Trigger \u2014 Poll Inbox').item.json.from.value[0].address + '\\nEmail Body:\\n' + ($('Gmail Trigger \u2014 Poll Inbox').item.json.text || $('Gmail Trigger \u2014 Poll Inbox').item.json.html || '') + '\\n\\nExtract the following fields as JSON:\\n- player_name: The name of the player (if mentioned)\\n- age_group: The age group \u2014 infer from age or date of birth if possible\\n- intent: One of \"trial\", \"fixture\", \"general_inquiry\", \"registration\", \"complaint\"\\n- parent_name: The parent/guardian name (if mentioned)\\n- parent_phone: Phone number (if mentioned)\\n- parent_email: Email address (use the From address if no other is specified)\\n- summary: A 1-2 sentence summary of the request\\n- urgency: \"high\", \"medium\", or \"low\"\\n\\nReturn ONLY valid JSON, no markdown fences.' }] }], generationConfig: { temperature: 0.1, maxOutputTokens: 500 } }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-gemini",
      "name": "Gemini \u2014 Extract Info",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -400,
        -32
      ]
    },
    {
      "parameters": {
        "jsCode": "const response = $('Gemini \u2014 Extract Info').item.json;\n\nlet raw = '';\ntry { raw = response.candidates[0].content.parts[0].text || ''; } catch (e) { raw = ''; }\n\nlet parsed;\ntry {\n  const cleaned = raw.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n  parsed = JSON.parse(cleaned);\n} catch (e) {\n  parsed = {\n    player_name: 'Unknown',\n    age_group: 'Unknown',\n    intent: 'general_inquiry',\n    parent_name: 'Unknown',\n    parent_email: $('Gmail Trigger \u2014 Poll Inbox').item.json.from.value[0].address,\n    summary: 'Could not parse email automatically',\n    urgency: 'medium'\n  };\n}\n\nconst originalEmail = $('Gmail Trigger \u2014 Poll Inbox').item.json;\n\nreturn {\n  json: {\n    ...parsed,\n    original_subject: originalEmail.subject,\n    original_from: originalEmail.from.value[0].address,\n    original_date: originalEmail.date,\n    gmail_message_id: originalEmail.id\n  }\n};"
      },
      "id": "node-parse-ai",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -176,
        -32
      ]
    },
    {
      "parameters": {
        "url": "={{ $('Config').item.json.app_url }}/api/calendar/availability",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "start",
              "value": "={{ $now.plus(2, 'days').startOf('day').plus(9, 'hours').toISO() }}"
            },
            {
              "name": "end",
              "value": "={{ $now.plus(2, 'days').startOf('day').plus(11, 'hours').toISO() }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-cal-check",
      "name": "Check Calendar Availability",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        48,
        -32
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "jsCode": "const ai = $('Parse AI Response').item.json;\nconst cal = $('Check Calendar Availability').item.json;\nconst config = $('Config').item.json;\n\nconst available = cal.available !== false;\nconst conflicts = cal.conflicts || [];\n\nlet calendarNote = available\n  ? '\u2705 Next available slot: Day after tomorrow, 9:00-11:00 AM'\n  : '\u26a0\ufe0f Calendar conflict: ' + conflicts.map(c => c.summary).join(', ');\n\nconst reviewMessage = [\n  '\ud83d\udce9 <b>New Trial/Inquiry Request</b>',\n  '',\n  `<b>Intent:</b> ${ai.intent}`,\n  `<b>Player:</b> ${ai.player_name || 'Not specified'}`,\n  `<b>Age Group:</b> ${ai.age_group || 'Not specified'}`,\n  `<b>Parent:</b> ${ai.parent_name || 'Not specified'}`,\n  `<b>Email:</b> ${ai.original_from}`,\n  `<b>Phone:</b> ${ai.parent_phone || 'Not specified'}`,\n  '',\n  `<b>Summary:</b> ${ai.summary}`,\n  `<b>Urgency:</b> ${ai.urgency}`,\n  '',\n  `<b>Calendar:</b> ${calendarNote}`,\n  '',\n  '\ud83d\udc47 <b>Reply with:</b>',\n  '<code>/approve</code> \u2014 Create calendar event + send confirmation',\n  '<code>/reject</code> \u2014 Send polite decline email'\n].join('\\n');\n\nreturn {\n  json: {\n    reviewMessage,\n    aiData: ai,\n    calendarAvailable: available,\n    calendarNote\n  }\n};"
      },
      "id": "node-build-review",
      "name": "Build Review Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        272,
        -32
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: $('Config').item.json.telegram_admin_chat_id, text: $json.reviewMessage, parse_mode: 'HTML' }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-send-hitl",
      "name": "Send to Admin \u2014 Telegram HITL",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        496,
        -32
      ]
    },
    {
      "parameters": {},
      "id": "node-hitl-wait",
      "name": "HITL \u2014 Wait for Decision",
      "type": "n8n-nodes-base.form",
      "typeVersion": 2.2,
      "position": [
        720,
        -32
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false
          },
          "conditions": [
            {
              "id": "check-approve",
              "leftValue": "={{ $json.Decision }}",
              "rightValue": "approve",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "node-approved",
      "name": "Approved?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        928,
        -32
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $('Config').item.json.app_url }}/api/calendar",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ summary: 'Trial \u2014 ' + ($('Build Review Message').item.json.aiData.player_name || 'New Player') + ' (' + ($('Build Review Message').item.json.aiData.age_group || 'TBD') + ')', description: 'Trial request from ' + $('Build Review Message').item.json.aiData.original_from, location: 'Training Ground', startTime: ($json['Preferred Date'] || $now.plus(2, 'days').toISODate()) + 'T' + ($json['Preferred Time'] || '09:00') + ':00.000+04:00', endTime: ($json['Preferred Date'] || $now.plus(2, 'days').toISODate()) + 'T' + ($json['Preferred Time'] ? String(Number($json['Preferred Time'].split(':')[0]) + 2).padStart(2, '0') + ':00' : '11:00') + ':00.000+04:00', checkAvailability: true }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-create-cal",
      "name": "Create Calendar Event",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1152,
        -160
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "sendTo": "={{ $('Build Review Message').item.json.aiData.original_from }}",
        "subject": "[YOUR ORG] \u2014 Your Trial Session is Confirmed!",
        "message": "=Dear {{ $('Build Review Message').item.json.aiData.parent_name || 'Parent/Guardian' }},\n\nGreat news! We're happy to confirm a trial session for {{ $('Build Review Message').item.json.aiData.player_name || 'your child' }}.\n\n\ud83d\udcc5 Date: {{ $('HITL \u2014 Wait for Decision').item.json['Preferred Date'] || 'To be confirmed' }}\n\u23f0 Time: {{ $('HITL \u2014 Wait for Decision').item.json['Preferred Time'] || '9:00 AM' }}\n\ud83d\udccd Location: Training Ground\n\nPlease bring comfortable sportswear and a water bottle.\n\nBest regards,\n[YOUR ORGANIZATION NAME]",
        "options": {}
      },
      "id": "node-confirm-email",
      "name": "Send Confirmation Email",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1376,
        -160
      ],
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "sendTo": "={{ $('Build Review Message').item.json.aiData.original_from }}",
        "subject": "RE: {{ $('Build Review Message').item.json.aiData.original_subject }}",
        "message": "=Dear {{ $('Build Review Message').item.json.aiData.parent_name || 'Parent/Guardian' }},\n\nThank you for your interest.\n\nUnfortunately, we are unable to accommodate your request at this time.\n\nPlease don't hesitate to reach out again in the future.\n\nBest regards,\n[YOUR ORGANIZATION NAME]",
        "options": {}
      },
      "id": "node-reject-email",
      "name": "Send Rejection Email",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1152,
        96
      ],
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: $('Config').item.json.telegram_admin_chat_id, text: '\u2705 Trial APPROVED for ' + ($('Build Review Message').item.json.aiData.player_name || 'Unknown') + '. Calendar event created. Confirmation email sent.', parse_mode: 'HTML' }) }}",
        "options": {}
      },
      "id": "node-notify-approved",
      "name": "Notify Admin \u2014 Approved",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1600,
        -160
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: $('Config').item.json.telegram_admin_chat_id, text: '\u274c Trial REJECTED for ' + ($('Build Review Message').item.json.aiData.player_name || 'Unknown') + '. Decline email sent.', parse_mode: 'HTML' }) }}",
        "options": {}
      },
      "id": "node-notify-rejected",
      "name": "Notify Admin \u2014 Rejected",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1376,
        96
      ],
      "continueOnFail": true
    }
  ],
  "connections": {
    "Gmail Trigger \u2014 Poll Inbox": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Auto-Reply \u2014 Acknowledge",
            "type": "main",
            "index": 0
          },
          {
            "node": "Gemini \u2014 Extract Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini \u2014 Extract Info": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Check Calendar Availability",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Calendar Availability": {
      "main": [
        [
          {
            "node": "Build Review Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Review Message": {
      "main": [
        [
          {
            "node": "Send to Admin \u2014 Telegram HITL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Approved?": {
      "main": [
        [
          {
            "node": "Create Calendar Event",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Rejection Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Calendar Event": {
      "main": [
        [
          {
            "node": "Send Confirmation Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Confirmation Email": {
      "main": [
        [
          {
            "node": "Notify Admin \u2014 Approved",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Rejection Email": {
      "main": [
        [
          {
            "node": "Notify Admin \u2014 Rejected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "tags": [
    {
      "name": "AI"
    },
    {
      "name": "Email"
    },
    {
      "name": "HITL"
    },
    {
      "name": "Telegram"
    }
  ]
}