from flask import Blueprint, request, render_template_string, jsonify, make_response
from datetime import datetime
import pymysql
import requests
import re
import os
import logging
import uuid
from logging.handlers import RotatingFileHandler
from dotenv import load_dotenv
from interaccion_planok import crear_lead_formulario_planok

load_dotenv()

# ============================================================
# LOG GENERAL
# ============================================================

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# ============================================================
# LOG ESPECÍFICO ENVÍO FORMULARIO
# Archivo: log_envioformulario.log
# ============================================================

LOG_DIR = os.path.dirname(os.path.abspath(__file__))
LOG_ENVIO_FORMULARIO_PATH = os.path.join(LOG_DIR, "log_envioformulario.log")

logger_formulario = logging.getLogger("log_envioformulario")
logger_formulario.setLevel(logging.INFO)
logger_formulario.propagate = False

if not logger_formulario.handlers:
    file_handler = RotatingFileHandler(
        LOG_ENVIO_FORMULARIO_PATH,
        maxBytes=5 * 1024 * 1024,
        backupCount=5,
        encoding="utf-8"
    )

    formatter = logging.Formatter(
        "%(asctime)s [%(levelname)s] %(message)s"
    )

    file_handler.setFormatter(formatter)
    logger_formulario.addHandler(file_handler)

formulario_widget_bp = Blueprint('formulario_widget', __name__)

DB_CONFIG = {
    'host': os.getenv('DB_HOST'),
    'user': os.getenv('DB_USER'),
    'password': os.getenv('DB_PASSWORD'),
    'database': os.getenv('DB_NAME'),
    'cursorclass': pymysql.cursors.DictCursor
}

CHATFUEL_TOKEN = os.getenv('CHATFUEL_TOKEN')
CHATFUEL_BOT_ID = os.getenv('CHATFUEL_BOT_ID')
CHATFUEL_URL = f"https://api.chatfuel.com/whatsapp/bots/{CHATFUEL_BOT_ID}/contacts?chatfuel_token={CHATFUEL_TOKEN}"
#CHATFUEL_URL = f"https://webhook.site/d2c96d92-7af0-4a63-8b7c-f6b0a507cba8"
FORMULARIO_PROYECTO_ID_DEFAULT = int(os.getenv("FORMULARIO_PROYECTO_ID", "17"))

FORM_HTML = """
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <style>
        body { background: transparent; overflow: hidden; font-family: sans-serif; }
        ::-webkit-scrollbar { width: 0px; background: transparent; }
    </style>
</head>
<body class="p-2">
    <form action="/api/widgets" method="POST" target="_top" class="flex flex-col gap-3 bg-white p-4 rounded-lg">
        <input type="hidden" name="telefono_destino" value="{{ telefono_destino }}">
        <input type="hidden" name="proyecto_id" value="{{ proyecto_id }}">
        <input type="hidden" name="proyecto" value="{{ proyecto }}">

        <div class="grid grid-cols-2 gap-2">
            <div>
                <label class="text-xs text-gray-700">Nombre</label>
                <input type="text" name="nombre" placeholder="Pablo" required
                       class="w-full border rounded p-1 text-sm bg-gray-50 focus:bg-white focus:border-green-500 outline-none">
            </div>
            <div>
                <label class="text-xs text-gray-700">Apellido</label>
                <input type="text" name="apellido" placeholder="Castro" required
                       class="w-full border rounded p-1 text-sm bg-gray-50 focus:bg-white focus:border-green-500 outline-none">
            </div>
        </div>

        <label class="text-xs text-gray-700">
            RUT
            <input type="text"
                   name="rut"
                   placeholder="16470532-3"
                   pattern="^[0-9]{7,8}-[0-9kK]{1}$"
                   title="Formato: 16470532-3"
                   required
                   class="w-full border rounded p-1 text-sm bg-gray-50 focus:bg-white focus:border-green-500 outline-none">
        </label>

        <label class="text-xs text-gray-700">
            Correo
            <input type="email" name="correo" placeholder="mail@ejemplo.com"
                   class="w-full border rounded p-1 text-sm bg-gray-50 focus:bg-white focus:border-green-500 outline-none">
        </label>

        <label class="text-xs text-gray-700">
            Teléfono
            <input type="text" name="telefono" placeholder="912345678" pattern="[0-9]{9}"
                   title="9 dígitos comenzando con 9" required
                   class="w-full border rounded p-1 text-sm bg-gray-50 focus:bg-white focus:border-green-500 outline-none">
        </label>

        <button type="submit"
                class="w-full bg-green-500 hover:bg-green-600 text-white font-bold py-2 rounded shadow transition duration-200 text-sm">
            💬 Ir a Chatear
        </button>
    </form>

    <script>
        const rutInput = document.querySelector('input[name="rut"]');

        if (rutInput) {
            rutInput.addEventListener("input", function () {
                let v = this.value;
                v = v.replace(/\\./g, '');
                v = v.replace(/[^0-9kK\\-]/g, '');
                this.value = v;
            });
        }
    </script>
</body>
</html>
"""


