#!/usr/bin/env python3
import os
import re
import requests
import xml.etree.ElementTree as ET
from datetime import datetime
import time  # para manejar tiempos y comparaciones

# Configuración de rutas, API key y URL de la lista M3U
OUTPUT_DIR = "/home/migosu/disco/web/servidor-mitilingo/programacion"
MOVIES_FOLDER = "/home/migosu/videos/peliculas"  # carpeta donde se encuentran las películas locales
TMDB_API_KEY = "c6f168888ef0b6c80325763d0415d8c2"
TMDB_BASE_URL = "https://api.themoviedb.org/3"
TMDB_IMAGE_BASE_URL = "https://image.tmdb.org/t/p/w500"
M3U_URL = "http://mitilingo.com:8484/get.php?username=peliculas&password=pCbabSLqhw&type=m3u_plus&output=mpegts"

def get_movies_from_m3u(url):
    """
    Descarga y parsea la lista M3U desde la URL dada.
    Retorna una lista de diccionarios con 'name' y 'stream_url' para cada película.
    """
    try:
        response = requests.get(url)
        if response.status_code != 200:
            print(f"Error al descargar la lista M3U: {response.status_code}")
            return []
        lines = response.text.splitlines()
    except Exception as e:
        print(f"Error al descargar la lista M3U: {e}")
        return []

    movies = []
    i = 0
    while i < len(lines):
        line = lines[i].strip()
        if line.startswith("#EXTINF:"):
            # Se extrae el nombre de la película del atributo tvg-name o tras la coma
            match = re.search(r'tvg-name="([^"]+)"', line)
            if match:
                movie_name = match.group(1).strip()
            else:
                parts = line.split(',', 1)
                movie_name = parts[1].strip() if len(parts) > 1 else ""
            # La siguiente línea contiene la URL de emisión
            stream_url = ""
            if i + 1 < len(lines):
                stream_url = lines[i+1].strip()
            movies.append({"name": movie_name, "stream_url": stream_url})
            i += 2
        else:
            i += 1
    return movies

def clean_filename(filename):
    """
    Limpia el nombre quitando la extensión y eliminando el año si aparece (formato de 4 dígitos).
    """
    name, _ = os.path.splitext(filename)
    cleaned = re.sub(r'[\(\[]?\b(19|20)\d{2}\b[\)\]]?', '', name)
    cleaned = re.sub(r'\s+', ' ', cleaned).strip()
    return cleaned

def search_movie(movie_name):
    """
    Consulta la API de TMDB para buscar la película por su nombre.
    Devuelve el primer resultado (si existe) o None en caso de no encontrar coincidencias.
    """
    url = f"{TMDB_BASE_URL}/search/movie"
    params = {
        "api_key": TMDB_API_KEY,
        "language": "es-ES",
        "query": movie_name
    }
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            data = response.json()
            results = data.get("results", [])
            if results:
                return results[0]
    except Exception as e:
        print(f"Error al buscar la película '{movie_name}': {e}")
    return None

def get_genre_mapping():
    """
    Obtiene el mapeo de géneros de TMDB (id a nombre) para el idioma español.
    """
    url = f"{TMDB_BASE_URL}/genre/movie/list"
    params = {
        "api_key": TMDB_API_KEY,
        "language": "es-ES"
    }
    mapping = {}
    try:
        response = requests.get(url, params=params)
        if response.status_code == 200:
            data = response.json()
            genres = data.get("genres", [])
            for genre in genres:
                mapping[genre["id"]] = genre["name"]
    except Exception as e:
        print(f"Error al obtener los géneros: {e}")
    return mapping

def create_item_element(movie, use_backdrop=False):
    """
    Crea el elemento XML <item> para una película usando los datos obtenidos de TMDB.
    Utiliza: título, id, overview, fecha de lanzamiento y la imagen (poster o backdrop).
    El enlace se establece con la URL de transmisión obtenida del archivo M3U.
    Si use_backdrop es True, se prefiere usar la imagen backdrop; de lo contrario, se usa poster.
    Si no hay imagen disponible, retorna None.
    """
    item = ET.Element("item")

    title = ET.SubElement(item, "title")
    title.text = movie.get("title", "")

    link = ET.SubElement(item, "link")
    link.text = movie.get("stream_url", "")

    description = ET.SubElement(item, "description")
    description.text = movie.get("overview", "")

    pubDate = ET.SubElement(item, "pubDate")
    release_date = movie.get("release_date", "")
    if release_date:
        try:
            dt = datetime.strptime(release_date, "%Y-%m-%d")
            default_time = "16:51:07"
            pubDate.text = dt.strftime("%a, %d %b %Y ") + default_time + " GMT"
        except Exception:
            pubDate.text = ""
    else:
        pubDate.text = ""

    guid = ET.SubElement(item, "guid", attrib={"isPermaLink": "false"})
    guid.text = str(movie.get("id"))

    video_url = movie.get("stream_url", "")
    ext = os.path.splitext(video_url)[1].lower()
    if ext:
        video_type = "video/" + ext[1:]
    else:
        video_type = "video/unknown"

    if use_backdrop:
        image_path = movie.get("backdrop_path")
        if not image_path:
            image_path = movie.get("poster_path")
        if not image_path:
            return None
    else:
        image_path = movie.get("poster_path")

    image_url = f"{TMDB_IMAGE_BASE_URL}{image_path}" if image_path else ""

    media_content = ET.Element("media:content", {
        "url": video_url,
        "type": video_type,
        "channels": "",
        "bitrate": "",
        "duration": "",
        "fileSize": "",
        "framerate": "",
        "height": "",
        "width": "",
        "isDefault": "true"
    })

    media_description = ET.SubElement(media_content, "media:description")
    media_description.text = movie.get("overview", "")

    media_keywords = ET.SubElement(media_content, "media:keywords")
    media_keywords.text = ""

    media_thumbnail = ET.SubElement(media_content, "media:thumbnail", {"url": image_url})

    media_title = ET.SubElement(media_content, "media:title")
    media_title.text = movie.get("title", "")

    item.append(media_content)
    return item

