"""Crea los 2 workflows de producción: verificación GET + agente POST."""
import json, urllib.request, os

API_KEY = os.environ.get("N8N_API_KEY", "")
BASE    = os.environ.get("N8N_BASE_URL", "http://localhost:5678") + "/api/v1"

id_get_prices    = "7hqeTzIe0iN8nEWh"
id_calc_budget   = "CtTIxulOODx8sPcI"
id_qualify       = "ohSMGhfOv08HsEho"
id_escalate      = "esagSy5x4KqXwwxg"
id_analyze_image = "C7FECW87O0StCRWj"
id_transcribe    = "0Yl4HMeBE6HYRazG"
id_render        = "Vlt2XlDqvGxGREur"
id_budget        = "oyDupIJSrT27ArTe"

VERIFY_TOKEN    = os.environ.get("META_VERIFY_TOKEN", "")
PHONE_NUMBER_ID = os.environ.get("META_PHONE_NUMBER_ID", "")
META_TOKEN      = os.environ.get("META_TOKEN", "")

SYSTEM_PROMPT = (
    "Sos Richard, el asistente comercial de Fibromuebles. "
    "Fabrica de muebles a medida en MDF y melamina, Bahia Blanca, Argentina (Corrientes 289).\n\n"
    "## Tu personalidad\n"
    "- Hablas en castellano argentino coloquial. Usas 'che', 'dale', 'te cuento'.\n"
    "- Directo y concreto. Sin frases serviles.\n"
    "- Mensajes cortos: maximo 4 lineas.\n"
    "- Si te preguntan si sos IA, decis que sos del equipo de Fibromuebles.\n\n"
    "## Tu objetivo\n"
    "Entender que necesita el cliente, deducir cortes, calcular solo de forma interna y crear nota privada para Edd.\n\n"
    "## Como calcular\n"
    "Antes de llamar a calculate_budget, identifica cada pieza del mueble.\n"
    "Placard: 2 laterales + techo + piso + fondo 3mm + zocalo pino + estantes + puertas + cajones.\n"
    "Bajo mesada: 2 laterales + piso + zocalos superiores. Alto 90cm, prof 60cm.\n"
    "Cajones: 2 laterales + 2 contrafrentes + frente visible + fondo 3mm blanco + 1 telescopica.\n"
    "Puertas batientes: max 50cm ancho. Cazoletas: 2 si alto<=100cm, 3 si <=180cm, 4 si >180cm.\n"
    "Puertas corredizas: max 120cm recomendado, llevan manijon de aluminio.\n\n"
    "## Herramientas disponibles\n"
    "- get_prices: precios actualizados. Sin parametros.\n"
    "- calculate_budget: calcula precio de UNA pieza. Enviar: tag, cant, a (ancho mm), b (alto mm), mat.\n"
    "  Tags: #Mueble, #Cajon, #Pino, #Herraje, #Adicional. Tags legacy #Medida-* migran a #Mueble.\n"
    "  Mat: 18b=melamina blanco 18mm / 18=MDF 18mm / 18c=color 18mm / 3b=blanco 3mm / 3=MDF 3mm.\n"
    "- qualify_lead: califica el lead. Enviar: phone, name, budget, location, urgency, product_interest, has_dimensions.\n"
    "- escalate_to_edd: escala a Edd. Enviar: phone, name, reason, summary.\n"
    "- analyze_image: analiza imagen. Enviar: media_url, media_type, context.\n"
    "- transcribe_audio: transcribe audio. Enviar: media_url, media_type, phone.\n"
    "- generate_render: genera render. Enviar: tipo_mueble, material, color, dimensiones, estilo, descripcion, ambiente.\n"
    "- prepare_budget_for_edelmar: crea nota privada. Enviar: conversation_id, cliente, mueble, medidas_cm, material, pieces, total_estimado, bloque_odoo.\n\n"
    "NUNCA des precio, rango ni valor de referencia al cliente. calculate_budget es solo interno y prepare_budget_for_edelmar crea nota privada.\n\n"
    "## Politica de precio privada\n"
    "Si el cliente no eligio material, pregunta una sola vez por MDF crudo, melamina blanca o melamina color. No calcules variantes publicas.\n\n"
    "## Cuando escalar a Edd\n"
    "- qualify_lead retorna score >= 6\n"
    "- El cliente quiere confirmar o cerrar un pedido\n"
    "- Reclamo con pedido anterior\n"
    "- Cliente fuera de Bahia Blanca pregunta por envio\n"
    "- Pedido complejo: cocina completa, local comercial, multiples ambientes\n"
    "- El cliente pide hablar con una persona\n"
    "Al escalar decir: 'Dale, te paso con Edd. Ya le mando tus datos y te contacta en el dia.'\n\n"
    "## Info del negocio\n"
    "- Materiales Faplac: MDF (3-25mm), Melamina blanca (3-18mm), Melamina color (18mm)\n"
    "- Entrega: MDF crudo 20 a 25 dias habiles; melamina 25 a 30 dias habiles desde la sena del 50%.\n"
    "- Flete en Bahia Blanca incluido. Para afuera, el cliente coordina comisionista.\n"
    "- Presupuesto valido 7 dias.\n"
)

