"""
Live Classes routes for video conferencing and course-based live sessions
"""
import json
import logging
import uuid
from datetime import datetime, timedelta
from flask import Blueprint, request, jsonify
from utils import (require_api_key, format_api_response, 
                   create_error_response, get_db_connection, fetch_as_dict)
from auth.jwt_manager import require_auth, optional_auth
from flask import g

logger = logging.getLogger(__name__)
live_classes_bp = Blueprint('live_classes', __name__)


@live_classes_bp.route('/api/live-classes/user/<user_id>', methods=['GET', 'OPTIONS'])
@require_api_key
@optional_auth
def get_user_live_classes(user_id):
    """Get all live classes for a user based on their course enrollments"""
    # Handle OPTIONS request for CORS preflight
    if request.method == 'OPTIONS':
        return '', 200
        
    try:
        with get_db_connection() as conn:
            cursor = conn.cursor(buffered=True)
            
            # Get user's enrolled courses and their live classes
            query = """
            SELECT 
                lc.id,
                lc.course_id,
                lc.title,
                lc.description,
                lc.scheduled_start_time,
                lc.scheduled_end_time,
                lc.actual_start_time,
                lc.actual_end_time,
                lc.jitsi_room_name,
                lc.max_participants,
                lc.status,
                lc.recording_enabled,
                lc.recording_url,
                lc.thumbnail_url,
                lc.is_public,
                COALESCE(lc.stream_type, 'jitsi') as stream_type,
                lc.youtube_url,
                lc.socket_room_id,
                c.title as course_title,
                c.image_url as course_thumbnail,
                u.username as instructor_name,
                u.email as instructor_email,
                COUNT(DISTINCT lcp.user_id) as participant_count,
                CASE WHEN lcp_user.user_id IS NOT NULL THEN 1 ELSE 0 END as is_registered
            FROM live_classes lc
            JOIN courses c ON lc.course_id = c.id
            JOIN user u ON lc.instructor_id = u.id
            LEFT JOIN live_class_participants lcp ON lc.id = lcp.live_class_id
            LEFT JOIN live_class_participants lcp_user ON lc.id = lcp_user.live_class_id AND lcp_user.user_id = %s
            WHERE lc.course_id IN (
                SELECT e.course_id FROM enrollments e WHERE e.user_id = %s AND e.payment_status IN ('free', 'paid')
            )
            AND lc.status != 'cancelled'
            GROUP BY lc.id
            ORDER BY 
                CASE lc.status 
                    WHEN 'live' THEN 1 
                    WHEN 'scheduled' THEN 2 
                    WHEN 'completed' THEN 3 
                END,
                lc.scheduled_start_time ASC
            """
            
            cursor.execute(query, (user_id, user_id))
            live_classes = fetch_as_dict(cursor)
            
            # Format datetime objects for JSON serialization
            for live_class in live_classes:
                for field in ['scheduled_start_time', 'scheduled_end_time', 'actual_start_time', 'actual_end_time']:
                    if live_class[field]:
                        live_class[field] = live_class[field].isoformat()
                        
                # Calculate if class is starting soon (within 30 minutes)
                if live_class['scheduled_start_time']:
                    start_time = datetime.fromisoformat(live_class['scheduled_start_time'])
                    now = datetime.now()
                    time_diff = start_time - now
                    live_class['starting_soon'] = 0 <= time_diff.total_seconds() <= 1800  # 30 minutes
                    live_class['can_join'] = live_class['status'] == 'live' or live_class['starting_soon']
                else:
                    live_class['starting_soon'] = False
                    live_class['can_join'] = live_class['status'] == 'live'
            
            return format_api_response(
                data=live_classes,
                message="Live classes retrieved successfully",
                include_legacy_fields=live_classes
            )
            
    except Exception as e:
        logger.error(f"Error fetching live classes for user {user_id}: {e}")
        return create_error_response(
            message="Failed to fetch live classes",
            status_code=500
        )