def normalize_phone(phone: str) -> str:
    d = re.sub(r'\D', '', phone or "")

    if d.startswith('0056'):
        d = d[4:]
    elif d.startswith('056'):
        d = d[3:]

    if re.fullmatch(r"9\d{8}", d):
        d = "56" + d

    if d and not d.startswith('56'):
        d = '56' + d

    return d


def normalize_rut(rut: str) -> str:
    rut = (rut or "").strip().upper()
    rut = rut.replace(".", "")
    rut = re.sub(r"[^0-9K\-]", "", rut)
    return rut


def validar_rut(rut: str) -> bool:
    rut = normalize_rut(rut)

    if not re.match(r'^[0-9]{7,8}-[0-9K]$', rut):
        return False

    num, dv = rut.split('-')

    suma = 0
    multiplo = 2

    for d in reversed(num):
        suma += int(d) * multiplo
        multiplo = multiplo + 1 if multiplo < 7 else 2

    resto = 11 - (suma % 11)

    if resto == 11:
        dv_calculado = "0"
    elif resto == 10:
        dv_calculado = "K"
    else:
        dv_calculado = str(resto)

    return dv_calculado == dv


def generar_message_id() -> str:
    return "web-" + uuid.uuid4().hex


def send_to_chatfuel_formulario(data: dict) -> bool:
    """
    Envía a Chatfuel inmediatamente después de guardar el formulario en la DB.
    Retorna True si Chatfuel responde 200, False en caso contrario.
    """
    message_id = data.get("message_id", "")

    if not CHATFUEL_TOKEN or not CHATFUEL_BOT_ID or CHATFUEL_TOKEN == "NO" or CHATFUEL_BOT_ID == "NO":
        logger_formulario.warning(
            f"[CHATFUEL OMITIDO] Chatfuel no configurado. message_id={message_id}"
        )
        logging.warning("Chatfuel no configurado (CHATFUEL_TOKEN/BOT_ID). Se omite envío.")
        return False

    phone = normalize_phone(data.get("telefono"))
    now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    rut_cliente = normalize_rut(data.get("Rut_cliente") or data.get("rut"))

    payload = {
        "phone": phone,
        "attributes": {
            "whatsapp_phone": phone,
            "crm Fecha_ingreso": now_str,
            "crm Hora_ingreso": now_str,
            "crm Rut_cliente": rut_cliente,
            "crm Nombre_cliente": data.get("nombre"),
            "crm Apellido_cliente": data.get("apellido"),
            "crm Email_cliente": data.get("correo"),
            "crm Proyecto": data.get("proyecto"),
            "crm Url_origen": data.get("url"),

            "medio_llegada_id": "3750",
            "medio_de_contacto": "CONILEAD.AI",

            "Activar_Contacto": "Formulario"
        },
        "invokeTriggers": True,
        "tagNames": ["Nuevo_Formulario"]
    }

    try:
        logger_formulario.info(
            f"[CHATFUEL INICIO] Enviando a Chatfuel. "
            f"message_id={message_id} phone={phone} proyecto={data.get('proyecto')}"
        )

        r = requests.post(
            CHATFUEL_URL,
            json=payload,
            headers={"Content-Type": "application/json"},
            timeout=12
        )

        if r.status_code == 200:
            logger_formulario.info(
                f"[CHATFUEL OK] message_id={message_id} status={r.status_code} response={r.text}"
            )
            logging.info(f"[OK] Enviado a Chatfuel (formulario): {r.text}")
            return True

        logger_formulario.error(
            f"[CHATFUEL ERROR] message_id={message_id} status={r.status_code} response={r.text}"
        )
        logging.error(f"[ERROR] Chatfuel {r.status_code}: {r.text}")
        return False

    except Exception as e:
        logger_formulario.exception(
            f"[CHATFUEL EXCEPTION] Falló envío a Chatfuel. message_id={message_id} error={e}"
        )
        logging.exception(f"[EXCEPTION] Envío a Chatfuel falló: {e}")
        return False


