from flask import Flask, render_template, redirect, url_for, request, jsonify
import os
import re
import requests
import json
import yt_dlp
from bs4 import BeautifulSoup
from werkzeug.middleware.proxy_fix import ProxyFix
from googleapiclient.discovery import build
import auth_helper

app = Flask(__name__)
# Enable ProxyFix to handle X-Forwarded headers from Apache
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
app.secret_key = 'super_secret_key_musica'

def get_youtube_client():
    creds = auth_helper.get_authenticated_service()
    return build('youtube', 'v3', credentials=creds)

# --- CONFIGURACIÓN DE RUTAS ---
if os.name == 'posix':  # Linux (Servidor)
    BASE_DATA_DIR = "/var/www/home/musica"
    DOWNLOAD_TEMP = "/srv/musica/temp"
    DOWNLOAD_MP3 = "/srv/musica/mp3"
else:  # Windows (Local)
    BASE_DATA_DIR = "."
    DOWNLOAD_TEMP = "canciones"
    DOWNLOAD_MP3 = "canciones mp3"

ENLACES_FILE = os.path.join(BASE_DATA_DIR, 'enlaces_descarga.txt')
HISTORY_FILE = os.path.join(BASE_DATA_DIR, 'history.json')

def create_folders():
    """Ensure required directories exist."""
    folders = [DOWNLOAD_TEMP, DOWNLOAD_MP3, BASE_DATA_DIR]
    for folder in folders:
        if not os.path.exists(folder):
            os.makedirs(folder)
            print(f"Directorio creado: {folder}")

# Initialize required folders at startup
create_folders()

for file_path in [ENLACES_FILE, HISTORY_FILE]:
    if not os.path.exists(file_path):
        with open(file_path, 'w', encoding='utf-8') as f:
            if file_path.endswith('.json'):
                json.dump({'discarded': [], 'downloaded': []}, f)
            else:
                f.write('')
        print(f"Archivo creado: {file_path}")

# Importar downloader después de definir carpetas
import downloader
downloader.downloader.input_folder = DOWNLOAD_TEMP
downloader.downloader.output_folder = DOWNLOAD_MP3

# Almacenamiento temporal
VIDEOS_CACHE = []

def valid_url_id(url):
    """Extrae un ID único de la URL para usar como clave en el historial"""
    if 'youtube.com' in url or 'youtu.be' in url:
        # Extraer video ID de YouTube
        if 'v=' in url:
            return url.split('v=')[1].split('&')[0]
        return url
    elif 'spotify' in url:
        return url
    return url

def load_history():
    """Carga el historial de canciones descartadas y descargadas"""
    if not os.path.exists(HISTORY_FILE):
        return {'discarded': [], 'downloaded': []}
    try:
        with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    except:
        return {'discarded': [], 'downloaded': []}

def save_history(history):
    """Guarda el historial en disco"""
    with open(HISTORY_FILE, 'w', encoding='utf-8') as f:
        json.dump(history, f, indent=4)

def is_blocked(url, history=None):
    """Verifica si una URL está en el historial (descartada o descargada)"""
    if history is None:
        history = load_history()
    
    vid_id = valid_url_id(url)
    
    # Check si el ID o la URL completa están en las listas
    # Esto es simple: si la URL contiene el ID bloqueado, fuera.
    
    blocked_ids = history.get('discarded', []) + history.get('downloaded', [])
    if vid_id in blocked_ids:
        return True
    if url in blocked_ids: 
        return True
        
    return False

# Removed Google API helper as it is not needed for search.

@app.route('/')
def index():
    print(f"DEBUG: Index hit. Script Root: {request.script_root}")
    return redirect(url_for('search'))

@app.route('/spotify')
def spotify_index():
    return render_template('spotify_manual.html', title="Importar Spotify")

