"""User management service for admin operations."""
import random
import string
from datetime import datetime
from flask import current_app
from sqlalchemy import or_, func
from app import db
from app.models import User, UserRole
from app.utils import validate_email, validate_password, validate_username, validate_name
from app.services.email_service import send_email


def list_users(page=1, per_page=20, role=None, is_active=None, is_verified=None, search=None):
    """
    List all users with pagination and filters.
    
    Args:
        page: Page number (default 1)
        per_page: Items per page (default 20)
        role: Filter by role (customer/owner/admin)
        is_active: Filter by active status (True/False)
        is_verified: Filter by owner verification status (True/False)
        search: Search by name, email, or username
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        query = User.query
        
        # Apply role filter
        if role:
            try:
                role_enum = UserRole(role.lower())
                query = query.filter_by(role=role_enum)
            except ValueError:
                return {'success': False, 'message': f'Invalid role: {role}', 'data': None}
        
        # Apply active status filter
        if is_active is not None:
            query = query.filter_by(is_active=is_active)
        
        # Apply verification status filter
        if is_verified is not None:
            query = query.filter_by(is_verified=is_verified)
        
        # Apply search
        if search:
            search_pattern = f"%{search}%"
            query = query.filter(
                or_(
                    User.first_name.ilike(search_pattern),
                    User.last_name.ilike(search_pattern),
                    User.email.ilike(search_pattern),
                    User.username.ilike(search_pattern)
                )
            )
        
        # Order by created_at descending (newest first)
        query = query.order_by(User.created_at.desc())
        
        # Paginate
        pagination = query.paginate(page=page, per_page=per_page, error_out=False)
        
        users = [user.to_dict_admin() for user in pagination.items]
        
        return {
            'success': True,
            'message': 'Users retrieved successfully',
            'data': {
                'users': users,
                'total': pagination.total,
                'page': pagination.page,
                'per_page': pagination.per_page,
                'pages': pagination.pages
            }
        }
        
    except Exception as e:
        current_app.logger.error(f"List users error: {str(e)}")
        return {'success': False, 'message': 'Failed to retrieve users', 'data': None}


def get_user_by_id_admin(user_id):
    """
    Get full user details (admin view).
    
    Args:
        user_id: User ID to fetch
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        return {
            'success': True,
            'message': 'User retrieved successfully',
            'data': user.to_dict_admin()
        }
        
    except Exception as e:
        current_app.logger.error(f"Get user by ID error: {str(e)}")
        return {'success': False, 'message': 'Failed to retrieve user', 'data': None}