EXTRACT_CODE = r"""
const body = $json.body;
const entry = body?.entry?.[0];
const change = entry?.changes?.[0];
const value = change?.value;
const msgs = value?.messages;

// Status updates (delivered, read) — ignorar
if (!msgs || msgs.length === 0) {
  return [{json: {skip: true, reason: 'no_message'}}];
}

const msg = msgs[0];
const from = msg.from;
const name = value.contacts?.[0]?.profile?.name || from;
const type = msg.type;

let input = '';
if (type === 'text') {
  input = msg.text.body;
} else if (type === 'image') {
  const caption = msg.image?.caption || '';
  input = caption ? '[imagen] ' + caption : '[imagen adjunta]';
} else if (type === 'audio') {
  input = '[nota de voz]';
} else {
  return [{json: {skip: true, reason: 'tipo_no_soportado_' + type}}];
}

return [{json: {
  input,
  from,
  name,
  type,
  sessionId: from,
  skip: false
}}];
"""

SEND_REPLY_CODE = (
    "const from = $('Extract Message').first().json.from;\n"
    "const rawOutput = $input.first().json.output || '[sin respuesta]';\n"
    "const output = rawOutput.length > 4000 ? rawOutput.substring(0, 4000) + '...' : rawOutput;\n"
    "const resp = await fetch(\n"
    f"  'https://graph.facebook.com/v18.0/{PHONE_NUMBER_ID}/messages',\n"
    "  {\n"
    "    method: 'POST',\n"
    "    headers: {\n"
    f"      'Authorization': 'Bearer {META_TOKEN}',\n"
    "      'Content-Type': 'application/json'\n"
    "    },\n"
    "    body: JSON.stringify({\n"
    "      messaging_product: 'whatsapp',\n"
    "      to: from,\n"
    "      type: 'text',\n"
    "      text: { body: output }\n"
    "    })\n"
    "  }\n"
    ");\n"
    "const result = await resp.json();\n"
    "return [{json: {...result, sent: resp.ok, status: resp.status}}];\n"
)


def api_post(path, data):
    body = json.dumps(data).encode()
    req = urllib.request.Request(BASE + path, data=body,
        headers={"X-N8N-API-KEY": API_KEY, "Content-Type": "application/json"})
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())


def api_post_empty(path):
    req = urllib.request.Request(BASE + path, data=b"{}",
        headers={"X-N8N-API-KEY": API_KEY, "Content-Type": "application/json"})
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())