@app.route('/spotify/scan', methods=['POST'])
def spotify_scan():
    global VIDEOS_CACHE
    print(f"DEBUG: Headers: {dict(request.headers)}")
    print(f"DEBUG: Script Root: {request.script_root}")
    print(f"DEBUG: Path: {request.path}")
    text = request.form.get('spotify_links')
    if not text:
        return redirect(url_for('spotify_index'))
        
    # Extraer enlaces
    links = re.findall(r'https://open\.spotify\.com/track/[a-zA-Z0-9]+', text)
    links = list(set(links)) # Unicos
    
    print(f"Encontrados {len(links)} enlaces de Spotify. Escaneando...")
    
    VIDEOS_CACHE = []
    
    # Procesar
    ydl_opts = {
        'quiet': True,
        'extract_flat': True,
        'skip_download': True,
    }

    for link in links:
        try:
            print(f"DEBUG: Scanning Spotify with yt-dlp: {link}")
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                info = ydl.extract_info(link, download=False)
                if not info:
                    continue
                
                track_name = info.get('track', info.get('title', 'Desconocido'))
                artist_name = info.get('artist', info.get('uploader', 'Desconocido'))
                img_url = info.get('thumbnail', '')

                if not track_name or track_name == 'Spotify':
                     # Si yt-dlp falla en el track, usamos el title genérico
                     track_name = info.get('title', 'Desconocido')

                full_title = f"{artist_name} - {track_name}"
                print(f"DEBUG: Found {full_title}")
                
                if not is_blocked(link):
                    VIDEOS_CACHE.append({
                        'id': link,
                        'title': track_name,
                        'channel': artist_name,
                        'thumbnail': img_url,
                        'url': link,
                        'download_ref': f"ytsearch1:{full_title}"
                    })
        except Exception as e:
            print(f"Error escaneando {link}: {e}")
            # Fallback a objeto simple si falla yt-dlp
            if not is_blocked(link):
                VIDEOS_CACHE.append({
                    'id': link,
                    'title': "Link de Spotify",
                    'channel': "Desconocido",
                    'thumbnail': "",
                    'url': link,
                    'download_ref': link
                })
            
    return render_template('index.html', videos=VIDEOS_CACHE, title=f"Escaneados ({len(VIDEOS_CACHE)})", mode="spotify_scan")

@app.route('/favorites')
def fetch_favorites():
    global VIDEOS_CACHE
    try:
        youtube = get_youtube_client()
        request_likes = youtube.videos().list(
            part="snippet,contentDetails",
            myRating="like",
            maxResults=50
        )
        response = request_likes.execute()
        
        VIDEOS_CACHE = []
        history = load_history()
        
        for item in response.get('items', []):
            video_url = f"https://www.youtube.com/watch?v={item['id']}"
            if not is_blocked(video_url, history):
                VIDEOS_CACHE.append({
                    'id': item['id'],
                    'title': item['snippet']['title'],
                    'channel': item['snippet']['channelTitle'],
                    'thumbnail': item['snippet']['thumbnails'].get('high', item['snippet']['thumbnails'].get('default')).get('url'),
                    'url': video_url,
                    'download_ref': video_url
                })
        
        return render_template('index.html', videos=VIDEOS_CACHE, title="YouTube Favorites", mode="likes")
    except Exception as e:
        return render_template('error.html', error=f"Error obteniendo favoritos: {str(e)}")

# Rutas antiguas eliminadas o simplificadas
# @app.route('/spotify/login') ...
# @app.route('/spotify/callback') ...
# @app.route('/spotify/playlists') ...
# @app.route('/spotify/playlist/<playlist_id>') ...

# Non-essential routes removed to avoid errors. Use /search and /spotify/scan instead.
@app.route('/selector')
@app.route('/playlists')
def legacy_redirects():
    return redirect(url_for('search'))

# Playlists features are currently disabled.

