"""
Flask routes for web dashboard
"""

import logging
from datetime import datetime
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, flash, session
from flask_login import login_required, current_user, login_user, logout_user
from werkzeug.security import check_password_hash

from .auth import AuthenticatedUser

logger = logging.getLogger(__name__)

# Blueprint definitions
main_bp = Blueprint('main', __name__)
auth_bp = Blueprint('auth', __name__)
api_bp = Blueprint('api', __name__)

# These will be set by the app.py when registering blueprints
main_bp.db_manager = None
main_bp.config_manager = None  
main_bp.message_bus = None

auth_bp.auth_manager = None
auth_bp.db_manager = None

api_bp.api = None
api_bp.db_manager = None
api_bp.config_manager = None
api_bp.message_bus = None


# Main routes
@main_bp.route('/')
@login_required
def index():
    """Dashboard home page"""
    try:
        return render_template('dashboard/index.html', 
                             user=current_user,
                             page_title="Dashboard")
    except Exception as e:
        logger.error(f"Dashboard index error: {e}")
        flash("Error loading dashboard", "error")
        return render_template('errors/500.html'), 500


@main_bp.route('/video')
@login_required
def video_control_page():
    """Video control page"""
    try:
        return render_template('dashboard/video.html',
                             user=current_user,
                             page_title="Video Control")
    except Exception as e:
        logger.error(f"Video control page error: {e}")
        flash("Error loading video control", "error")
        return render_template('errors/500.html'), 500


@main_bp.route('/templates')
@login_required
def templates():
    """Template management page"""
    try:
        return render_template('dashboard/templates.html',
                             user=current_user,
                             page_title="Templates")
    except Exception as e:
        logger.error(f"Templates page error: {e}")
        flash("Error loading templates", "error")
        return render_template('errors/500.html'), 500


@main_bp.route('/config')
@login_required
def configuration():
    """Configuration page"""
    try:
        if not current_user.is_admin:
            flash("Admin access required", "error")
            return redirect(url_for('main.index'))
        
        return render_template('dashboard/config.html',
                             user=current_user,
                             page_title="Configuration")
    except Exception as e:
        logger.error(f"Configuration page error: {e}")
        flash("Error loading configuration", "error")
        return render_template('errors/500.html'), 500


@main_bp.route('/users')
@login_required
def users():
    """User management page"""
    try:
        if not current_user.is_admin:
            flash("Admin access required", "error")
            return redirect(url_for('main.index'))
        
        return render_template('dashboard/users.html',
                             user=current_user,
                             page_title="User Management")
    except Exception as e:
        logger.error(f"Users page error: {e}")
        flash("Error loading user management", "error")
        return render_template('errors/500.html'), 500


@main_bp.route('/tokens')
@login_required
def api_tokens():
    """API token management page"""
    try:
        return render_template('dashboard/tokens.html',
                             user=current_user,
                             page_title="API Tokens")
    except Exception as e:
        logger.error(f"API tokens page error: {e}")
        flash("Error loading API tokens", "error")
        return render_template('errors/500.html'), 500


@main_bp.route('/logs')
@login_required
def logs():
    """Application logs page"""
    try:
        if not current_user.is_admin:
            flash("Admin access required", "error")
            return redirect(url_for('main.index'))
        
        return render_template('dashboard/logs.html',
                             user=current_user,
                             page_title="Application Logs")
    except Exception as e:
        logger.error(f"Logs page error: {e}")
        flash("Error loading logs", "error")
        return render_template('errors/500.html'), 500


# Auth routes
@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
    """Login page"""
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))
    
    if request.method == 'POST':
        try:
            username = request.form.get('username', '').strip()
            password = request.form.get('password', '')
            remember_me = request.form.get('remember_me', False)
            
            if not username or not password:
                flash("Username and password are required", "error")
                return render_template('auth/login.html')
            
            # Authenticate user
            authenticated_user = auth_bp.auth_manager.authenticate_user(username, password)
            
            if authenticated_user:
                login_user(authenticated_user, remember=remember_me)
                logger.info(f"User logged in: {username}")
                
                # Redirect to next page or dashboard
                next_page = request.args.get('next')
                if next_page:
                    return redirect(next_page)
                else:
                    return redirect(url_for('main.index'))
            else:
                flash("Invalid username or password", "error")
                return render_template('auth/login.html')
                
        except Exception as e:
            logger.error(f"Login error: {e}")
            flash("Login failed. Please try again.", "error")
            return render_template('auth/login.html')
    
    return render_template('auth/login.html')
    
    
