import logging
from datetime import datetime
from flask import request, jsonify, current_app
from flask_jwt_extended import jwt_required, get_jwt_identity
from sqlalchemy import func, desc
from app.api import bp
from app import db
from app.utils.security import require_admin, require_active_user
from app.utils.logging import log_api_request
from app.upload.file_handler import get_file_upload_handler
from app.upload.fixture_parser import get_fixture_parser

logger = logging.getLogger(__name__)

@bp.route('/matches', methods=['GET'])
@jwt_required()
def api_get_matches():
    """Get matches with pagination and filtering"""
    try:
        from app.models import User, Match, FileUpload
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user or not user.is_active:
            return jsonify({'error': 'User not found or inactive'}), 404
        
        # Pagination parameters
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 20, type=int), 100)
        
        # Filtering parameters
        status_filter = request.args.get('status')
        search_query = request.args.get('search', '').strip()
        active_only = request.args.get('active_only', 'false').lower() == 'true'
        
        # Base query
        if user.is_admin:
            query = Match.query
        else:
            query = Match.query.filter_by(created_by=user_id)
        
        # Apply filters
        if active_only:
            query = query.filter_by(active_status=True)
        
        if status_filter == 'active':
            query = query.filter_by(active_status=True)
        elif status_filter == 'pending':
            query = query.filter_by(active_status=False)
        elif status_filter == 'zip_pending':
            query = query.filter_by(zip_upload_status='pending')
        elif status_filter == 'zip_completed':
            query = query.filter_by(zip_upload_status='completed')
        elif status_filter == 'zip_failed':
            query = query.filter_by(zip_upload_status='failed')
        
        # Search functionality
        if search_query:
            search_pattern = f"%{search_query}%"
            query = query.filter(
                db.or_(
                    Match.fighter1_township.ilike(search_pattern),
                    Match.fighter2_township.ilike(search_pattern),
                    Match.venue_kampala_township.ilike(search_pattern),
                    Match.match_number.like(search_pattern)
                )
            )
        
        # Sorting
        sort_by = request.args.get('sort_by', 'created_at')
        sort_order = request.args.get('sort_order', 'desc')
        
        if hasattr(Match, sort_by):
            sort_column = getattr(Match, sort_by)
            if sort_order == 'asc':
                query = query.order_by(sort_column.asc())
            else:
                query = query.order_by(sort_column.desc())
        else:
            query = query.order_by(Match.created_at.desc())
        
        # Execute pagination
        matches_pagination = query.paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        # Include outcomes if requested
        include_outcomes = request.args.get('include_outcomes', 'false').lower() == 'true'
        
        matches_data = []
        for match in matches_pagination.items:
            match_dict = match.to_dict(include_outcomes=include_outcomes)
            matches_data.append(match_dict)
        
        return jsonify({
            'matches': matches_data,
            'pagination': {
                'page': page,
                'pages': matches_pagination.pages,
                'per_page': per_page,
                'total': matches_pagination.total,
                'has_next': matches_pagination.has_next,
                'has_prev': matches_pagination.has_prev
            },
            'filters': {
                'status': status_filter,
                'search': search_query,
                'active_only': active_only,
                'sort_by': sort_by,
                'sort_order': sort_order
            }
        }), 200
        
    except Exception as e:
        logger.error(f"API get matches error: {str(e)}")
        return jsonify({'error': 'Failed to retrieve matches'}), 500

@bp.route('/matches/<int:match_id>', methods=['GET'])
@jwt_required()
def api_get_match(match_id):
    """Get specific match details"""
    try:
        from app.models import User, Match, FileUpload
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user or not user.is_active:
            return jsonify({'error': 'User not found or inactive'}), 404
        
        # Get match
        if user.is_admin:
            match = Match.query.get(match_id)
        else:
            match = Match.query.filter_by(id=match_id, created_by=user_id).first()
        
        if not match:
            return jsonify({'error': 'Match not found'}), 404
        
        # Get associated uploads
        uploads = FileUpload.query.filter_by(match_id=match_id).all()
        
        return jsonify({
            'match': match.to_dict(include_outcomes=True),
            'uploads': [upload.to_dict() for upload in uploads]
        }), 200
        
    except Exception as e:
        logger.error(f"API get match error: {str(e)}")
        return jsonify({'error': 'Failed to retrieve match'}), 500