@app.route('/search', methods=['GET', 'POST'])
def search():
    global VIDEOS_CACHE
    
    if request.method == 'POST':
        query = request.form.get('query')
        if not query:
            return redirect(url_for('search'))
            
        VIDEOS_CACHE = [] # Limpiar
        try:
            print(f"Buscando con yt-dlp: {query}...")
            ydl_opts = {
                'quiet': True,
                'extract_flat': 'in_playlist',
            }
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                result = ydl.extract_info(f"ytsearch20:{query}", download=False)
                if 'entries' in result:
                    for e in result['entries']:
                        video_url = f"https://www.youtube.com/watch?v={e['id']}"
                        if not is_blocked(video_url):
                            VIDEOS_CACHE.append({
                                'id': e['id'],
                                'title': e['title'],
                                'channel': e.get('uploader', 'Desconocido'),
                                'thumbnail': e.get('thumbnails', [{}])[-1].get('url', ''),
                                'url': video_url,
                                'download_ref': video_url
                            })
                
            return render_template('index.html', videos=VIDEOS_CACHE, title=f"Resultados: {query}", mode="search")
        except Exception as e:
            return render_template('error.html', error=f"Error en búsqueda: {str(e)}")
            
    # GET request: Mostrar barra de búsqueda vacía o resultados anteriores
    return render_template('index.html', videos=[], title="Buscador", mode="search_input")

# Removed unused fetch_videos and reload_videos.

@app.route('/save', methods=['POST'])
def save_selection():
    data = request.json
    selected_urls = data.get('urls', [])
    
    if not selected_urls:
        return jsonify({'status': 'error', 'message': 'No hay URLs para guardar'})

    # Guardar en archivo para descarga
    with open(ENLACES_FILE, 'a', encoding='utf-8') as f: 
        for url in selected_urls:
            f.write(url + '\n')
            
    # Marcar como descargados en historial
    history = load_history()
    for url in selected_urls:
        vid_id = valid_url_id(url)
        if vid_id not in history['downloaded']:
             history['downloaded'].append(vid_id)
    save_history(history)
            
    return jsonify({'status': 'success', 'count': len(selected_urls)})

@app.route('/api/discard', methods=['POST'])
def discard_video():
    data = request.json
    url = data.get('url')
    if not url:
        return jsonify({'status': 'error'})
        
    history = load_history()
    vid_id = valid_url_id(url)
    
    if vid_id not in history['discarded']:
        history['discarded'].append(vid_id)
        save_history(history)
        
    return jsonify({'status': 'success'})

@app.route('/api/reset_history', methods=['POST'])
def reset_history():
    history = {'discarded': [], 'downloaded': []}
    save_history(history)
    return jsonify({'status': 'success', 'message': 'Historial reiniciado. Las canciones ocultas volverán a aparecer.'})

import downloader

@app.route('/downloads')
def downloads_page():
    return render_template('downloader.html')

@app.route('/api/start_download', methods=['POST'])
def start_download():
    # Leer archivo
    try:
        if not os.path.exists(ENLACES_FILE):
             return jsonify({'status': 'error', 'message': 'No hay lista de enlaces para descargar.'})
             
        with open(ENLACES_FILE, 'r', encoding='utf-8') as f:
            urls = [line.strip() for line in f if line.strip()]
            
        if not urls:
            return jsonify({'status': 'error', 'message': 'La lista de enlaces está vacía.'})
            
        if downloader.downloader.start_download(urls):
            return jsonify({'status': 'success', 'message': 'Descarga iniciada'})
        else:
            return jsonify({'status': 'error', 'message': 'Ya hay una descarga en curso'})
            
    except Exception as e:
        return jsonify({'status': 'error', 'message': str(e)})

@app.route('/api/clear', methods=['POST'])
def clear_list():
    try:
        with open(ENLACES_FILE, 'w', encoding='utf-8') as f:
            f.write('')
        return jsonify({'status': 'success', 'message': 'Lista vaciada.'})
    except Exception as e:
        return jsonify({'status': 'error', 'message': str(e)})

@app.route('/api/status')
def download_status():
    pending_count = 0
    if os.path.exists(ENLACES_FILE):
         with open(ENLACES_FILE, 'r', encoding='utf-8') as f:
             pending_count = len([line for line in f if line.strip()])
             
    return jsonify({
        'is_downloading': downloader.downloader.is_downloading,
        'logs': downloader.downloader.log_messages,
        'progress': downloader.downloader.current_progress,
        'finished': downloader.downloader.finished_files,
        'total': downloader.downloader.total_files,
        'pending_in_file': pending_count
    })

if __name__ == '__main__':
    print("Iniciando servidor... Abre http://127.0.0.1:5000")
    app.run(debug=False, port=5000)
