# -*- coding: utf-8 -*-
"""
Descarga de archivos: wget y requests (streaming).

Incluye validación básica del archivo descargado (no HTML, tamaño mínimo).
"""

import logging
import os
import subprocess

import requests

from . import config
from . import utils


def _eliminar_si_existe(ruta):
    """Borra el archivo si existe; ignora errores."""
    if os.path.exists(ruta):
        try:
            os.remove(ruta)
        except OSError:
            pass


def _validar_archivo_descargado(ruta, nombre_app, min_size=500000):
    """
    Comprueba que el archivo no sea HTML y tenga un tamaño mínimo.

    Returns:
        True si es válido; en caso contrario registra error, borra el archivo y devuelve False.
    """
    tamano = os.path.getsize(ruta)
    try:
        with open(ruta, "rb") as f:
            cabecera = f.read(512)
        if b"<html" in cabecera.lower() or b"<!doctype" in cabecera.lower():
            utils.registrar_error(
                f"{nombre_app}: Se descargó HTML en vez del binario ({tamano} bytes). Eliminando."
            )
            os.remove(ruta)
            return False
    except Exception:
        pass
    if tamano < min_size:
        logging.warning(
            f"{nombre_app}: Archivo pequeño ({tamano} bytes) por debajo del umbral ({min_size}). "
            "Se acepta igualmente."
        )
    logging.info(f"{nombre_app}: Descarga exitosa ({tamano} bytes)")
    return True


def descargar_con_wget(url, ruta_destino, nombre_app):
    """
    Descarga usando el binario wget (reintentos, resume).

    Returns:
        True si la descarga fue correcta y la validación pasó.
    """
    try:
        if os.path.exists(ruta_destino):
            os.remove(ruta_destino)
            logging.info(f"{nombre_app}: Archivo previo eliminado antes de descargar")
        logging.info(f"{nombre_app}: Descargando desde {url}")
        cmd = ["wget", "-nv", "-c", "--tries=10", "--timeout=30", "-O", ruta_destino, url]
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
        if result.stderr:
            for linea in result.stderr.strip().split("\n"):
                linea = linea.strip()
                if linea and not linea.startswith("--"):
                    logging.info(f"{nombre_app}: {linea}")
        if result.returncode != 0:
            utils.registrar_error(f"{nombre_app}: wget falló con código {result.returncode}")
            _eliminar_si_existe(ruta_destino)
            return False
        if not os.path.exists(ruta_destino):
            utils.registrar_error(f"{nombre_app}: wget terminó pero no creó el archivo")
            return False
        return _validar_archivo_descargado(ruta_destino, nombre_app)
    except subprocess.TimeoutExpired:
        utils.registrar_error(f"{nombre_app}: wget timeout (10 min)")
        _eliminar_si_existe(ruta_destino)
        return False
    except Exception as e:
        utils.registrar_error(f"{nombre_app}: Error ejecutando wget: {e}")
        _eliminar_si_existe(ruta_destino)
        return False


def descargar_con_requests(url, ruta_destino, nombre_app, headers=None):
    """
    Descarga con requests en modo streaming.

    Returns:
        True si la descarga y validación (tamaño mínimo 100KB) son correctas.
    """
    if headers is None:
        headers = config.DEFAULT_HEADERS.copy()
    try:
        with requests.get(
            url, headers=headers, stream=True, timeout=300, allow_redirects=True
        ) as r:
            r.raise_for_status()
            ct = (r.headers.get("Content-Type") or "").lower()
            if "text/html" in ct:
                utils.registrar_error(
                    f"Error: Se recibió HTML al descargar {nombre_app}. URL: {url}"
                )
                return False
            with open(ruta_destino, "wb") as f:
                for chunk in r.iter_content(chunk_size=8192):
                    f.write(chunk)
        return _validar_archivo_descargado(ruta_destino, nombre_app, min_size=100000)
    except Exception as e:
        utils.registrar_error(f"Error al descargar el archivo de {nombre_app}: {e}")
        _eliminar_si_existe(ruta_destino)
        return False
