import os
import sys
import imaplib
import email
import importlib.util
import pymysql
import requests
import re
import logging

from dotenv import load_dotenv
from email.mime.text import MIMEText
from smtplib import SMTP_SSL
from email.utils import parsedate_to_datetime
from email.header import decode_header
from email.utils import parseaddr

load_dotenv()

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

# ==============================
# CONFIGURACIÓN
# ==============================

IMAP_SERVER = 'ebcoom.inteliventa.ai'
EMAIL_ACCOUNT = 'lead@ebcoom.inteliventa.ai'
PASSWORD = '4+A^sX~vpm1g.Wpk'

SMTP_SERVER = 'ebcoom.inteliventa.ai'
SMTP_PORT = 465

DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_HOST = os.getenv('DB_HOST')
DB_NAME = os.getenv('DB_NAME')

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}"

DB_CONFIG = {
    'host': DB_HOST,
    'user': DB_USER,
    'password': DB_PASSWORD,
    'database': DB_NAME,
    'cursorclass': pymysql.cursors.DictCursor
}

# ==============================
# PLANTILLAS
# ==============================

TEMPLATES_DIR = os.path.join(os.path.dirname(__file__), 'template-email')

TEMPLATES_MAP = {
    'no-responder@toctoc.com': 'procesar_toctoc',
    'no-responder@mercadolibre.com': 'procesar_mercadolibre',
    'no-responder@portalinmobiliario.com': 'procesar_portalinmobiliario',
    'noresponder@enlaceinmobiliario.cl': 'procesar_enlaceinmobiliario',
    'pulsoolas@gmail.com': 'procesar_webcotizar'
}

# ==============================
# LOGS
# ==============================

LOG_DIR = os.path.join(os.path.dirname(__file__), '..', 'logs')
os.makedirs(LOG_DIR, exist_ok=True)

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[
        logging.FileHandler(os.path.join(LOG_DIR, "email_reader.log")),
        logging.StreamHandler()
    ]
)

# ==============================
# UTILIDADES
# ==============================
def extract_email_address(from_header):
    name, email_addr = parseaddr(from_header)
    return email_addr.lower()

def sanitize_field(value):

    if value is None:
        return ""

    return str(value).replace('\n', ' ').replace('\r', '').strip()


def decode_mime_header(header_value):

    if not header_value:
        return ""

    decoded_parts = decode_header(header_value)

    decoded_string = ""

    for part, encoding in decoded_parts:

        if isinstance(part, bytes):

            try:
                decoded_string += part.decode(encoding or "utf-8", errors="ignore")

            except:
                decoded_string += part.decode("utf-8", errors="ignore")

        else:
            decoded_string += part

    return decoded_string.strip()


def normalize_phone(phone):

    phone = re.sub(r'\D', '', phone)

    if phone.startswith("569"):
        return phone

    if phone.startswith("9"):
        return "56" + phone

    if phone.startswith("56"):
        return phone

    return "56" + phone


def extract_remitente_name(remitente):

    if remitente and "<" in remitente:
        return remitente.split("<")[0].strip()

    return remitente.strip()


# ==============================
# CONEXIONES
# ==============================

def connect_to_imap():

    mail = imaplib.IMAP4_SSL(IMAP_SERVER)
    mail.login(EMAIL_ACCOUNT, PASSWORD)

    return mail


def connect_to_smtp():

    smtp = SMTP_SSL(SMTP_SERVER, SMTP_PORT)
    smtp.login(EMAIL_ACCOUNT, PASSWORD)

    return smtp


# ==============================
# CARGAR TEMPLATE
# ==============================

def load_template(template_name):

    template_path = os.path.join(TEMPLATES_DIR, f"{template_name}.py")

    spec = importlib.util.spec_from_file_location(template_name, template_path)

    module = importlib.util.module_from_spec(spec)

    spec.loader.exec_module(module)

    return module


# ==============================
# BASE DE DATOS
# ==============================

def email_exists(message_id):

    connection = pymysql.connect(**DB_CONFIG)

    try:

        with connection.cursor() as cursor:

            sql = "SELECT COUNT(*) as count FROM correos_datos WHERE message_id=%s"

            cursor.execute(sql, (message_id,))

            result = cursor.fetchone()

            return result["count"] > 0

    finally:

        connection.close()


def insert_into_database(data):

    connection = pymysql.connect(**DB_CONFIG)

    try:

        with connection.cursor() as cursor:

            sql = """
            INSERT INTO correos_datos
            (
                message_id,
                asunto,
                remitente,
                nombre,
                proyecto,
                rut,
                correo,
                telefono,
                fecha_registro
            )
            VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)
            """

            cursor.execute(sql, (

                data.get("ID"),
                data.get("Asunto"),
                data.get("Remitente"),
                data.get("Nombre"),
                data.get("Proyecto"),
                data.get("RUT"),
                data.get("Correo"),
                data.get("Teléfono"),
                data.get("Fecha")

            ))

        connection.commit()

    finally:

        connection.close()