@live_classes_bp.route('/api/live-classes/<class_id>/join', methods=['POST', 'OPTIONS'])
@require_api_key
@require_auth
def join_live_class(class_id):
    """Join a live class - register user as participant"""
    # Handle OPTIONS request for CORS preflight
    if request.method == 'OPTIONS':
        return '', 200
        
    user_id = None
    try:
        user_id = g.current_user_id
        
        with get_db_connection() as conn:
            cursor = conn.cursor(buffered=True)
            
            # First, get basic live class info including stream type
            class_query = """
            SELECT 
                lc.id,
                lc.course_id,
                lc.status,
                lc.max_participants,
                lc.scheduled_start_time,
                lc.jitsi_room_name,
                lc.jitsi_room_password,
                COALESCE(lc.stream_type, 'jitsi') as stream_type,
                lc.youtube_url,
                lc.socket_room_id
            FROM live_classes lc
            WHERE lc.id = %s
            """
            
            cursor.execute(class_query, (class_id,))
            class_info = cursor.fetchone()
            
            if not class_info:
                return create_error_response("Live class not found", 404)
                
            # Check if user is enrolled in the course
            course_id = class_info[1]
            cursor.execute("SELECT id FROM enrollments WHERE user_id = %s AND course_id = %s AND payment_status IN ('free', 'paid')", (user_id, course_id))
            enrollment = cursor.fetchone()
            
            if not enrollment:
                return create_error_response("You are not enrolled in this course", 403)
                
            # Check if class is available for joining
            if class_info[2] not in ['scheduled', 'live']:
                return create_error_response("Live class is not available for joining", 400)
            
            # Register user as participant
            participant_query = """
            INSERT INTO live_class_participants 
            (live_class_id, user_id, joined_at, can_use_chat) 
            VALUES (%s, %s, %s, 1)
            ON DUPLICATE KEY UPDATE 
            joined_at = VALUES(joined_at)
            """
            
            cursor.execute(participant_query, (class_id, user_id, datetime.now()))
            conn.commit()
            
            # Extract stream type and related info
            stream_type = class_info[7] or 'jitsi'
            youtube_url = class_info[8]
            socket_room_id = class_info[9] or f'live_class_{class_id}'
            
            # Build join info based on stream type
            if stream_type == 'youtube':
                # YouTube live stream
                join_info = {
                    'stream_type': 'youtube',
                    'youtube_url': youtube_url,
                    'socket_room_id': socket_room_id,
                    'class_id': class_id,
                    'can_join': True,
                    'join_url': f"/dashboard/live-classes/{class_id}/youtube-room"
                }
            else:
                # Jitsi interactive class (default)
                join_info = {
                    'stream_type': 'jitsi',
                    'room_name': class_info[5],  # jitsi_room_name
                    'room_password': class_info[6],  # jitsi_room_password
                    'class_id': class_id,
                    'can_join': True,
                    'join_url': f"/dashboard/live-classes/{class_id}/room"
                }
            
            return format_api_response(
                data=join_info,
                message="Successfully joined live class",
                include_legacy_fields=join_info
            )
            
    except Exception as e:
        logger.error(f"Error joining live class {class_id} for user {user_id or 'unknown'}: {e}")
        return create_error_response(
            message="Failed to join live class",
            status_code=500
        )


@live_classes_bp.route('/api/live-classes/<class_id>/leave', methods=['POST', 'OPTIONS'])
@require_api_key
@require_auth
def leave_live_class(class_id):
    """Leave a live class - update participant record"""
    # Handle OPTIONS request for CORS preflight
    if request.method == 'OPTIONS':
        return '', 200
        
    user_id = None
    try:
        user_id = g.current_user_id
        
        with get_db_connection() as conn:
            cursor = conn.cursor(buffered=True)
            
            # Update participant record
            leave_query = """
            UPDATE live_class_participants 
            SET left_at = %s,
                attendance_duration = TIMESTAMPDIFF(MINUTE, joined_at, %s)
            WHERE live_class_id = %s AND user_id = %s
            """
            
            now = datetime.now()
            cursor.execute(leave_query, (now, now, class_id, user_id))
            conn.commit()
            
            return format_api_response(
                data={'left_at': now.isoformat()},
                message="Successfully left live class",
                include_legacy_fields={'left_at': now.isoformat()}
            )
            
    except Exception as e:
        logger.error(f"Error leaving live class {class_id} for user {user_id or 'unknown'}: {e}")
        return create_error_response(
            message="Failed to leave live class",
            status_code=500
        )