# ─── Workflow 1: Verificación GET ───────────────────────────────────────────
print("Creando fibromuebles-webhook-verify (GET)...")
wf_verify = {
    "name": "fibromuebles-webhook-verify",
    "nodes": [
        {"id":"v1","name":"Webhook GET","type":"n8n-nodes-base.webhook","typeVersion":1,"position":[240,300],
         "parameters":{"httpMethod":"GET","path":"fibromuebles-whatsapp","responseMode":"lastNode","options":{}}},
        {"id":"v2","name":"Check Token","type":"n8n-nodes-base.if","typeVersion":1,"position":[460,300],
         "parameters":{"conditions":{"string":[{
             "value1":"={{ $json.query['hub.verify_token'] }}",
             "operation":"equal",
             "value2": VERIFY_TOKEN
         }]}}},
        {"id":"v3","name":"Respond Challenge","type":"n8n-nodes-base.respondToWebhook","typeVersion":1,"position":[680,200],
         "parameters":{"respondWith":"text","responseBody":"={{ $('Webhook GET').first().json.query['hub.challenge'] }}"}},
        {"id":"v4","name":"Respond Forbidden","type":"n8n-nodes-base.respondToWebhook","typeVersion":1,"position":[680,400],
         "parameters":{"respondWith":"text","responseCode":403,"responseBody":"Forbidden"}}
    ],
    "connections": {
        "Webhook GET":    {"main":[[{"node":"Check Token","type":"main","index":0}]]},
        "Check Token":    {"main":[
            [{"node":"Respond Challenge","type":"main","index":0}],
            [{"node":"Respond Forbidden","type":"main","index":0}]
        ]}
    },
    "settings":{"executionOrder":"v1"}
}

r = api_post("/workflows", wf_verify)
verify_id = r["id"]
print(f"Creado: {r['name']} -> ID: {verify_id}")
try:
    api_post_empty(f"/workflows/{verify_id}/activate")
    print("Activado.")
except Exception as e:
    print(f"No se pudo activar automáticamente: {e}")
    print("Activarlo manualmente en n8n UI.")


