#!/usr/bin/env python3
"""R1 - build lead_capture.n8n.json out of n8n_normalize_code.js.

Why this file exists
--------------------
n8n keeps a Code node's script inside the workflow file. This pack also ships
that same script as a .js file, so you can read it, edit it and diff it in a
normal editor. A build step is what stops those two copies from drifting
apart: change the .js, re-run this, and the workflow file holds the new text.
The test file in this folder asserts the two match, so a drift fails a test
instead of surprising you during a live order.

Run it from this folder:

    python3 build_workflow_json.py

What it does NOT do: it never opens a network connection, never talks to an
n8n instance, and never imports anything. The workflow is imported by a human
in the n8n web UI (SETUP.md, step 3). n8n is not installed on the machine this
pack was built on, so nothing here was executed by n8n; that limitation is
stated in RECIPE.md, and SETUP.md lists the five things to check on import.

Read-date: 2026-11-10. Stdlib only.
"""

from __future__ import annotations

import json
from pathlib import Path

HERE = Path(__file__).resolve().parent
CODE_FILE = HERE / "n8n_normalize_code.js"
OUT_FILE = HERE / "lead_capture.n8n.json"

WORKFLOW_NAME = "R1 lead capture: sheet row + Gmail draft (never a send)"

WEBHOOK_PATH = "back-office-lead"

# Stable, recognisable ids, so re-running this file produces the same bytes.
ID_WEBHOOK = "0f1e2d3c-0001-4a00-8000-000000000001"
ID_CODE = "0f1e2d3c-0002-4a00-8000-000000000002"
ID_SHEET = "0f1e2d3c-0003-4a00-8000-000000000003"
ID_GMAIL = "0f1e2d3c-0004-4a00-8000-000000000004"

SHEET_HEADER = ["receivedAt", "leadDate", "name", "email", "phone", "source", "message"]

DRAFT_MESSAGE = (
    "=Hi {{ $json.name ? $json.name.split(' ')[0] : 'there' }},\n\n"
    "Thanks for getting in touch{{ $json.source ? ' about ' + $json.source : '' }}. "
    "Your details are recorded and I will reply to this address.\n\n"
    "This is what arrived:\n"
    "{{ $json.message ? $json.message : '(nothing was written in the form)' }}"
)


def sheet_row_mapping() -> dict[str, str]:
    """The seven sheet columns and the item field each one is filled from."""
    return {column: f"={{{{ $json.{_field_of(column)} }}}}" for column in SHEET_HEADER}


def _field_of(column: str) -> str:
    """The item field behind a sheet column (they are already the same names)."""
    return column


def build(js_code: str) -> dict:
    """The whole workflow document, as the structure n8n imports."""
    return {
        "name": WORKFLOW_NAME,
        "nodes": [
            {
                "parameters": {
                    "httpMethod": "POST",
                    "path": WEBHOOK_PATH,
                    "responseMode": "onReceived",
                    "options": {},
                },
                "id": ID_WEBHOOK,
                "name": "New lead arrives",
                "type": "n8n-nodes-base.webhook",
                "typeVersion": 2,
                "position": [-400, 300],
                "webhookId": ID_WEBHOOK,
            },
            {
                "parameters": {"mode": "runOnceForAllItems", "jsCode": js_code},
                "id": ID_CODE,
                "name": "Normalize and check",
                "type": "n8n-nodes-base.code",
                "typeVersion": 2,
                "position": [-160, 300],
            },
            {
                "parameters": {
                    "operation": "append",
                    "documentId": {"__rl": True, "mode": "list", "value": "", "cachedResultName": ""},
                    "sheetName": {"__rl": True, "mode": "list", "value": "", "cachedResultName": ""},
                    "columns": {
                        "mappingMode": "defineBelow",
                        "value": sheet_row_mapping(),
                        "matchingColumns": [],
                        "schema": [],
                    },
                    "options": {},
                },
                "credentials": {"googleSheetsOAuth2Api": {"id": "", "name": "Google Sheets account"}},
                "id": ID_SHEET,
                "name": "Add the lead row",
                "type": "n8n-nodes-base.googleSheets",
                "typeVersion": 4.5,
                "position": [80, 300],
            },
            {
                "parameters": {
                    "resource": "draft",
                    "operation": "create",
                    "emailType": "to",
                    "sendTo": "={{ $json.email }}",
                    "subject": "=Re: your enquiry",
                    "message": DRAFT_MESSAGE,
                    "options": {},
                },
                "credentials": {"gmailOAuth2": {"id": "", "name": "Gmail account"}},
                "id": ID_GMAIL,
                "name": "Create the reply draft",
                "type": "n8n-nodes-base.gmail",
                "typeVersion": 2.1,
                "position": [320, 300],
            },
        ],
        "connections": {
            "New lead arrives": {
                "main": [[{"node": "Normalize and check", "type": "main", "index": 0}]]
            },
            "Normalize and check": {
                "main": [[{"node": "Add the lead row", "type": "main", "index": 0}]]
            },
            "Add the lead row": {
                "main": [[{"node": "Create the reply draft", "type": "main", "index": 0}]]
            },
        },
        "active": False,
        "settings": {"executionOrder": "v1"},
        "pinData": {},
        "meta": {
            "readDate": "2026-11-10",
            "recipe": "R1 of the Back-Office Autopilot pack",
            "note": (
                "The last node creates a Gmail DRAFT. Nothing in this workflow can send a "
                "message: a draft waits in the Drafts folder until a human opens it and "
                "presses send. Four values are yours to set - the two credentials, the "
                "spreadsheet and the tab. See SETUP.md."
            ),
        },
    }


def main() -> int:
    js_code = CODE_FILE.read_text(encoding="utf-8")
    document = build(js_code)
    OUT_FILE.write_text(
        json.dumps(document, indent=2, ensure_ascii=False) + "\n", encoding="utf-8"
    )
    print(f"wrote {OUT_FILE.name} ({OUT_FILE.stat().st_size} bytes) from {CODE_FILE.name}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