@live_classes_bp.route('/api/live-classes/<class_id>/chat', methods=['GET', 'OPTIONS'])
@require_api_key
@require_auth
def get_live_class_chat(class_id):
    """Get chat messages for a live class"""
    # Handle OPTIONS request for CORS preflight
    if request.method == 'OPTIONS':
        return '', 200
        
    user_id = None
    try:
        user_id = g.current_user_id
        
        with get_db_connection() as conn:
            cursor = conn.cursor(buffered=True)
            
            # Check if user has access to this class
            access_query = """
            SELECT 1 FROM live_class_participants 
            WHERE live_class_id = %s AND user_id = %s
            """
            cursor.execute(access_query, (class_id, user_id))
            if not cursor.fetchone():
                return create_error_response("Access denied", 403)
            
            # Get chat messages
            chat_query = """
            SELECT 
                lcc.id,
                lcc.message,
                lcc.message_type,
                lcc.file_url,
                lcc.reply_to_message_id,
                lcc.is_private,
                lcc.created_at,
                u.username,
                u.profile_img_url
            FROM live_class_chat lcc
            JOIN user u ON lcc.user_id = u.id
            WHERE lcc.live_class_id = %s 
            AND (lcc.is_private = 0 OR lcc.user_id = %s OR lcc.private_to_user_id = %s)
            ORDER BY lcc.created_at ASC
            LIMIT 100
            """
            
            cursor.execute(chat_query, (class_id, user_id, user_id))
            messages = fetch_as_dict(cursor)
            
            # Format datetime
            for message in messages:
                message['created_at'] = message['created_at'].isoformat()
            
            return format_api_response(
                data=messages,
                message="Chat messages retrieved successfully",
                include_legacy_fields=messages
            )
            
    except Exception as e:
        logger.error(f"Error fetching chat for live class {class_id}: {e}")
        return create_error_response(
            message="Failed to fetch chat messages",
            status_code=500
        )


@live_classes_bp.route('/api/live-classes/<class_id>/chat', methods=['POST', 'OPTIONS'])
@require_api_key
@require_auth
def send_chat_message(class_id):
    """Send a chat message in live class"""
    # Handle OPTIONS request for CORS preflight
    if request.method == 'OPTIONS':
        return '', 200
        
    user_id = None
    try:
        user_id = g.current_user_id
        data = request.get_json()
        
        message = data.get('message', '').strip()
        message_type = data.get('message_type', 'text')
        reply_to = data.get('reply_to_message_id')
        is_private = data.get('is_private', False)
        private_to_user_id = data.get('private_to_user_id')
        
        if not message:
            return create_error_response("Message cannot be empty", 400)
        
        with get_db_connection() as conn:
            cursor = conn.cursor(buffered=True)
            
            # Check if user has chat permission
            permission_query = """
            SELECT can_use_chat FROM live_class_participants 
            WHERE live_class_id = %s AND user_id = %s
            """
            cursor.execute(permission_query, (class_id, user_id))
            permission = cursor.fetchone()
            
            if not permission or not permission[0]:
                return create_error_response("Chat permission denied", 403)
            
            # Insert chat message
            insert_query = """
            INSERT INTO live_class_chat 
            (live_class_id, user_id, message, message_type, reply_to_message_id, 
             is_private, private_to_user_id) 
            VALUES (%s, %s, %s, %s, %s, %s, %s)
            """
            
            cursor.execute(insert_query, (
                class_id, user_id, message, message_type, reply_to,
                is_private, private_to_user_id
            ))
            
            message_id = cursor.lastrowid
            conn.commit()
            
            return format_api_response(
                data={'message_id': message_id, 'created_at': datetime.now().isoformat()},
                message="Message sent successfully",
                include_legacy_fields={'message_id': message_id, 'created_at': datetime.now().isoformat()}
            )
            
    except Exception as e:
        logger.error(f"Error sending chat message in live class {class_id}: {e}")
        return create_error_response(
            message="Failed to send message",
            status_code=500
        )