def insert_into_lead_entrantes(data):

    connection = pymysql.connect(**DB_CONFIG)

    try:

        with connection.cursor() as cursor:

            sql = """
            INSERT INTO Lead_entrantes
            (
                Now,
                Fecha_ingreso,
                ID_centralizador,
                Estado,
                ID_cliente,
                Rut_cliente,
                Nombre_cliente,
                Apellido_cliente,
                Numero_telefono_fijo_cliente,
                Numero_telefono_movil_cliente,
                Email_cliente,
                Medio_llegada,
                Via_ingreso,
                Proyecto,
                enviado_cf,
                respuesta_cf,
                ID_interno
            )
            VALUES
            (
                NOW(),%s,%s,'pendiente',%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s
            )
            """

            values = (

                data.get("Fecha"),
                data.get("ID"),
                data.get("RUT"),
                data.get("RUT"),
                data.get("Nombre"),
                data.get("Apellido"),
                data.get("Teléfono"),
                data.get("Teléfono"),
                data.get("Correo"),
                extract_remitente_name(data.get("Remitente")),
                "Portales Web",
                data.get("Proyecto"),
                True,
                None,
                "0"

            )

            cursor.execute(sql, values)

        connection.commit()

    finally:

        connection.close()


# ==============================
# CHATFUEL
# ==============================

def send_to_chatfuel(data):

    remitente_name = extract_remitente_name(data.get("Remitente"))

    payload = {

        "id": data.get("ID"),
        "subject": data.get("Asunto"),
        "crm Medio_llegada": remitente_name,
        "crm Nombre_cliente": data.get("Nombre"),
        "crm Proyecto": data.get("Proyecto"),
        "crm Rut_cliente": data.get("RUT"),
        "crm Email_cliente": data.get("Correo"),
        "phone": normalize_phone(data.get("Teléfono")),
        "date": data.get("Fecha"),
        "crm telefono_movil": normalize_phone(data.get("Teléfono")),
        "Activar_Contacto": True,
        "invokeTriggers": True,
        "tagNames": ["Nuevo_lead"]

    }

    logging.info(f"Payload Chatfuel: {payload}")

    try:

        r = requests.post(CHATFUEL_URL, json=payload)

        if r.status_code == 200:

            logging.info("Enviado a Chatfuel")

        else:

            logging.error(f"Error Chatfuel {r.text}")

    except Exception as e:

        logging.error(f"Error enviando Chatfuel {e}")


# ==============================
# PROCESAR CORREOS
# ==============================

def fetch_emails():

    mail = connect_to_imap()

    mail.select('inbox')

    status, data = mail.search(None, 'ALL')

    email_ids = data[0].split()

    logging.info(f"Correos encontrados: {email_ids}")

    for email_id in email_ids:

        status, data = mail.fetch(email_id, '(RFC822)')

        raw_email = data[0][1]

        msg = email.message_from_bytes(raw_email)

        subject = sanitize_field(decode_mime_header(msg.get("Subject")))
        from_ = sanitize_field(decode_mime_header(msg.get("From")))
        date_raw = msg.get("Date")
        
        from_raw = sanitize_field(decode_mime_header(msg.get("From")))
        from_email = extract_email_address(from_raw)

        message_id = sanitize_field(msg.get("Message-ID") or subject)

        if email_exists(message_id):

            logging.info("Correo ya procesado")

            continue

        try:

            date = parsedate_to_datetime(date_raw).strftime('%Y-%m-%d %H:%M:%S')

        except:

            date = None

        template_name = None

        for sender, template in TEMPLATES_MAP.items():
            if sender.lower() == from_email:
                template_name = template
                break
        if not template_name:

            logging.info(f"Correo ignorado: {from_}")

            continue

        try:

            template = load_template(template_name)

            processed_data = template.process_email(msg)

            processed_data["Fecha"] = date
            processed_data["ID"] = message_id
            processed_data["Asunto"] = subject
            processed_data["Remitente"] = from_

            processed_data["Teléfono"] = normalize_phone(processed_data.get("Teléfono"))

            insert_into_database(processed_data)

            insert_into_lead_entrantes(processed_data)

            send_to_chatfuel(processed_data)

            mail.copy(email_id, 'INBOX.Procesados')

            mail.store(email_id, '+FLAGS', '\\Deleted')

            logging.info(f"Procesado: {message_id}")

        except Exception as e:

            logging.error(f"Error procesando {message_id}: {e}")

    mail.expunge()

    mail.logout()


if __name__ == "__main__":

    fetch_emails()