@main_bp.route('/video_test')
@login_required
def video_test():
    """Video upload test page"""
    try:
        return render_template('dashboard/video_test.html',
                             user=current_user,
                             page_title="Video Upload Test")
    except Exception as e:
        logger.error(f"Video test page error: {e}")
        flash("Error loading video test page", "error")
        return render_template('errors/500.html'), 500


@auth_bp.route('/logout')
@login_required
def logout():
    """Logout user"""
    try:
        username = current_user.username
        logout_user()
        logger.info(f"User logged out: {username}")
        flash("You have been logged out", "info")
    except Exception as e:
        logger.error(f"Logout error: {e}")
    
    return redirect(url_for('auth.login'))


@auth_bp.route('/change-password', methods=['GET', 'POST'])
@login_required
def change_password():
    """Change password page"""
    if request.method == 'POST':
        try:
            current_password = request.form.get('current_password', '')
            new_password = request.form.get('new_password', '')
            confirm_password = request.form.get('confirm_password', '')
            
            if not all([current_password, new_password, confirm_password]):
                flash("All fields are required", "error")
                return render_template('auth/change_password.html')
            
            if new_password != confirm_password:
                flash("New passwords do not match", "error")
                return render_template('auth/change_password.html')
            
            if len(new_password) < 6:
                flash("Password must be at least 6 characters", "error")
                return render_template('auth/change_password.html')
            
            # Change password
            success = auth_bp.auth_manager.change_password(
                current_user.id, current_password, new_password
            )
            
            if success:
                flash("Password changed successfully", "success")
                return redirect(url_for('main.index'))
            else:
                flash("Current password is incorrect", "error")
                return render_template('auth/change_password.html')
                
        except Exception as e:
            logger.error(f"Change password error: {e}")
            flash("Failed to change password", "error")
            return render_template('auth/change_password.html')
    
    return render_template('auth/change_password.html')