@live_classes_bp.route('/api/live-classes/<class_id>/resources', methods=['GET', 'OPTIONS'])
@require_api_key
@require_auth
def get_live_class_resources(class_id):
    """Get resources for a live class using existing resources table"""
    user_id = None
    try:
        user_id = g.current_user_id
        
        with get_db_connection() as conn:
            cursor = conn.cursor(buffered=True)
            
            # Check access and get course_id
            access_query = """
            SELECT lc.course_id FROM live_classes lc
            JOIN live_class_participants lcp ON lc.id = lcp.live_class_id
            WHERE lc.id = %s AND lcp.user_id = %s
            """
            cursor.execute(access_query, (class_id, user_id))
            result = cursor.fetchone()
            
            if not result:
                return create_error_response("Access denied", 403)
                
            course_id = result[0]
            
            # Get resources for this course
            resources_query = """
            SELECT 
                r.id,
                r.title,
                r.type,
                r.resource_url,
                r.created_at,
                t.title as topic_title
            FROM resources r
            LEFT JOIN topics t ON r.topic_id = t.id
            WHERE r.course_id = %s
            ORDER BY r.created_at DESC
            """
            
            cursor.execute(resources_query, (course_id,))
            resources = fetch_as_dict(cursor)
            
            # Format datetime
            for resource in resources:
                resource['created_at'] = resource['created_at'].isoformat()
            
            return format_api_response(
                data=resources,
                message="Live class resources retrieved successfully",
                include_legacy_fields=resources
            )
            
    except Exception as e:
        logger.error(f"Error fetching resources for live class {class_id}: {e}")
        return create_error_response(
            message="Failed to fetch resources",
            status_code=500
        )


@live_classes_bp.route('/api/live-classes/<class_id>/details', methods=['GET', 'OPTIONS'])
@require_api_key
@optional_auth
def get_live_class_details(class_id):
    """Get detailed information about a specific live class"""
    try:
        with get_db_connection() as conn:
            cursor = conn.cursor(buffered=True)
            
            # Get live class details
            details_query = """
            SELECT 
                lc.id,
                lc.course_id,
                lc.title,
                lc.description,
                lc.scheduled_start_time,
                lc.scheduled_end_time,
                lc.actual_start_time,
                lc.actual_end_time,
                lc.jitsi_room_name,
                lc.max_participants,
                lc.status,
                lc.recording_enabled,
                lc.recording_url,
                lc.thumbnail_url,
                lc.is_public,
                COALESCE(lc.stream_type, 'jitsi') as stream_type,
                lc.youtube_url,
                lc.socket_room_id,
                c.title as course_title,
                c.description as course_description,
                c.image_url as course_thumbnail,
                u.username as instructor_name,
                u.email as instructor_email,
                u.profile_img_url as instructor_avatar,
                COUNT(DISTINCT lcp.user_id) as participant_count
            FROM live_classes lc
            JOIN courses c ON lc.course_id = c.id
            JOIN user u ON lc.instructor_id = u.id
            LEFT JOIN live_class_participants lcp ON lc.id = lcp.live_class_id
            WHERE lc.id = %s
            GROUP BY lc.id
            """
            
            cursor.execute(details_query, (class_id,))
            details = cursor.fetchone()
            
            if not details:
                return create_error_response("Live class not found", 404)
            
            # Convert to dict and format datetime
            details_dict = {
                'id': details[0],
                'course_id': details[1],
                'title': details[2],
                'description': details[3],
                'scheduled_start_time': details[4].isoformat() if details[4] else None,
                'scheduled_end_time': details[5].isoformat() if details[5] else None,
                'actual_start_time': details[6].isoformat() if details[6] else None,
                'actual_end_time': details[7].isoformat() if details[7] else None,
                'jitsi_room_name': details[8],
                'max_participants': details[9],
                'status': details[10],
                'recording_enabled': bool(details[11]),
                'recording_url': details[12],
                'thumbnail_url': details[13],
                'is_public': bool(details[14]),
                'stream_type': details[15] or 'jitsi',
                'youtube_url': details[16],
                'socket_room_id': details[17] or f'live_class_{details[0]}',
                'course': {
                    'title': details[18],
                    'description': details[19],
                    'thumbnail_url': details[20]
                },
                'instructor': {
                    'name': details[21],
                    'email': details[22],
                    'avatar': details[23]
                },
                'participant_count': details[24]
            }
            
            return format_api_response(
                data=details_dict,
                message="Live class details retrieved successfully",
                include_legacy_fields=details_dict
            )
            
    except Exception as e:
        logger.error(f"Error fetching details for live class {class_id}: {e}")
        return create_error_response(
            message="Failed to fetch live class details",
            status_code=500
        )
