from fastapi import APIRouter, Depends, HTTPException, status, Request, Response
from sqlalchemy.orm import Session
from sqlalchemy import func, and_
from slowapi import Limiter
from slowapi.util import get_remote_address
from typing import Dict
import logging
import hashlib
import json
from ..database import get_db
from ..models.user import User
from ..models.stream import Stream
from ..models.comment import Comment
from ..models.watch_history import WatchHistory
from ..models.permission import Role
from ..schemas.user import UserResponse
from ..schemas.admin import UserRoleUpdate, UserListResponse, SystemStats
from ..auth import get_current_admin_user, require_permission
from ..sse import publish_event

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/admin", tags=["admin"])
limiter = Limiter(key_func=get_remote_address)


@router.get("/users")
async def list_users(
    skip: int = 0,
    limit: int = 50,
    role: str = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_permission("admin:users")),
    request: Request = None
):
    query = db.query(User)

    if role:
        role_obj = db.query(Role).filter(Role.name == role).first()
        if role_obj:
            query = query.filter(User.role_id == role_obj.id)

    users = query.order_by(User.created_at.desc()).offset(skip).limit(limit).all()
    result = [UserListResponse.from_orm_with_role(user) for user in users]

    # Calculate ETag from result
    result_dict = [r.model_dump() for r in result]
    result_json = json.dumps(result_dict, default=str)
    etag = hashlib.md5(result_json.encode()).hexdigest()

    if request and request.headers.get("if-none-match") == etag:
        return Response(status_code=304)

    return result


@router.get("/users/{user_id}", response_model=UserResponse)
async def get_user(
    user_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_permission("admin:users"))
):
    user = db.query(User).filter(User.id == user_id).first()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    return UserResponse.from_orm_with_role(user)


@router.put("/users/{user_id}/role", response_model=UserResponse)
async def update_user_role(
    user_id: str,
    role_update: UserRoleUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_permission("admin:users"))
):
    logger.info(f"Attempting to update role for user_id: {user_id} to role: {role_update.role}")
    user = db.query(User).filter(User.id == user_id).first()
    
    if not user:
        logger.warning(f"User not found: {user_id}")
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    logger.info(f"User found: {user.username}, current role: {user.role.name if user.role else None}")
    
    # Get role object
    new_role = db.query(Role).filter(Role.name == role_update.role).first()
    if not new_role:
        logger.warning(f"Role not found: {role_update.role}")
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Role not found"
        )
    
    logger.info(f"New role found: {new_role.name}")
    
    # Prevent removing admin role from last admin
    if user.role and user.role.name == "admin" and role_update.role != "admin":
        admin_role = db.query(Role).filter(Role.name == "admin").first()
        admin_count = db.query(User).filter(User.role_id == admin_role.id).count()
        logger.info(f"Admin count: {admin_count}")
        if admin_count <= 1:
            logger.warning("Cannot remove admin role from the last admin")
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Cannot remove admin role from the last admin"
            )
    
    user.role_id = new_role.id
    db.commit()
    db.refresh(user)
    
    # Publish SSE event for user role change
    publish_event("user_role_changed", {"user_id": str(user.id), "role_name": new_role.name})
    
    return UserResponse.from_orm_with_role(user)


@router.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_user(
    user_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_permission("admin:users"))
):
    user = db.query(User).filter(User.id == user_id).first()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    # Prevent deleting the last admin
    if user.role and user.role.name == "admin":
        admin_role = db.query(Role).filter(Role.name == "admin").first()
        admin_count = db.query(User).filter(User.role_id == admin_role.id).count()
        if admin_count <= 1:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Cannot delete the last admin"
            )
    
    # Prevent self-deletion
    if user.id == current_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot delete yourself"
        )
    
    db.delete(user)
    db.commit()
    
    return None


@router.get("/stats", response_model=SystemStats)
async def get_system_stats(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    total_users = db.query(User).count()
    total_streams = db.query(Stream).count()
    total_comments = db.query(Comment).count()

    # Active users: users who have watched something in the last 7 days
    from datetime import datetime, timedelta
    seven_days_ago = datetime.utcnow() - timedelta(days=7)
    active_users = db.query(WatchHistory).filter(
        WatchHistory.last_watched_at >= seven_days_ago
    ).distinct(WatchHistory.user_id).count()

    # Users by role
    from app.models.permission import Role
    users_by_role = {}
    for role_name in ["user", "mod", "subscriber", "creator", "admin"]:
        role = db.query(Role).filter(Role.name == role_name).first()
        if role:
            count = db.query(User).filter(User.role_id == role.id).count()
            users_by_role[role_name] = count
        else:
            users_by_role[role_name] = 0

    return SystemStats(
        total_users=total_users,
        total_streams=total_streams,
        total_comments=total_comments,
        active_users=active_users,
        users_by_role=users_by_role
    )


@router.put("/users/{user_id}/activate", response_model=UserResponse)
async def activate_user(
    user_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_permission("admin:users"))
):
    user = db.query(User).filter(User.id == user_id).first()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    user.is_active = True
    db.commit()
    db.refresh(user)
    
    return UserResponse.from_orm_with_role(user)


@router.put("/users/{user_id}/deactivate", response_model=UserResponse)
async def deactivate_user(
    user_id: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_permission("admin:users"))
):
    user = db.query(User).filter(User.id == user_id).first()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    # Prevent deactivating yourself
    if user.id == current_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot deactivate yourself"
        )
    
    user.is_active = False
    db.commit()
    db.refresh(user)
    
    return UserResponse.from_orm_with_role(user)
