from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import Body
from typing import Optional
import sys

# Add shared modules to path
sys.path.append('/app')

from app.core.dependencies import get_current_active_user, CurrentUser
from app.models.user_profile import UserProfile
from app.models.role import Role
from app.models.user_role import UserRole
from app.schemas.profile import ProfileResponse, ProfileUpdate
from bson import ObjectId

router = APIRouter(prefix="/accounts", tags=["User Profiles"])

@router.get("/me", response_model=ProfileResponse)
async def get_my_profile(current_user: CurrentUser = Depends(get_current_active_user)):
    """Get current user's profile"""
    try:
        profile = await UserProfile.find_one(UserProfile.user_id == ObjectId(current_user.id))
        
        if not profile:
            # Auto-create a basic profile for first-time users
            profile = await UserProfile.create_from_auth_user(
                user_id=ObjectId(current_user.id),
                email=current_user.email,
                username=current_user.username
            )
        
        # Get user roles
        user_roles = await UserRole.get_user_roles(ObjectId(current_user.id), active_only=True)
        roles = [role.role_name for role in user_roles]
        
        return ProfileResponse(
            id=str(profile.id),
            user_id=str(profile.user_id),
            email=profile.email,
            username=profile.username,
            first_name=profile.first_name,
            last_name=profile.last_name,
            display_name=profile.display_name,
            full_name=profile.get_full_name(),
            bio=profile.bio,
            phone=profile.phone,
            website=str(profile.website) if profile.website else None,
            country=profile.country,
            city=profile.city,
            timezone=profile.timezone,
            avatar_url=profile.avatar_url,
            cover_photo_url=profile.cover_photo_url,
            social_links=profile.social_links,
            birth_date=profile.birth_date,
            gender=profile.gender,
            visibility=profile.visibility,
            status=profile.status,
            profile_completion_percentage=profile.profile_completion_percentage,
            followers_count=profile.followers_count,
            following_count=profile.following_count,
            posts_count=profile.posts_count,
            created_at=profile.created_at,
            updated_at=profile.updated_at,
            last_seen=profile.last_seen,
            tags=profile.tags,
            custom_fields=profile.custom_fields,
            roles=roles
        )
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to get profile: {str(e)}"
        )

@router.post("/assign-default-role/{user_id}")
async def assign_default_role_to_user(
    user_id: str,
    current_user: CurrentUser = Depends(get_current_active_user)
):
    """Assign default role to a user (admin only)"""
    try:
        # Check if current user is admin
        user_roles = await UserRole.get_user_roles(ObjectId(current_user.id), active_only=True)
        if not any(role.role_name == "admin" for role in user_roles):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Only administrators can assign roles"
            )
        
        # Check if user exists
        profile = await UserProfile.find_one(UserProfile.user_id == ObjectId(user_id))
        if not profile:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="User not found"
            )
        
        # Check if user already has roles
        existing_roles = await UserRole.get_user_roles(ObjectId(user_id), active_only=True)
        if existing_roles:
            return {
                "message": "User already has roles",
                "roles": [role.role_name for role in existing_roles]
            }
        
        # Get or create default role
        default_role = await Role.find_one(Role.name == "user")
        if not default_role:
            default_role = Role(
                name="user",
                description="Default user role",
                role_type="SYSTEM",
                is_system_role=True,
                is_active=True,
                priority=1
            )
            await default_role.save()
        
        # Assign default role
        user_role = UserRole(
            user_id=ObjectId(user_id),
            role_name=default_role.name,
            assigned_by=ObjectId(current_user.id),
            reason="Default role assignment by admin",
            is_active=True
        )
        await user_role.save()
        
        return {
            "message": "Default role assigned successfully",
            "user_id": user_id,
            "role": default_role.name
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to assign role: {str(e)}"
        )

@router.get("/users-without-roles")
async def get_users_without_roles(
    current_user: CurrentUser = Depends(get_current_active_user)
):
    """Get list of users without roles (admin only)"""
    try:
        # Check if current user is admin
        user_roles = await UserRole.get_user_roles(ObjectId(current_user.id), active_only=True)
        if not any(role.role_name == "admin" for role in user_roles):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Only administrators can view this information"
            )
        
        # Get all user profiles
        user_profiles = await UserProfile.find_all().to_list()
        users_without_roles = []
        
        for profile in user_profiles:
            user_roles = await UserRole.get_user_roles(profile.user_id, active_only=True)
            if not user_roles:
                users_without_roles.append({
                    "user_id": str(profile.user_id),
                    "email": profile.email,
                    "username": profile.username,
                    "full_name": profile.get_full_name()
                })
        
        return {
            "users_without_roles": users_without_roles,
            "count": len(users_without_roles)
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to get users without roles: {str(e)}"
        )