def create_user(data, bypass_email_verification=False):
    """
    Admin creates a new user account.
    
    Args:
        data: Dictionary with user data
        bypass_email_verification: If True, set is_email_verified=True
        
    Required fields: first_name, last_name, username, email, password
    Optional fields: role, phone_number, address, city, country, date_of_birth
    
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        # Validate required fields
        required_fields = ['first_name', 'last_name', 'username', 'email', 'password']
        for field in required_fields:
            if field not in data or not data[field]:
                return {'success': False, 'message': f'{field} is required', 'data': None}
        
        # Validate inputs
        is_valid, error = validate_name(data['first_name'], "First name")
        if not is_valid:
            return {'success': False, 'message': error, 'data': None}
        
        is_valid, error = validate_name(data['last_name'], "Last name")
        if not is_valid:
            return {'success': False, 'message': error, 'data': None}
        
        is_valid, error = validate_username(data['username'])
        if not is_valid:
            return {'success': False, 'message': error, 'data': None}
        
        is_valid, error = validate_email(data['email'])
        if not is_valid:
            return {'success': False, 'message': error, 'data': None}
        
        is_valid, error = validate_password(data['password'])
        if not is_valid:
            return {'success': False, 'message': error, 'data': None}
        
        # Check if user already exists
        if User.query.filter_by(email=data['email']).first():
            return {'success': False, 'message': 'Email already registered', 'data': None}
        
        if User.query.filter_by(username=data['username']).first():
            return {'success': False, 'message': 'Username already taken', 'data': None}
        
        # Validate role if provided
        role = UserRole.CUSTOMER  # Default
        if 'role' in data and data['role']:
            try:
                role = UserRole(data['role'].lower())
            except ValueError:
                return {'success': False, 'message': f'Invalid role: {data["role"]}', 'data': None}
        
        # Create user
        user = User(
            first_name=data['first_name'],
            last_name=data['last_name'],
            username=data['username'],
            email=data['email'],
            role=role,
            is_email_verified=bypass_email_verification
        )
        user.set_password(data['password'])
        
        # Set optional fields
        if 'phone_number' in data:
            user.phone_number = data['phone_number']
        if 'address' in data:
            user.address = data['address']
        if 'city' in data:
            user.city = data['city']
        if 'country' in data:
            user.country = data['country']
        if 'date_of_birth' in data:
            user.date_of_birth = data['date_of_birth']
        
        db.session.add(user)
        db.session.commit()
        
        return {
            'success': True,
            'message': 'User created successfully',
            'data': user.to_dict_admin()
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Create user error: {str(e)}")
        return {'success': False, 'message': 'Failed to create user', 'data': None}


def update_user(user_id, data):
    """
    Admin updates any user's information.
    
    Args:
        user_id: User ID to update
        data: Dictionary with fields to update
        
    Allowed fields: first_name, last_name, email, username, phone_number,
                   date_of_birth, address, city, country
    
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        # Update first_name
        if 'first_name' in data:
            is_valid, error = validate_name(data['first_name'], "First name")
            if not is_valid:
                return {'success': False, 'message': error, 'data': None}
            user.first_name = data['first_name']
        
        # Update last_name
        if 'last_name' in data:
            is_valid, error = validate_name(data['last_name'], "Last name")
            if not is_valid:
                return {'success': False, 'message': error, 'data': None}
            user.last_name = data['last_name']
        
        # Update email (check uniqueness)
        if 'email' in data:
            is_valid, error = validate_email(data['email'])
            if not is_valid:
                return {'success': False, 'message': error, 'data': None}
            
            existing = User.query.filter(
                User.email == data['email'],
                User.id != str(user_id)
            ).first()
            if existing:
                return {'success': False, 'message': 'Email already in use', 'data': None}
            user.email = data['email']
        
        # Update username (check uniqueness)
        if 'username' in data:
            is_valid, error = validate_username(data['username'])
            if not is_valid:
                return {'success': False, 'message': error, 'data': None}
            
            existing = User.query.filter(
                User.username == data['username'],
                User.id != str(user_id)
            ).first()
            if existing:
                return {'success': False, 'message': 'Username already taken', 'data': None}
            user.username = data['username']
        
        # Update phone_number (check uniqueness)
        if 'phone_number' in data:
            phone = data['phone_number']
            if phone:
                existing = User.query.filter(
                    User.phone_number == phone,
                    User.id != str(user_id)
                ).first()
                if existing:
                    return {'success': False, 'message': 'Phone number already in use', 'data': None}
            user.phone_number = phone if phone else None
        
        # Update other fields
        if 'date_of_birth' in data:
            user.date_of_birth = data['date_of_birth']
        
        if 'address' in data:
            user.address = data['address']
        
        if 'city' in data:
            user.city = data['city']
        
        if 'country' in data:
            user.country = data['country']
        
        db.session.commit()
        
        return {
            'success': True,
            'message': 'User updated successfully',
            'data': user.to_dict_admin()
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Update user error: {str(e)}")
        return {'success': False, 'message': 'Failed to update user', 'data': None}


def delete_user(user_id, hard_delete=False):
    """
    Delete user account (soft or hard delete).
    
    Args:
        user_id: User ID to delete
        hard_delete: If True, permanently delete from database
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        if hard_delete:
            # Hard delete - permanently remove from database
            db.session.delete(user)
            message = 'User permanently deleted'
        else:
            # Soft delete - just deactivate
            user.is_active = False
            message = 'User deactivated successfully'
        
        db.session.commit()
        
        return {
            'success': True,
            'message': message,
            'data': None
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Delete user error: {str(e)}")
        return {'success': False, 'message': 'Failed to delete user', 'data': None}


def change_user_role(user_id, new_role):
    """
    Change user's role.
    
    Args:
        user_id: User ID to update
        new_role: New role (customer/owner/admin)
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        # Validate role
        try:
            role_enum = UserRole(new_role.lower())
        except ValueError:
            return {'success': False, 'message': f'Invalid role: {new_role}', 'data': None}
        
        old_role = user.role.value
        user.role = role_enum
        db.session.commit()
        
        return {
            'success': True,
            'message': f'User role changed from {old_role} to {new_role}',
            'data': user.to_dict_admin()
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Change user role error: {str(e)}")
        return {'success': False, 'message': 'Failed to change user role', 'data': None}


def verify_owner(user_id):
    """
    Verify owner account (set is_verified=True).
    
    Args:
        user_id: User ID to verify
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        if user.role != UserRole.OWNER:
            return {'success': False, 'message': 'User is not an owner', 'data': None}
        
        if user.is_verified:
            return {'success': False, 'message': 'Owner is already verified', 'data': None}
        
        user.is_verified = True
        db.session.commit()
        
        return {
            'success': True,
            'message': 'Owner verified successfully',
            'data': user.to_dict_admin()
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Verify owner error: {str(e)}")
        return {'success': False, 'message': 'Failed to verify owner', 'data': None}


def toggle_account_status(user_id, is_active):
    """
    Activate or deactivate user account.
    
    Args:
        user_id: User ID to update
        is_active: True to activate, False to deactivate
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        user.is_active = is_active
        db.session.commit()
        
        status = 'activated' if is_active else 'deactivated'
        
        return {
            'success': True,
            'message': f'Account {status} successfully',
            'data': user.to_dict_admin()
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Toggle account status error: {str(e)}")
        return {'success': False, 'message': 'Failed to update account status', 'data': None}


def force_email_verification(user_id):
    """
    Manually mark user's email as verified.
    
    Args:
        user_id: User ID to verify
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        if user.is_email_verified:
            return {'success': False, 'message': 'Email is already verified', 'data': None}
        
        user.is_email_verified = True
        db.session.commit()
        
        return {
            'success': True,
            'message': 'Email verified successfully',
            'data': user.to_dict_admin()
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Force email verification error: {str(e)}")
        return {'success': False, 'message': 'Failed to verify email', 'data': None}


def generate_temp_password(length=12):
    """Generate a random temporary password."""
    characters = string.ascii_letters + string.digits + "!@#$%^&*"
    return ''.join(random.choice(characters) for _ in range(length))


def reset_user_password(user_id, admin_id):
    """
    Admin resets user's password and sends email with temp password.
    
    Args:
        user_id: User ID whose password to reset
        admin_id: Admin user ID performing the reset
        
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        user = User.query.filter_by(id=str(user_id)).first()
        
        if not user:
            return {'success': False, 'message': 'User not found', 'data': None}
        
        admin = User.query.filter_by(id=str(admin_id)).first()
        if not admin:
            return {'success': False, 'message': 'Admin user not found', 'data': None}
        
        # Generate temporary password
        temp_password = generate_temp_password()
        
        # Update user's password
        user.set_password(temp_password)
        db.session.commit()
        
        # Send email to user
        subject = "Your Password Has Been Reset"
        body = f"""
Hello {user.first_name},

Your password has been reset by an administrator.

Your temporary password is: {temp_password}

For security reasons, please:
1. Log in using this temporary password
2. Change your password immediately after logging in

If you did not request this password reset, please contact support immediately.

Best regards,
AFFIX WEB ADVERTS Team
"""
        
        email_sent = send_email(user.email, subject, body)
        
        if not email_sent:
            current_app.logger.warning(f"Password reset email failed for {user.email}")
            return {
                'success': False,
                'message': 'Password was reset but failed to send email notification',
                'data': None
            }
        
        # Log the action
        current_app.logger.info(f"Password reset for user {user_id} by admin {admin_id}")
        
        return {
            'success': True,
            'message': 'Password reset successfully. User will receive an email with temporary password.',
            'data': None
        }
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Reset password error: {str(e)}")
        return {'success': False, 'message': 'Failed to reset password', 'data': None}


def get_user_stats():
    """
    Get user statistics and analytics.
    
    Returns:
        dict: {'success': bool, 'message': str, 'data': dict/None}
    """
    try:
        # Total users
        total_users = User.query.count()
        
        # Active users
        active_users = User.query.filter_by(is_active=True).count()
        
        # Users by role
        customers = User.query.filter_by(role=UserRole.CUSTOMER).count()
        owners = User.query.filter_by(role=UserRole.OWNER).count()
        admins = User.query.filter_by(role=UserRole.ADMIN).count()
        
        # Verified owners
        verified_owners = User.query.filter_by(
            role=UserRole.OWNER,
            is_verified=True
        ).count()
        
        # Email verified users
        email_verified = User.query.filter_by(is_email_verified=True).count()
        
        # Recent registrations (last 7 days)
        from datetime import timedelta
        seven_days_ago = datetime.utcnow() - timedelta(days=7)
        recent_registrations = User.query.filter(
            User.created_at >= seven_days_ago
        ).count()
        
        stats = {
            'total_users': total_users,
            'active_users': active_users,
            'inactive_users': total_users - active_users,
            'customers': customers,
            'owners': owners,
            'admins': admins,
            'verified_owners': verified_owners,
            'email_verified': email_verified,
            'recent_registrations_7days': recent_registrations
        }
        
        return {
            'success': True,
            'message': 'User statistics retrieved successfully',
            'data': stats
        }
        
    except Exception as e:
        current_app.logger.error(f"Get user stats error: {str(e)}")
        return {'success': False, 'message': 'Failed to retrieve user statistics', 'data': None}