@formulario_widget_bp.after_request
def add_cors_headers(resp):
    origin = request.headers.get("Origin")
    resp.headers["Access-Control-Allow-Origin"] = origin if origin else "*"
    resp.headers["Vary"] = "Origin"
    resp.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
    resp.headers["Access-Control-Allow-Headers"] = "Content-Type, Accept"
    resp.headers["Access-Control-Max-Age"] = "86400"
    return resp


@formulario_widget_bp.route("/api/widget-view", methods=["GET"])
def widget_view():
    telefono_destino = request.args.get("telefono_destino", "")
    proyecto_id = request.args.get("proyecto_id", str(FORMULARIO_PROYECTO_ID_DEFAULT))
    proyecto = request.args.get("proyecto", "")

    return render_template_string(
        FORM_HTML,
        telefono_destino=telefono_destino,
        proyecto_id=proyecto_id,
        proyecto=proyecto
    )


@formulario_widget_bp.route("/api/widgets", methods=["POST", "OPTIONS"], strict_slashes=False)
def api_widgets():
    if request.method == "OPTIONS":
        return make_response("", 204)

    request_inicio = datetime.now()
    message_id = generar_message_id()

    logger_formulario.info(
        f"[REQUEST INICIO] endpoint=/api/widgets message_id={message_id} "
        f"ip={request.remote_addr} content_type={request.content_type}"
    )

    if request.is_json:
        data = request.get_json(silent=True) or {}
    else:
        data = request.form.to_dict() if request.form else {}

    try:
        data["message_id"] = message_id
        data["rut"] = normalize_rut(data.get("rut"))
        data["telefono"] = re.sub(r'\D', '', data.get("telefono", ""))
        data["proyecto_id"] = data.get("proyecto_id") or str(FORMULARIO_PROYECTO_ID_DEFAULT)

        logger_formulario.info(
            f"[DATOS RECIBIDOS] message_id={message_id} "
            f"nombre={data.get('nombre')} apellido={data.get('apellido')} "
            f"rut={data.get('rut')} telefono={data.get('telefono')} "
            f"correo={data.get('correo')} proyecto={data.get('proyecto')} "
            f"proyecto_id={data.get('proyecto_id')}"
        )

        if not data.get("nombre"):
            logger_formulario.warning(f"[VALIDACION ERROR] Falta nombre. message_id={message_id}")
            return jsonify({"success": False, "error": "Falta nombre"}), 400

        if not data.get("apellido"):
            logger_formulario.warning(f"[VALIDACION ERROR] Falta apellido. message_id={message_id}")
            return jsonify({"success": False, "error": "Falta apellido"}), 400

        if not data.get("rut"):
            logger_formulario.warning(f"[VALIDACION ERROR] Falta rut. message_id={message_id}")
            return jsonify({"success": False, "error": "Falta rut"}), 400

        if not validar_rut(data["rut"]):
            logger_formulario.warning(
                f"[VALIDACION ERROR] RUT inválido. message_id={message_id} rut={data.get('rut')}"
            )
            return jsonify({"success": False, "error": "RUT inválido"}), 400

        if not re.fullmatch(r"9\d{8}", data.get("telefono", "")):
            logger_formulario.warning(
                f"[VALIDACION ERROR] Teléfono inválido. message_id={message_id} telefono={data.get('telefono')}"
            )
            return jsonify({"success": False, "error": "Teléfono inválido"}), 400

        url_val = (data.get("url") or "").strip() or (request.headers.get("Referer") or "")
        data["url"] = url_val

        # ============================================================
        # 1) GUARDAR EN formulario_datos
        # ============================================================

        conn = None

        try:
            logger_formulario.info(
                f"[DB INICIO] Insertando formulario_datos. message_id={message_id}"
            )

            conn = pymysql.connect(**DB_CONFIG)

            with conn.cursor() as cursor:
                sql = """
                INSERT INTO formulario_datos (
                  message_id, asunto, nombre, proyecto, rut, correo, telefono,
                  fecha_registro, remitente, renta, apellido, url
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                """

                cursor.execute(sql, (
                    message_id,
                    data.get("asunto"),
                    data.get("nombre"),
                    data.get("proyecto"),
                    data.get("rut"),
                    data.get("correo"),
                    data.get("telefono"),
                    datetime.now(),
                    data.get("remitente") or "Formulario wp web",
                    data.get("renta"),
                    data.get("apellido"),
                    url_val
                ))

            conn.commit()

            logger_formulario.info(
                f"[DB OK] formulario_datos guardado correctamente. message_id={message_id}"
            )

        except Exception as e:
            if conn:
                conn.rollback()

            logger_formulario.exception(
                f"[DB ERROR] No se pudo guardar formulario_datos. "
                f"message_id={message_id} error={e}"
            )

            raise

        finally:
            if conn:
                conn.close()

        # ============================================================
        # 2) SI SE GUARDÓ EN formulario_datos, CREAR LEAD PLANOK
        # ============================================================

        planok_ok = False

        try:
            logger_formulario.info(
                f"[PLANOK INICIO] Ejecutando crear_lead_formulario_planok. "
                f"message_id={message_id} telefono={data.get('telefono')} rut={data.get('rut')}"
            )

            resultado_planok = crear_lead_formulario_planok(
                nombre=data.get("nombre"),
                apellido_paterno=data.get("apellido"),
                telefono_movil=data.get("telefono"),
                email=data.get("correo"),
                rut_dni=data.get("rut"),
                proyecto_id=data.get("proyecto_id") or FORMULARIO_PROYECTO_ID_DEFAULT,
                proyecto=data.get("proyecto") or "",
                comentario="Cotizador en pagina web.",
                utm_source="Conilead"
            )

            planok_ok = True

            logger_formulario.info(
                f"[PLANOK OK] crear_lead_formulario_planok finalizado. "
                f"message_id={message_id} resultado={resultado_planok}"
            )

        except Exception as e:
            logger_formulario.exception(
                f"[PLANOK ERROR] Falló crear_lead_formulario_planok. "
                f"message_id={message_id} error={e}"
            )

            raise

        # ============================================================
        # 3) SI PLANOK TERMINÓ, ENVIAR A CHATFUEL
        # ============================================================

        chatfuel_ok = False

        try:
            logger_formulario.info(
                f"[CHATFUEL PRE] Ejecutando send_to_chatfuel_formulario. message_id={message_id}"
            )

            chatfuel_ok = send_to_chatfuel_formulario({**data, "url": url_val, "message_id": message_id})

            logger_formulario.info(
                f"[CHATFUEL FIN] send_to_chatfuel_formulario finalizado. "
                f"message_id={message_id} chatfuel_ok={chatfuel_ok}"
            )

        except Exception as e:
            logger_formulario.exception(
                f"[CHATFUEL ERROR GENERAL] Falló llamada a send_to_chatfuel_formulario. "
                f"message_id={message_id} error={e}"
            )

            raise

        duracion = (datetime.now() - request_inicio).total_seconds()

        logger_formulario.info(
            f"[REQUEST OK] Flujo completo finalizado. "
            f"message_id={message_id} planok_ok={planok_ok} "
            f"chatfuel_ok={chatfuel_ok} duracion_seg={duracion}"
        )

        return jsonify({
            "success": True,
            "message_id": message_id,
            "planok_ok": planok_ok,
            "chatfuel_ok": chatfuel_ok
        })

    except Exception as e:
        duracion = (datetime.now() - request_inicio).total_seconds()

        logger_formulario.exception(
            f"[REQUEST ERROR] Error en /api/widgets. "
            f"message_id={message_id} error={e} duracion_seg={duracion}"
        )

        logging.exception("Error en /api/widgets")

        return jsonify({
            "success": False,
            "message_id": message_id,
            "error": str(e)
        }), 500