# lastfm_cover_downloader.py

import os
import requests
import urllib.parse
from pathlib import Path
import logging

# Configuración básica de logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# Obtener la ruta de la clave de API de Last.fm desde una variable de entorno
API_KEY_FILE = os.environ.get(
    'LASTFM_API_KEY_PATH', os.path.expandvars('$HOME/apikeys/lastfm'))


def get_lastfm_api_key():
    """Leer la clave de API de Last.fm desde un archivo."""
    try:
        with open(API_KEY_FILE, 'r') as file:
            api_key = file.readline().strip()
            logger.info(f"Successfully read Last.fm API key from {
                        API_KEY_FILE}")
            return api_key
    except FileNotFoundError:
        logger.error(f"API key file '{API_KEY_FILE}' not found.")
        raise
    except Exception as e:
        logger.error(f"Error reading API key: {e}")
        raise


# Obtener la clave de API de Last.fm
LASTFM_API_KEY = get_lastfm_api_key()
if not LASTFM_API_KEY:
    raise RuntimeError("Last.fm API key could not be loaded.")


def get_largest_cover_image(data):
    """Seleccionar la imagen de portada más grande disponible en la respuesta de Last.fm."""
    if 'album' in data and 'image' in data['album']:
        # Definir el orden de prioridad de tamaños
        size_priority = ["mega", "extralarge", "large", "medium", "small"]
        for size in size_priority:
            for img in data['album']['image']:
                if img["size"] == size and img["#text"]:
                    logger.info(f"Using {size} cover: {img['#text']}")
                    return img["#text"]
    return None


def download_image(cover_url, output_path):
    """Descargar la imagen de portada desde una URL y guardarla en la ruta especificada."""
    try:
        logger.info(f"Downloading image from {cover_url} to {output_path}")
        response = requests.get(cover_url, stream=True)
        if response.status_code == 200:
            with open(output_path, 'wb') as f:
                for chunk in response.iter_content(1024):
                    f.write(chunk)
            logger.info(f"Image downloaded to {output_path}")
            return output_path
        else:
            logger.error(f"Failed to download image. HTTP Status: {
                         response.status_code}")
            raise Exception(f"HTTP Status {response.status_code}")
    except Exception as e:
        logger.error(f"Error downloading image: {e}")
        raise


def download_cover_from_lastfm(artist, album, album_dir):
    """Descargar la portada del álbum desde Last.fm y guardarla en el directorio del álbum."""
    try:
        logger.info(f"Fetching cover for '{album}' by {
                    artist} from Last.fm...")
        # URL de la API de Last.fm
        url = f"http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key={LASTFM_API_KEY}&artist={
            urllib.parse.quote(artist)}&album={urllib.parse.quote(album)}&format=json"
        response = requests.get(url)
        if response.status_code == 200:
            data = response.json()
            cover_url = get_largest_cover_image(data)
            if cover_url:
                # Asegurar que el directorio existe
                album_dir.mkdir(parents=True, exist_ok=True)
                local_cover_path = album_dir / "cover.jpg"  # Guardar como 'cover.jpg'
                download_image(cover_url, local_cover_path)
                logger.info(f"Downloaded cover to {local_cover_path}")
                return local_cover_path
        logger.warning(f"No cover found for '{album}' by {artist} on Last.fm.")
        raise Exception(f"No cover found for '{album}' by {artist}.")
    except Exception as e:
        logger.error(f"Error fetching cover from Last.fm: {e}")
        raise


def cover_exists(album_dir):
    """Verificar si 'cover.jpg' o 'Cover.jpg' existe en el directorio del álbum."""
    cover_path_lower = album_dir / "cover.jpg"
    cover_path_upper = album_dir / "Cover.jpg"
    exists = cover_path_lower.exists() or cover_path_upper.exists()
    logger.info(f"Checking cover existence in '{album_dir}': {
                'Found' if exists else 'Not found'}")
    return exists


def get_local_album_dir(xesam_url, music_base_path=os.environ.get('MUSIC_LIBRARY_PATH', os.path.expandvars('$HOME/media/all'))):
    """Extraer el directorio del álbum desde la ruta `xesam:url`."""
    if not xesam_url:
        logger.warning(
            "xesam:url is empty or missing. Skipping cover detection.")
        return None

    try:
        logger.info(f"Raw xesam:url value: {xesam_url}")

        # Convertir la URL xesam en una ruta de archivo local
        local_path = urllib.parse.unquote(xesam_url).replace("file://", "")
        logger.info(f"Converted local path: {local_path}")

        # Eliminar '/trackXXXX' si es una ruta de archivo CUE
        if "/track" in local_path and ".cue" in local_path:
            local_path = local_path.split("/track")[0]
            logger.info(f"Stripped CUE path: {local_path}")

        # Si la ruta no es absoluta, agregar el directorio base de música
        track_path = Path(local_path)
        if not track_path.is_absolute():
            track_path = Path(music_base_path) / track_path
            logger.info(f"Updated to absolute path: {track_path}")

        # Verificar si la ruta resultante existe
        if not track_path.exists():
            logger.warning(f"The path '{track_path}' does not exist.")
            return None

        # Manejar archivos CUE: Subir al directorio del álbum real
        if track_path.suffix == ".cue":
            return track_path.parent

        # Manejo estándar de rutas
        if track_path.is_file():
            return track_path.parent
        else:
            logger.warning(f"Path is not a valid file: {track_path}")
    except Exception as e:
        logger.error(f"Error extracting local album directory: {e}")
    return None