@bp.route('/matches/<int:match_id>', methods=['PUT'])
@jwt_required()
def api_update_match(match_id):
    """Update match details"""
    try:
        from app.models import User, Match
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user or not user.is_active:
            return jsonify({'error': 'User not found or inactive'}), 404
        
        # Get match
        if user.is_admin:
            match = Match.query.get(match_id)
        else:
            match = Match.query.filter_by(id=match_id, created_by=user_id).first()
        
        if not match:
            return jsonify({'error': 'Match not found'}), 404
        
        data = request.get_json()
        if not data:
            return jsonify({'error': 'No data provided'}), 400
        
        # Update allowed fields
        updatable_fields = ['start_time', 'end_time', 'result']
        updated_fields = []
        
        for field in updatable_fields:
            if field in data:
                if field in ['start_time', 'end_time'] and data[field]:
                    try:
                        setattr(match, field, datetime.fromisoformat(data[field]))
                        updated_fields.append(field)
                    except ValueError:
                        return jsonify({'error': f'Invalid datetime format for {field}'}), 400
                else:
                    setattr(match, field, data[field])
                    updated_fields.append(field)
        
        if updated_fields:
            match.updated_at = datetime.utcnow()
            db.session.commit()
            
            return jsonify({
                'message': 'Match updated successfully',
                'updated_fields': updated_fields,
                'match': match.to_dict()
            }), 200
        else:
            return jsonify({'message': 'No fields to update'}), 200
        
    except Exception as e:
        logger.error(f"API update match error: {str(e)}")
        db.session.rollback()
        return jsonify({'error': 'Failed to update match'}), 500

@bp.route('/matches/<int:match_id>', methods=['DELETE'])
@jwt_required()
def api_delete_match(match_id):
    """Delete match (admin only)"""
    try:
        from app.models import User, Match, FileUpload
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user or not user.is_admin:
            return jsonify({'error': 'Admin privileges required'}), 403
        
        match = Match.query.get(match_id)
        if not match:
            return jsonify({'error': 'Match not found'}), 404
        
        # Delete associated files
        uploads = FileUpload.query.filter_by(match_id=match_id).all()
        for upload in uploads:
            try:
                import os
                if os.path.exists(upload.file_path):
                    os.remove(upload.file_path)
            except Exception as e:
                logger.warning(f"Failed to delete file {upload.file_path}: {str(e)}")
        
        # Delete match (cascades to outcomes and uploads)
        db.session.delete(match)
        db.session.commit()
        
        return jsonify({'message': 'Match deleted successfully'}), 200
        
    except Exception as e:
        logger.error(f"API delete match error: {str(e)}")
        db.session.rollback()
        return jsonify({'error': 'Failed to delete match'}), 500

