# -*- coding: utf-8 -*-
"""
Funciones de utilidad: notificaciones, normalización y comparación de versiones.

- enviar_correo_error / registrar_error: reporte de errores a log y correo.
- limpiar_version / comparar_versiones: normalizar y comparar cadenas de versión.
- obtener_version / obtener_version_header: extraer versión de cadenas o cabeceras HTTP.
"""

import datetime
import logging
import re
import subprocess

from . import config


# -----------------------------------------------------------------------------
# Notificaciones
# -----------------------------------------------------------------------------


def enviar_correo_error(mensaje):
    """
    Envía un correo notificando un error durante la ejecución (usa comando 'mail').

    Args:
        mensaje: Descripción del error.
    """
    if not config.ENVIAR_CORREO:
        return
    try:
        asunto = "[softlibre] Error en actualizador"
        cuerpo = (
            f"{mensaje}\n"
            f"Fecha: {datetime.datetime.now().strftime('%d-%m-%Y %H:%M')}\n"
        )
        destinatarios = [d.strip() for d in config.EMAIL_TO.split(",")]
        cmd = ["mail", "-s", asunto, "-r", config.EMAIL_FROM, "--"] + destinatarios
        result = subprocess.run(cmd, input=cuerpo, text=True, capture_output=True, timeout=30)
        if result.stdout:
            logging.info(f"mail STDOUT: {result.stdout.strip()}")
        if result.stderr:
            logging.info(f"mail STDERR: {result.stderr.strip()}")
        if result.returncode == 0:
            logging.info(f"Correo de error enviado a {config.EMAIL_TO}")
        else:
            logging.error(f"Error al enviar correo (exit code {result.returncode}).")
    except Exception as e:
        logging.warning(f"No se pudo enviar el correo de error: {e}")


def registrar_error(mensaje):
    """
    Registra un error en el log y envía notificación por correo.

    Args:
        mensaje: Mensaje de error.
    """
    logging.error(mensaje)
    enviar_correo_error(mensaje)


# -----------------------------------------------------------------------------
# Versiones
# -----------------------------------------------------------------------------


def limpiar_version(version):
    """
    Normaliza una cadena de versión (solo dígitos y puntos).

    Args:
        version: Cadena original (ej. "v1.2.3-beta").

    Returns:
        Versión limpia (ej. "1.2.3") o cadena vacía si version es None/vacía.
    """
    if not version:
        return ""
    v = str(version).replace("_", ".").replace("-", ".")
    v = re.sub(r"[^0-9.]", "", v)
    v = re.sub(r"\.{2,}", ".", v).strip(".")
    return v


def comparar_versiones(version1, version2):
    """
    Compara dos versiones numéricas (segmentos separados por puntos).

    Returns:
        1 si version1 > version2, -1 si version1 < version2, 0 si son iguales.
    """
    if not version1 or not version2:
        return 0
    v1 = limpiar_version(version1)
    v2 = limpiar_version(version2)
    partes_v1 = v1.split(".")
    partes_v2 = v2.split(".")
    for i in range(max(len(partes_v1), len(partes_v2))):
        p1 = int(partes_v1[i]) if i < len(partes_v1) and partes_v1[i].isdigit() else 0
        p2 = int(partes_v2[i]) if i < len(partes_v2) and partes_v2[i].isdigit() else 0
        if p1 > p2:
            return 1
        if p1 < p2:
            return -1
    return 0


def obtener_version(pattern, filename):
    """
    Extrae la versión de una cadena (nombre de archivo o URL) con una regex.

    Args:
        pattern: Expresión regular (con grupo de captura opcional).
        filename: Cadena donde buscar.

    Returns:
        Versión encontrada o None.
    """
    if not pattern or not filename:
        return None
    match = re.search(pattern, filename)
    if match:
        return match.group(1) if match.groups() else match.group(0)
    return None


def obtener_version_header(pattern, headers):
    """
    Extrae la versión desde el header Content-Disposition de una respuesta HTTP.

    Args:
        pattern: Regex para la versión.
        headers: Diccionario de cabeceras.

    Returns:
        Versión extraída o None.
    """
    content_disp = headers.get("Content-Disposition")
    if content_disp:
        match = re.search(r'filename="?([^";]+)"?', content_disp)
        if match:
            return obtener_version(pattern, match.group(1))
    return None