# API routes
@api_bp.route('/status')
def system_status():
    """Get system status"""
    try:
        status = api_bp.api.get_system_status()
        return jsonify(status)
    except Exception as e:
        logger.error(f"API status error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/video/status')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def video_status():
    """Get video player status"""
    try:
        status = api_bp.api.get_video_status()
        return jsonify(status)
    except Exception as e:
        logger.error(f"API video status error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/video/control', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def video_control():
    """Control video player"""
    try:
        data = request.get_json() or {}
        action = data.get('action')
        
        if not action:
            return jsonify({"error": "Action is required"}), 400
        
        # Remove action from data to avoid duplicate argument error
        control_data = {k: v for k, v in data.items() if k != 'action'}
        result = api_bp.api.control_video(action, **control_data)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API video control error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/overlay', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def update_overlay():
    """Update video overlay"""
    try:
        data = request.get_json() or {}
        template = data.get('template')
        overlay_data = data.get('data', {})
        
        if not template:
            return jsonify({"error": "Template is required"}), 400
        
        result = api_bp.api.update_overlay(template, overlay_data)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API overlay update error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/templates')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def get_templates():
    """Get available templates"""
    try:
        templates = api_bp.api.get_templates()
        return jsonify(templates)
    except Exception as e:
        logger.error(f"API get templates error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/config')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def get_configuration():
    """Get configuration"""
    try:
        section = request.args.get('section')
        config = api_bp.api.get_configuration(section)
        return jsonify(config)
    except Exception as e:
        logger.error(f"API get configuration error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/config/<section>')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def get_config_section(section):
    """Get configuration section"""
    try:
        config = api_bp.api.get_configuration(section)
        return jsonify(config)
    except Exception as e:
        logger.error(f"API get config section error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/config/<section>', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def update_config_section(section):
    """Update configuration section"""
    try:
        data = request.get_json() or {}
        result = api_bp.api.update_configuration(section, data)
        return jsonify(result)
    except Exception as e:
        logger.error(f"API update config section error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/config', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def update_configuration():
    """Update configuration"""
    try:
        data = request.get_json() or {}
        section = data.get('section')
        config_data = data.get('config')
        
        if not section or not config_data:
            return jsonify({"error": "Section and config data are required"}), 400
        
        result = api_bp.api.update_configuration(section, config_data)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API update configuration error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/users')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def get_users():
    """Get all users"""
    try:
        users = api_bp.api.get_users()
        return jsonify(users)
    except Exception as e:
        logger.error(f"API get users error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/users', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def create_user():
    """Create new user"""
    try:
        data = request.get_json() or {}
        username = data.get('username', '').strip()
        email = data.get('email', '').strip()
        password = data.get('password', '')
        is_admin = data.get('is_admin', False)
        
        if not all([username, email, password]):
            return jsonify({"error": "Username, email, and password are required"}), 400
        
        result = api_bp.api.create_user(username, email, password, is_admin)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API create user error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/users/<int:user_id>', methods=['PUT'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def update_user(user_id):
    """Update user"""
    try:
        data = request.get_json() or {}
        username = data.get('username')
        email = data.get('email')
        password = data.get('password')
        is_admin = data.get('is_admin')
        
        result = api_bp.api.update_user(user_id, username, email, password, is_admin)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API update user error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/users/<int:user_id>', methods=['DELETE'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def delete_user(user_id):
    """Delete user"""
    try:
        result = api_bp.api.delete_user(user_id)
        return jsonify(result)
    except Exception as e:
        logger.error(f"API delete user error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/tokens')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def get_api_tokens():
    """Get API tokens for current user"""
    try:
        user_id = getattr(current_user, 'id', None) or getattr(request, 'current_user', {}).get('user_id')
        
        if not user_id:
            return jsonify({"error": "User not authenticated"}), 401
        
        tokens = api_bp.api.get_api_tokens(user_id)
        return jsonify(tokens)
        
    except Exception as e:
        logger.error(f"API get tokens error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/tokens', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def create_api_token():
    """Create API token"""
    try:
        data = request.get_json() or {}
        token_name = data.get('name', '').strip()
        expires_hours = data.get('expires_hours', 8760)  # 1 year default
        
        if not token_name:
            return jsonify({"error": "Token name is required"}), 400
        
        user_id = getattr(current_user, 'id', None) or getattr(request, 'current_user', {}).get('user_id')
        
        if not user_id:
            return jsonify({"error": "User not authenticated"}), 401
        
        result = api_bp.api.create_api_token(user_id, token_name, expires_hours)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API create token error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/tokens/<int:token_id>', methods=['DELETE'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def revoke_api_token(token_id):
    """Revoke API token"""
    try:
        user_id = getattr(current_user, 'id', None) or getattr(request, 'current_user', {}).get('user_id')
        
        if not user_id:
            return jsonify({"error": "User not authenticated"}), 401
        
        result = api_bp.api.revoke_api_token(user_id, token_id)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API revoke token error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/logs')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def get_logs():
    """Get application logs"""
    try:
        level = request.args.get('level', 'INFO')
        limit = int(request.args.get('limit', 100))
        
        logs = api_bp.api.get_logs(level, limit)
        return jsonify(logs)
        
    except Exception as e:
        logger.error(f"API get logs error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/test-message', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def send_test_message():
    """Send test message to component"""
    try:
        data = request.get_json() or {}
        recipient = data.get('recipient')
        message_type = data.get('message_type')
        message_data = data.get('data', {})
        
        if not recipient or not message_type:
            return jsonify({"error": "Recipient and message type are required"}), 400
        
        result = api_bp.api.send_test_message(recipient, message_type, message_data)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API test message error: {e}")
        return jsonify({"error": str(e)}), 500


# Video upload and delete routes
@api_bp.route('/video/upload', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def upload_video():
    """Upload video file"""
    try:
        if 'video' not in request.files:
            return jsonify({"error": "No video file provided"}), 400
        
        file = request.files['video']
        if file.filename == '':
            return jsonify({"error": "No file selected"}), 400
        
        template = request.form.get('template', 'news_template')
        
        result = api_bp.api.upload_video(file, template)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API video upload error: {e}")
        return jsonify({"error": str(e)}), 500


@api_bp.route('/video/delete', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def delete_video():
    """Delete uploaded video"""
    try:
        data = request.get_json() or {}
        filename = data.get('filename')
        
        if not filename:
            return jsonify({"error": "Filename is required"}), 400
        
        result = api_bp.api.delete_video(filename)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"API video delete error: {e}")
        return jsonify({"error": str(e)}), 500


# Auth token endpoint for JWT creation
@auth_bp.route('/token', methods=['POST'])
def create_auth_token():
    """Create JWT authentication token"""
    try:
        data = request.get_json() or {}
        username = data.get('username', '').strip()
        password = data.get('password', '')
        
        if not username or not password:
            return jsonify({"error": "Username and password are required"}), 400
        
        # Authenticate user
        authenticated_user = auth_bp.auth_manager.authenticate_user(username, password)
        
        if authenticated_user:
            # Create JWT token
            token = auth_bp.auth_manager.create_jwt_token(authenticated_user.id)
            
            if token:
                return jsonify({
                    "access_token": token,
                    "token_type": "bearer",
                    "user": authenticated_user.to_dict()
                })
            else:
                return jsonify({"error": "Failed to create token"}), 500
        else:
            return jsonify({"error": "Invalid credentials"}), 401
            
    except Exception as e:
        logger.error(f"Token creation error: {e}")
        return jsonify({"error": str(e)}), 500