@bp.route('/statistics', methods=['GET'])
@jwt_required()
def api_get_statistics():
    """Get comprehensive statistics"""
    try:
        from app.models import User, Match, FileUpload
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user or not user.is_active:
            return jsonify({'error': 'User not found or inactive'}), 404
        
        # User statistics
        user_stats = {
            'total_matches': Match.query.filter_by(created_by=user_id).count(),
            'active_matches': Match.query.filter_by(
                created_by=user_id, active_status=True
            ).count(),
            'total_uploads': FileUpload.query.filter_by(uploaded_by=user_id).count(),
            'completed_uploads': FileUpload.query.filter_by(
                uploaded_by=user_id, upload_status='completed'
            ).count(),
            'failed_uploads': FileUpload.query.filter_by(
                uploaded_by=user_id, upload_status='failed'
            ).count(),
            'pending_zip_uploads': Match.query.filter_by(
                created_by=user_id, zip_upload_status='pending'
            ).count()
        }
        
        # Global statistics (if admin)
        global_stats = {}
        if user.is_admin:
            from app.database import get_db_manager
            db_manager = get_db_manager()
            global_stats = db_manager.get_database_stats()
            
            file_handler = get_file_upload_handler()
            fixture_parser = get_fixture_parser()
            
            upload_stats = file_handler.get_upload_statistics()
            parsing_stats = fixture_parser.get_parsing_statistics()
            
            global_stats.update({
                'upload_stats': upload_stats,
                'parsing_stats': parsing_stats
            })
        
        # Recent activity
        recent_matches = Match.query.filter_by(created_by=user_id)\
            .order_by(Match.created_at.desc()).limit(5).all()
        
        recent_uploads = FileUpload.query.filter_by(uploaded_by=user_id)\
            .order_by(FileUpload.created_at.desc()).limit(5).all()
        
        return jsonify({
            'user_stats': user_stats,
            'global_stats': global_stats,
            'recent_activity': {
                'matches': [match.to_dict(include_outcomes=False) for match in recent_matches],
                'uploads': [upload.to_dict() for upload in recent_uploads]
            }
        }), 200
        
    except Exception as e:
        logger.error(f"API statistics error: {str(e)}")
        return jsonify({'error': 'Failed to retrieve statistics'}), 500

@bp.route('/admin/users', methods=['GET'])
@jwt_required()
@require_admin
def api_admin_get_users():
    """Get users list (admin only)"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 20, type=int), 100)
        
        search_query = request.args.get('search', '').strip()
        status_filter = request.args.get('status')
        
        from app.models import User
        # Base query
        query = User.query
        
        # Apply filters
        if status_filter == 'active':
            query = query.filter_by(is_active=True)
        elif status_filter == 'inactive':
            query = query.filter_by(is_active=False)
        elif status_filter == 'admin':
            query = query.filter_by(is_admin=True)
        
        # Search functionality
        if search_query:
            search_pattern = f"%{search_query}%"
            query = query.filter(
                db.or_(
                    User.username.ilike(search_pattern),
                    User.email.ilike(search_pattern)
                )
            )
        
        # Pagination
        users_pagination = query.order_by(User.created_at.desc()).paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        return jsonify({
            'users': [user.to_dict() for user in users_pagination.items],
            'pagination': {
                'page': page,
                'pages': users_pagination.pages,
                'per_page': per_page,
                'total': users_pagination.total,
                'has_next': users_pagination.has_next,
                'has_prev': users_pagination.has_prev
            }
        }), 200
        
    except Exception as e:
        logger.error(f"API admin users error: {str(e)}")
        return jsonify({'error': 'Failed to retrieve users'}), 500

@bp.route('/admin/users/<int:user_id>', methods=['PUT'])
@jwt_required()
@require_admin
def api_admin_update_user(user_id):
    """Update user (admin only)"""
    try:
        from app.models import User
        user = User.query.get(user_id)
        if not user:
            return jsonify({'error': 'User not found'}), 404
        
        data = request.get_json()
        if not data:
            return jsonify({'error': 'No data provided'}), 400
        
        # Update allowed fields
        updatable_fields = ['is_active', 'is_admin']
        updated_fields = []
        
        for field in updatable_fields:
            if field in data:
                setattr(user, field, bool(data[field]))
                updated_fields.append(field)
        
        if updated_fields:
            user.updated_at = datetime.utcnow()
            db.session.commit()
            
            return jsonify({
                'message': 'User updated successfully',
                'updated_fields': updated_fields,
                'user': user.to_dict()
            }), 200
        else:
            return jsonify({'message': 'No fields to update'}), 200
        
    except Exception as e:
        logger.error(f"API admin update user error: {str(e)}")
        db.session.rollback()
        return jsonify({'error': 'Failed to update user'}), 500

@bp.route('/admin/logs', methods=['GET'])
@jwt_required()
@require_admin
def api_admin_get_logs():
    """Get system logs (admin only)"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 50, type=int), 200)
        
        level_filter = request.args.get('level')
        module_filter = request.args.get('module')
        
        from app.models import SystemLog
        # Base query
        query = SystemLog.query
        
        # Apply filters
        if level_filter:
            query = query.filter_by(level=level_filter)
        
        if module_filter:
            query = query.filter_by(module=module_filter)
        
        # Pagination
        logs_pagination = query.order_by(SystemLog.created_at.desc()).paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        return jsonify({
            'logs': [log.to_dict() for log in logs_pagination.items],
            'pagination': {
                'page': page,
                'pages': logs_pagination.pages,
                'per_page': per_page,
                'total': logs_pagination.total,
                'has_next': logs_pagination.has_next,
                'has_prev': logs_pagination.has_prev
            }
        }), 200
        
    except Exception as e:
        logger.error(f"API admin logs error: {str(e)}")
        return jsonify({'error': 'Failed to retrieve logs'}), 500

