# Monkey patch MUST be first - before any other imports!
import eventlet
eventlet.monkey_patch()

import os
from flask import Flask, send_from_directory, jsonify, request, session
from flask_socketio import SocketIO, emit
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
import downloader

# Relay State
broadcast_state = {
    'active': False
}
listener_count = 0
MUSIC_FOLDER = "music"
# Ensure music folder exists
if not os.path.exists(MUSIC_FOLDER):
    os.makedirs(MUSIC_FOLDER)

# Helper for shared routes
def setup_shared_routes(app):
    @app.route('/library.json')
    def get_library():
        library = []
        if os.path.exists(MUSIC_FOLDER):
            for filename in sorted(os.listdir(MUSIC_FOLDER)):
                if filename.lower().endswith(('.mp3', '.m4a', '.wav', '.flac', '.ogg')):
                    library.append({
                        "title": os.path.splitext(filename)[0],
                        "file": f"music/{filename}"
                    })
        return jsonify(library)

    @app.route('/download', methods=['POST'])
    def download():
        data = request.json
        url = data.get('url')
        quality = data.get('quality', '320')
        if not url:
            return jsonify({"success": False, "error": "No URL provided"}), 400
        result = downloader.download_mp3(url, quality)
        return jsonify(result)

    @app.route('/search_youtube', methods=['GET'])
    def search_youtube():
        query = request.args.get('q', '')
        if not query:
            return jsonify({"success": False, "error": "No query provided"}), 400
        
        # Get API key from environment variable
        api_key = os.environ.get('YOUTUBE_API_KEY', '')
        if not api_key:
            return jsonify({
                "success": False, 
                "error": "YouTube API key not configured. Set YOUTUBE_API_KEY environment variable."
            }), 500
        
        try:
            import requests
            # Search YouTube using Data API v3
            url = 'https://www.googleapis.com/youtube/v3/search'
            params = {
                'part': 'snippet',
                'q': query,
                'type': 'video',
                'videoCategoryId': '10',  # Music category
                'maxResults': 20,
                'key': api_key
            }
            
            response = requests.get(url, params=params)
            data = response.json()
            
            if 'error' in data:
                return jsonify({
                    "success": False,
                    "error": data['error'].get('message', 'YouTube API error')
                }), 400
            
            # Format results
            results = []
            for item in data.get('items', []):
                results.append({
                    'videoId': item['id']['videoId'],
                    'title': item['snippet']['title'],
                    'channel': item['snippet']['channelTitle'],
                    'thumbnail': item['snippet']['thumbnails']['medium']['url'],
                    'url': f"https://www.youtube.com/watch?v={item['id']['videoId']}"
                })
            
            return jsonify({"success": True, "results": results})
            
        except Exception as e:
            return jsonify({"success": False, "error": str(e)}), 500

    @app.route('/<path:filename>')
    def serve_static(filename):
        response = send_from_directory('.', filename)
        if filename.endswith(('.css', '.js', '.html')):
            response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
        return response

    @app.route('/')
    def index():
        return send_from_directory('.', 'index.html')

# === DJ SERVER (Port 5000) ===
dj_app = Flask(__name__, static_folder='.', static_url_path='')
dj_app.config['SECRET_KEY'] = 'dj_panel_secret'
setup_shared_routes(dj_app)
dj_socketio = SocketIO(
    dj_app, 
    cors_allowed_origins="*", 
    async_mode='eventlet',
    max_http_buffer_size=1e8, # 100MB buffer
    ping_timeout=10, 
    ping_interval=5,
    logger=False,
    engineio_logger=False
)

@dj_socketio.on('connect')
def dj_connect():
    print(f"🎧 DJ connected: {request.sid}")
    session['is_dj'] = True

@dj_socketio.on('disconnect')
def dj_disconnect():
    if session.get('is_dj'):
        print("⚠️ DJ disconnected - broadcast will continue until manually stopped")
        session['is_dj'] = False
        # Don't stop streaming_active - let it continue
        # Broadcast will resume when DJ reconnects