@router.post("/exist")
async def check_profile_existence(
    email: Optional[str] = Body(None),
    username: Optional[str] = Body(None)
):
    """Check if a profile with given email or username exists.
    Returns { exists: true|false }
    """
    try:
        if not email and not username:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="email or username is required"
            )

        query = {}
        if email:
            query["email"] = email
        if username:
            query["username"] = username

        profile = await UserProfile.find_one(query)
        return { "exists": bool(profile) }
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to check existence: {str(e)}"
        )

@router.put("/me", response_model=ProfileResponse)
async def update_my_profile(
    profile_update: ProfileUpdate,
    current_user: CurrentUser = Depends(get_current_active_user)
):
    """Update current user's profile"""
    try:
        profile = await UserProfile.find_one(UserProfile.user_id == ObjectId(current_user.id))
        
        if not profile:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Profile not found"
            )
        
        # Update fields
        update_data = profile_update.dict(exclude_unset=True)
        
        for field, value in update_data.items():
            if hasattr(profile, field):
                setattr(profile, field, value)
        
        # Update completion percentage
        await profile.update_completion_percentage()
        
        # Return updated profile
        return ProfileResponse(
            id=str(profile.id),
            user_id=str(profile.user_id),
            email=profile.email,
            username=profile.username,
            first_name=profile.first_name,
            last_name=profile.last_name,
            display_name=profile.display_name,
            full_name=profile.get_full_name(),
            bio=profile.bio,
            phone=profile.phone,
            website=str(profile.website) if profile.website else None,
            country=profile.country,
            city=profile.city,
            timezone=profile.timezone,
            avatar_url=profile.avatar_url,
            cover_photo_url=profile.cover_photo_url,
            social_links=profile.social_links,
            birth_date=profile.birth_date,
            gender=profile.gender,
            visibility=profile.visibility,
            status=profile.status,
            profile_completion_percentage=profile.profile_completion_percentage,
            followers_count=profile.followers_count,
            following_count=profile.following_count,
            posts_count=profile.posts_count,
            created_at=profile.created_at,
            updated_at=profile.updated_at,
            last_seen=profile.last_seen,
            tags=profile.tags,
            custom_fields=profile.custom_fields
        )
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to update profile: {str(e)}"
        )

@router.get("/{user_id}", response_model=ProfileResponse)
async def get_user_profile(
    user_id: str,
    current_user: Optional[CurrentUser] = Depends(get_current_active_user)
):
    """Get a user's profile by ID"""
    try:
        profile = await UserProfile.find_one(UserProfile.user_id == ObjectId(user_id))
        
        if not profile:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Profile not found"
            )
        
        # Check if profile can be viewed
        viewer_id = ObjectId(current_user.id) if current_user else None
        if not profile.can_be_viewed_by(viewer_id):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Profile is private"
            )
        
        return ProfileResponse(
            id=str(profile.id),
            user_id=str(profile.user_id),
            email=profile.email,
            username=profile.username,
            first_name=profile.first_name,
            last_name=profile.last_name,
            display_name=profile.display_name,
            full_name=profile.get_full_name(),
            bio=profile.bio,
            phone=profile.phone if profile.visibility.value == "public" else None,
            website=str(profile.website) if profile.website else None,
            country=profile.country,
            city=profile.city,
            timezone=profile.timezone,
            avatar_url=profile.avatar_url,
            cover_photo_url=profile.cover_photo_url,
            social_links=profile.social_links,
            birth_date=profile.birth_date if profile.visibility.value == "public" else None,
            gender=profile.gender,
            visibility=profile.visibility,
            status=profile.status,
            profile_completion_percentage=profile.profile_completion_percentage,
            followers_count=profile.followers_count,
            following_count=profile.following_count,
            posts_count=profile.posts_count,
            created_at=profile.created_at,
            updated_at=profile.updated_at,
            last_seen=profile.last_seen if profile.visibility.value == "public" else None,
            tags=profile.tags,
            custom_fields={}  # Don't expose custom fields to other users
        )
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to get profile: {str(e)}"
        )