@bp.route('/admin/system-info', methods=['GET'])
@jwt_required()
@require_admin
def api_admin_system_info():
    """Get system information (admin only)"""
    try:
        from app.database import get_db_manager
        db_manager = get_db_manager()
        
        # Database statistics
        db_stats = db_manager.get_database_stats()
        
        # System health
        db_healthy = db_manager.test_connection()
        
        # Upload statistics
        file_handler = get_file_upload_handler()
        upload_stats = file_handler.get_upload_statistics()
        
        # Parsing statistics
        fixture_parser = get_fixture_parser()
        parsing_stats = fixture_parser.get_parsing_statistics()
        
        from app.models import UserSession
        # Active sessions
        active_sessions = UserSession.query.filter_by(is_active=True).count()
        
        system_info = {
            'database': {
                'healthy': db_healthy,
                'statistics': db_stats
            },
            'uploads': upload_stats,
            'parsing': parsing_stats,
            'sessions': {
                'active_sessions': active_sessions
            },
            'timestamp': datetime.utcnow().isoformat()
        }
        
        return jsonify(system_info), 200
        
    except Exception as e:
        logger.error(f"API system info error: {str(e)}")
        return jsonify({'error': 'Failed to retrieve system information'}), 500

@bp.route('/admin/cleanup', methods=['POST'])
@jwt_required()
@require_admin
def api_admin_cleanup():
    """Perform system cleanup (admin only)"""
    try:
        cleanup_type = request.json.get('type', 'all') if request.json else 'all'
        
        results = {}
        
        if cleanup_type in ['all', 'sessions']:
            # Clean up expired sessions
            from app.database import get_db_manager
            db_manager = get_db_manager()
            expired_sessions = db_manager.cleanup_expired_sessions()
            results['expired_sessions_cleaned'] = expired_sessions
        
        if cleanup_type in ['all', 'logs']:
            # Clean up old logs (older than 30 days)
            days = request.json.get('log_retention_days', 30) if request.json else 30
            from app.database import get_db_manager
            db_manager = get_db_manager()
            old_logs = db_manager.cleanup_old_logs(days)
            results['old_logs_cleaned'] = old_logs
        
        if cleanup_type in ['all', 'uploads']:
            # Clean up failed uploads
            file_handler = get_file_upload_handler()
            file_handler.cleanup_failed_uploads()
            results['failed_uploads_cleaned'] = True
        
        return jsonify({
            'message': 'Cleanup completed successfully',
            'results': results
        }), 200
        
    except Exception as e:
        logger.error(f"API cleanup error: {str(e)}")
        return jsonify({'error': 'Cleanup failed'}), 500

# Error handlers for API
@bp.errorhandler(404)
def api_not_found(error):
    return jsonify({'error': 'Endpoint not found'}), 404

@bp.errorhandler(405)
def api_method_not_allowed(error):
    return jsonify({'error': 'Method not allowed'}), 405

@bp.errorhandler(500)
def api_internal_error(error):
    return jsonify({'error': 'Internal server error'}), 500