def stop_broadcast_after_timeout():
    """No longer used - broadcasts don't auto-stop"""
    pass

@dj_socketio.on('start_broadcast')
def dj_start():
    broadcast_state['active'] = True
    session['is_dj'] = True
    print("🎙️ Broadcast -> ACTIVE")
    
    listener_socketio.emit('broadcast_started', namespace='/')
    listener_socketio.emit('stream_status', {'active': True}, namespace='/')

@dj_socketio.on('stop_broadcast')
def dj_stop():
    broadcast_state['active'] = False
    session['is_dj'] = False
    print("🛑 DJ stopped broadcasting")
    
    listener_socketio.emit('broadcast_stopped', namespace='/')
    listener_socketio.emit('stream_status', {'active': False}, namespace='/')

@dj_socketio.on('audio_chunk')
def dj_audio(data):
    # Relay audio chunk to all listeners immediately
    if broadcast_state['active']:
        listener_socketio.emit('audio_data', data, namespace='/')

# === LISTENER SERVER (Port 6000) ===
listener_app = Flask(__name__, static_folder='.', static_url_path='')
listener_app.config['SECRET_KEY'] = 'listener_secret'
setup_shared_routes(listener_app)
listener_socketio = SocketIO(
    listener_app, 
    cors_allowed_origins="*", 
    async_mode='eventlet',
    max_http_buffer_size=1e8, # 100MB buffer
    ping_timeout=10, 
    ping_interval=5,
    logger=False,
    engineio_logger=False
)

@listener_socketio.on('connect')
def listener_connect():
    print(f"👂 Listener Socket Connected: {request.sid}")

@listener_socketio.on('disconnect')
def listener_disconnect():
    global listener_count
    if session.get('is_listener'):
        # Clear session flag FIRST to prevent re-entry issues
        session['is_listener'] = False
        listener_count = max(0, listener_count - 1)
        print(f"❌ Listener left. Total: {listener_count}")
        # Broadcast to all listeners
        listener_socketio.emit('listener_count', {'count': listener_count}, namespace='/')
        # Broadcast to all DJs
        dj_socketio.emit('listener_count', {'count': listener_count}, namespace='/')

@listener_socketio.on('join_listener')
def listener_join():
    global listener_count
    if not session.get('is_listener'):
        session['is_listener'] = True
        listener_count += 1
        print(f"👂 New listener joined. Total: {listener_count}")
        # Broadcast to all listeners
        listener_socketio.emit('listener_count', {'count': listener_count}, namespace='/')
        # Broadcast to all DJs
        dj_socketio.emit('listener_count', {'count': listener_count}, namespace='/')
    
    emit('stream_status', {'active': broadcast_state['active']})

@listener_socketio.on('request_header')
def handle_request_header():
    # Header logic removed for local relay mode
    pass

@listener_socketio.on('get_listener_count')
def listener_get_count():
    emit('listener_count', {'count': listener_count})

# DJ Panel Routes (No engine commands needed in local mode)
@dj_socketio.on('get_mixer_status')
def get_mixer_status():
    pass

@dj_socketio.on('audio_sync_queue')
def audio_sync_queue(data):
    pass


if __name__ == '__main__':
    print("=" * 50)
    print("🎧 TECHDJ PRO - DUAL PORT ARCHITECTURE")
    print("=" * 50)
    print("👉 DJ PANEL:    http://localhost:5000")
    print("👉 LISTEN PAGE: http://localhost:5001")
    print("=" * 50)
    
    # Audio engine DISABLED
    print("✅ Local Radio server ready")
    
    # Run both servers using eventlet's spawn
    eventlet.spawn(dj_socketio.run, dj_app, host='0.0.0.0', port=5000, debug=False)
    listener_socketio.run(listener_app, host='0.0.0.0', port=5001, debug=False)