def create_rss_feed(items):
    """
    Crea la estructura completa del feed RSS y agrega los items proporcionados.
    """
    rss = ET.Element("rss", {"xmlns:media": "http://search.yahoo.com/mrss/", "version": "2.0"})
    channel = ET.SubElement(rss, "channel")

    title = ET.SubElement(channel, "title")
    title.text = "Tilingo"

    link = ET.SubElement(channel, "link")
    link.text = ""

    description = ET.SubElement(channel, "description")
    description.text = "Feed on video content for testing channel applications built on the Roku developer platform"

    language = ET.SubElement(channel, "language")
    language.text = "en-us"

    pubDate = ET.SubElement(channel, "pubDate")
    pubDate.text = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")

    image = ET.SubElement(channel, "image")
    image_title = ET.SubElement(image, "title")
    image_title.text = "Tilingo"
    image_url = ET.SubElement(image, "url")
    image_url.text = "http://mitilingo.com/logo.png"
    image_width = ET.SubElement(image, "width")
    image_width.text = "-1"
    image_height = ET.SubElement(image, "height")
    image_height.text = "-1"

    for item in items:
        channel.append(item)

    return rss

def main():
    # Asegurarse de que el directorio de salida exista
    os.makedirs(OUTPUT_DIR, exist_ok=True)

    # Obtener el mapeo de géneros (aunque no se utiliza directamente para generar el feed)
    genre_mapping = get_genre_mapping()

    # Descargar y parsear la lista M3U
    m3u_entries = get_movies_from_m3u(M3U_URL)
    if not m3u_entries:
        print("No se encontraron entradas en la lista M3U.")
        return

    # Construir un diccionario de películas en la carpeta
    # Se mapea el nombre limpio (en minúsculas) al tiempo de creación del archivo
    folder_movies = {}
    if os.path.exists(MOVIES_FOLDER):
        for file in os.listdir(MOVIES_FOLDER):
            file_path = os.path.join(MOVIES_FOLDER, file)
            if os.path.isfile(file_path):
                cleaned_name = clean_filename(file).lower()
                creation_time = os.path.getctime(file_path)
                folder_movies[cleaned_name] = creation_time
    else:
        print(f"La carpeta de películas '{MOVIES_FOLDER}' no existe.")

    current_time = time.time()
    threshold_seconds = 7 * 24 * 3600  # 7 días en segundos

    all_items = []
    estrenos_candidates = []  # Lista de tuplas: (rating, item)

    for entry in m3u_entries:
        movie_name = entry.get("name", "")
        stream_url = entry.get("stream_url", "")
        clean_name = clean_filename(movie_name)
        normalized_name = clean_name.lower()
        print(f"Buscando datos para: {clean_name}")
        tmdb_movie = search_movie(clean_name)
        if tmdb_movie:
            tmdb_movie["stream_url"] = stream_url
            item = create_item_element(tmdb_movie)
            if item is not None:
                all_items.append(item)

            found_local = False
            local_creation_time = None

            # Comparación directa (insensible a mayúsculas)
            if normalized_name in folder_movies:
                found_local = True
                local_creation_time = folder_movies[normalized_name]
            else:
                # Si no coincide directamente, se recorre la lista de archivos y se consulta TMDB para comparar el título en español
                for file_clean, creation_time in folder_movies.items():
                    if file_clean == normalized_name:
                        continue
                    tmdb_result_file = search_movie(file_clean)
                    if tmdb_result_file:
                        tmdb_spanish_title = tmdb_result_file.get("title", "").strip().lower()
                        if tmdb_spanish_title == normalized_name:
                            found_local = True
                            local_creation_time = creation_time
                            break

            # Si se encontró el archivo local y fue agregado en la última semana, se agrega a los candidatos para estrenos
            if found_local and (current_time - local_creation_time) < threshold_seconds:
                estreno_item = create_item_element(tmdb_movie, use_backdrop=True)
                if estreno_item is not None:
                    rating = tmdb_movie.get("vote_average", 0)
                    estrenos_candidates.append((rating, estreno_item))
        else:
            print(f"No se encontraron datos para: {clean_name}")

    # Seleccionar las 10 películas con mejor rating de las agregadas en la última semana
    estrenos_candidates.sort(key=lambda x: x[0], reverse=True)
    estrenos_items = [item for _, item in estrenos_candidates[:10]]

    # Crear los feeds RSS
    rss_all = create_rss_feed(all_items)
    rss_estrenos = create_rss_feed(estrenos_items)

    # Guardar los archivos RSS
    tree_all = ET.ElementTree(rss_all)
    tree_estrenos = ET.ElementTree(rss_estrenos)

    tree_all.write(os.path.join(OUTPUT_DIR, "peliculas.rss"), encoding="UTF-8", xml_declaration=True)
    tree_estrenos.write(os.path.join(OUTPUT_DIR, "estrenos.rss"), encoding="UTF-8", xml_declaration=True)

    print("Feeds RSS generados exitosamente.")

    # Registrar la fecha y hora de la última ejecución en estrenos.log
    script_dir = os.path.dirname(os.path.abspath(__file__))
    log_file_path = os.path.join(script_dir, "estrenos.log")
    with open(log_file_path, "w") as log_file:
        now = datetime.now()
        log_file.write(now.strftime("%Y-%m-%d %H:%M:%S"))

if __name__ == "__main__":
    main()
