import streamlit as st
import cloudinary
import cloudinary.uploader
import cloudinary.api
import requests
import io
import zipfile
import logging

# Configuración de la página y del logging
st.set_page_config(
    page_title="Cloudinary AI Background Generator",
    page_icon="🤖",
    layout="wide"
)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


def init_cloudinary():
    """
    Inicializa Cloudinary utilizando las credenciales definidas en st.secrets.
    Registra en session_state si se inicializó correctamente y realiza una limpieza inicial.
    """
    if 'cloudinary_initialized' not in st.session_state:
        try:
            cloudinary.config(url=st.secrets['CLOUDINARY_URL'])
            st.session_state.cloudinary_initialized = True
            cleanup_cloudinary()  # Limpieza de recursos al iniciar
            logging.info("Cloudinary inicializado correctamente.")
        except Exception as e:
            st.error("Error: No se encontraron las credenciales de Cloudinary en secrets.toml")
            st.session_state.cloudinary_initialized = False
            logging.error(f"Error al inicializar Cloudinary: {e}")


def check_file_size(file, max_size_mb=10):
    """
    Verifica que el tamaño del archivo no exceda el límite especificado (en MB).
    """
    file.seek(0, io.SEEK_END)
    file_size = file.tell() / (1024 * 1024)
    file.seek(0)
    return file_size <= max_size_mb


def cleanup_cloudinary():
    """
    Limpia todos los recursos almacenados en Cloudinary.
    """
    if not st.session_state.get('cloudinary_initialized', False):
        return
    try:
        result = cloudinary.api.resources()
        if 'resources' in result and result['resources']:
            public_ids = [resource['public_id'] for resource in result['resources']]
            if public_ids:
                cloudinary.api.delete_resources(public_ids)
                logging.info("Recursos de Cloudinary limpiados correctamente.")
    except Exception as e:
        st.error(f"Error al limpiar recursos: {e}")
        logging.error(f"Error al limpiar recursos: {e}")


def process_image(image, width, height, dpr):
    """
    Procesa la imagen utilizando Cloudinary aplicando una transformación definida.

    Parámetros:
    - image: Objeto tipo BytesIO con la imagen a procesar.
    - width, height: Dimensiones deseadas.
    - dpr: Escalado de resolución.

    Retorna:
    - Tuple con la imagen procesada en bytes y la extensión del archivo.
    """
    if not st.session_state.get('cloudinary_initialized', False):
        st.error("Cloudinary no está inicializado correctamente")
        return None, None

    try:
        image.seek(0)
        if not check_file_size(image, 10):
            st.error("La imagen excede el límite de 10MB")
            return None, None

        image_content = image.read()
        response = cloudinary.uploader.upload(
            image_content,
            transformation=[{
                "width": width,
                "height": height,
                "crop": "pad",
                "background": "gen_fill",
                "quality": 100,
                "dpr": dpr,
                "flags": "preserve_transparency"
            }]
        )
        processed_url = response['secure_url']
        processed_image = requests.get(processed_url).content
        file_format = response.get('format', 'jpg')
        logging.info("Imagen procesada correctamente.")
        return processed_image, file_format
    except Exception as e:
        st.error(f"Error procesando imagen: {e}")
        logging.error(f"Error en process_image: {e}")
        return None, None


def main():
    """
    Función principal que configura la interfaz de la aplicación y coordina el flujo de procesamiento.
    """
    init_cloudinary()

    st.title("🤖 Cloudinary AI Background Generator")

    with st.expander("📌 ¿Cómo usar esta herramienta?", expanded=True):
        st.markdown(
            """
            **Transforma tus imágenes automáticamente con IA:**
            - 🔄 Redimensiona manteniendo la relación de aspecto
            - 🎨 Genera fondos coherentes usando IA
            - 📥 Descarga múltiples imágenes en un ZIP
    
            **Formatos soportados:**
            - PNG, JPG, JPEG, WEBP
    
            **Pasos para usar:**
            1. Define las dimensiones deseadas (ancho y alto)
            2. Sube tus imágenes (hasta 10MB cada una)
            3. Haz clic en "Procesar Imágenes"
            4. Descarga los resultados finales
    
            **Características clave:**
            - Preserva transparencia en PNGs
            - Soporte para formatos modernos (WEBP)
            - Calidad ultra HD (DPR configurable entre 1 y 3)
            - Procesamiento por lotes
            - Fondo generado por IA adaptado al contexto
    
            **Notas:**
            - Las imágenes subidas se borran automáticamente después del procesamiento
            - Para mejores resultados, usa imágenes con sujetos bien definidos
            - El tiempo de procesamiento varía según el tamaño y cantidad de imágenes
            """
        )

    # Sección de parámetros de configuración
    col1, col2, col3 = st.columns(3)
    with col1:
        width = st.number_input("Ancho (px)", value=1000, min_value=100, max_value=3000)
    with col2:
        height = st.number_input("Alto (px)", value=460, min_value=100, max_value=3000)
    with col3:
        dpr = st.number_input("DPR", value=3, min_value=1, max_value=3, step=1)

    # Carga de archivos de imagen
    uploaded_files = st.file_uploader(
        "Sube tus imágenes (máx. 10MB por archivo)",
        type=['png', 'jpg', 'jpeg', 'webp'],
        accept_multiple_files=True
    )

    if uploaded_files:
        st.header("Imágenes Originales")
        cols = st.columns(3)
        original_images = []
        for idx, file in enumerate(uploaded_files):
            file_bytes = file.getvalue()
            original_images.append((file.name, file_bytes))
            with cols[idx % 3]:
                st.image(file_bytes, caption=file.name, use_column_width=True)

        if st.button("Procesar Imágenes"):
            if not st.session_state.get('cloudinary_initialized', False):
                st.error("Por favor, asegúrate de que Cloudinary esté correctamente configurado")
                return

            processed_images = []
            progress_bar = st.progress(0)

            for idx, (name, img_bytes) in enumerate(original_images):
                img_io = io.BytesIO(img_bytes)
                with st.spinner(f'Procesando imagen {idx + 1}/{len(original_images)}...'):
                    processed, file_format = process_image(img_io, width, height, dpr)
                    if processed:
                        processed_images.append((processed, file_format))
                    progress_bar.progress((idx + 1) / len(original_images))

            if processed_images:
                st.header("Imágenes Procesadas")
                cols = st.columns(3)
                for idx, (img_bytes, file_format) in enumerate(processed_images):
                    with cols[idx % 3]:
                        st.image(img_bytes, caption=f"Formato: {file_format}", use_column_width=True)

                # Empaquetado en ZIP
                zip_buffer = io.BytesIO()
                with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
                    for idx, (img_bytes, file_format) in enumerate(processed_images):
                        zip_file.writestr(f'imagen_procesada_{idx}.{file_format}', img_bytes)

                st.download_button(
                    label="Descargar todas las imágenes",
                    data=zip_buffer.getvalue(),
                    file_name="imagenes_procesadas.zip",
                    mime="application/zip"
                )


if __name__ == "__main__":
    main()