# ─── Workflow 2: Agente de producción (POST) ────────────────────────────────
print("\nCreando whatsapp-agent-fibromuebles (PRODUCCIÓN)...")
wf_prod = {
    "name": "whatsapp-agent-fibromuebles",
    "nodes": [
        {"id":"p1","name":"Webhook WhatsApp","type":"n8n-nodes-base.webhook","typeVersion":1,"position":[240,300],
         "parameters":{"httpMethod":"POST","path":"fibromuebles-whatsapp","responseMode":"lastNode","options":{}}},

        {"id":"p2","name":"Extract Message","type":"n8n-nodes-base.code","typeVersion":2,"position":[460,300],
         "parameters":{"jsCode": EXTRACT_CODE}},

        {"id":"p3","name":"Has Message?","type":"n8n-nodes-base.if","typeVersion":1,"position":[680,300],
         "parameters":{"conditions":{"boolean":[{"value1":"={{ $json.skip }}","value2":False}]}}},

        {"id":"p4","name":"Respond 200 Skip","type":"n8n-nodes-base.respondToWebhook","typeVersion":1,"position":[900,420],
         "parameters":{"respondWith":"text","responseBody":"OK"}},

        {"id":"p5","name":"Richard - AI Agent","type":"@n8n/n8n-nodes-langchain.agent","typeVersion":1,"position":[900,200],
         "retryOnFail": True, "maxTries": 3, "waitBetweenTries": 20000,
         "parameters":{
             "promptType":"define",
             "text":"={{ $json.input }}",
             "options":{"systemMessage": SYSTEM_PROMPT}
         }},

        {"id":"p6","name":"GPT-4.1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","typeVersion":1,"position":[780,440],
         "parameters":{"model":"gpt-4.1","options":{"maxTokens":500,"maxRetries":6,"temperature":0.2}}},

        {"id":"p7","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","typeVersion":1,"position":[920,440],
         "parameters":{
             "sessionKey":"={{ $('Extract Message').first().json.sessionId }}",
             "contextWindowLength":12
         }},

        {"id":"p8","name":"get_prices","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1060,440],
         "parameters":{"name":"get_prices","description":"Obtiene precios actualizados de materiales. Sin parametros.",
                       "workflowId":{"__rl":True,"value":id_get_prices,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p9","name":"calculate_budget","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1200,440],
         "parameters":{"name":"calculate_budget","description":"Calcula precio de una pieza. Parametros: tag, cant, a (ancho mm), b (alto mm), mat.",
                       "workflowId":{"__rl":True,"value":id_calc_budget,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p10","name":"qualify_lead","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1340,440],
         "parameters":{"name":"qualify_lead","description":"Califica el lead (score 0-10). Parametros: phone, name, budget, location, urgency, product_interest, has_dimensions.",
                       "workflowId":{"__rl":True,"value":id_qualify,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p11","name":"escalate_to_edd","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1480,440],
         "parameters":{"name":"escalate_to_edd","description":"Escala a Edd. Parametros: phone, name, reason, summary.",
                       "workflowId":{"__rl":True,"value":id_escalate,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p12","name":"analyze_image","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1060,560],
         "parameters":{"name":"analyze_image","description":"Analiza imagen del cliente. Parametros: media_url, media_type, context.",
                       "workflowId":{"__rl":True,"value":id_analyze_image,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p13","name":"transcribe_audio","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1200,560],
         "parameters":{"name":"transcribe_audio","description":"Transcribe audio del cliente. Parametros: media_url, media_type, phone.",
                       "workflowId":{"__rl":True,"value":id_transcribe,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p14","name":"generate_render","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1340,560],
         "parameters":{"name":"generate_render","description":"Genera render del mueble. Parametros: tipo_mueble, material, color, dimensiones, estilo, descripcion, ambiente.",
                       "workflowId":{"__rl":True,"value":id_render,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p15","name":"generate_budget","type":"@n8n/n8n-nodes-langchain.toolWorkflow","typeVersion":1.2,"position":[1480,560],
         "parameters":{"name":"generate_budget","description":"Genera presupuesto formateado para WhatsApp. Parametros: cliente, mueble, items, render_url, notas, tiempo_entrega.",
                       "workflowId":{"__rl":True,"value":id_budget,"mode":"id"},"fields":{"values":[]}}},

        {"id":"p16","name":"Send WhatsApp Reply","type":"n8n-nodes-base.code","typeVersion":2,"position":[1120,200],
         "parameters":{"jsCode": SEND_REPLY_CODE}},

        {"id":"p17","name":"Respond 200","type":"n8n-nodes-base.respondToWebhook","typeVersion":1,"position":[1340,200],
         "parameters":{"respondWith":"text","responseBody":"OK"}}
    ],
    "connections": {
        "Webhook WhatsApp":   {"main":[[{"node":"Extract Message","type":"main","index":0}]]},
        "Extract Message":    {"main":[[{"node":"Has Message?","type":"main","index":0}]]},
        "Has Message?":       {"main":[
            [{"node":"Richard - AI Agent","type":"main","index":0}],
            [{"node":"Respond 200 Skip","type":"main","index":0}]
        ]},
        "Richard - AI Agent": {"main":[[{"node":"Send WhatsApp Reply","type":"main","index":0}]]},
        "Send WhatsApp Reply":{"main":[[{"node":"Respond 200","type":"main","index":0}]]},
        "GPT-4.1":            {"ai_languageModel":[[{"node":"Richard - AI Agent","type":"ai_languageModel","index":0}]]},
        "Window Buffer Memory":{"ai_memory":[[{"node":"Richard - AI Agent","type":"ai_memory","index":0}]]},
        "get_prices":         {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":0}]]},
        "calculate_budget":   {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":1}]]},
        "qualify_lead":       {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":2}]]},
        "escalate_to_edd":    {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":3}]]},
        "analyze_image":      {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":4}]]},
        "transcribe_audio":   {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":5}]]},
        "generate_render":    {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":6}]]},
        "generate_budget":    {"ai_tool":[[{"node":"Richard - AI Agent","type":"ai_tool","index":7}]]}
    },
    "settings":{"executionOrder":"v1"}
}

r = api_post("/workflows", wf_prod)
prod_id = r["id"]
print(f"Creado: {r['name']} -> ID: {prod_id}")
try:
    api_post_empty(f"/workflows/{prod_id}/activate")
    print("Activado.")
except Exception as e:
    print(f"No se pudo activar automáticamente: {e}")
    print("Activarlo manualmente en n8n UI.")

print(f"\n{'='*50}")
print(f"IDs generados:")
print(f"  fibromuebles-webhook-verify : {verify_id}")
print(f"  whatsapp-agent-fibromuebles : {prod_id}")
print(f"\nURL del webhook para Meta:")
print(f"  https://n8n.edd-os.com.ar/webhook/fibromuebles-whatsapp")
print(f"\nVerify Token: {VERIFY_TOKEN}")
print(f"\nSi no se activaron automáticamente:")
print(f"  1. Abrí cada workflow en n8n UI")
print(f"  2. En 'GPT-4.1' asigná la credencial OpenAI")
print(f"  3. Activá con el toggle")
