from sqlalchemy.orm import Session, joinedload
from sqlalchemy import and_, or_, func
from typing import List, Optional
import uuid

from app.models.user_model import User
from app.models.tenant_model import Tenants
from app.schemas.user_schema import UserCreate, UserUpdate
from app.core.logging_config import get_db_logger

# 获取数据库专用日志器
db_logger = get_db_logger()


class UserRepository:
    """用户数据访问层"""

    def __init__(self, db: Session):
        self.db = db

    def get_user_by_id(self, user_id: uuid.UUID) -> Optional[User]:
        """根据ID获取用户"""
        db_logger.debug(f"根据ID查询用户: user_id={user_id}")
        
        try:
            user = self.db.query(User).options(joinedload(User.tenant)).filter(User.id == user_id).first()
            if user:
                db_logger.debug(f"用户查询成功: {user.username} (ID: {user_id})")
            else:
                db_logger.debug(f"用户不存在: user_id={user_id}")
            return user
        except Exception as e:
            db_logger.error(f"根据ID查询用户失败: user_id={user_id} - {str(e)}")
            raise

    def get_user_by_email(self, email: str) -> Optional[User]:
        """根据邮箱获取用户"""
        db_logger.debug(f"根据邮箱查询用户: email={email}")
        
        try:
            user = self.db.query(User).options(joinedload(User.tenant)).filter(User.email == email).first()
            if user:
                db_logger.debug(f"用户查询成功: {user.username} (email: {email})")
            else:
                db_logger.debug(f"用户不存在: email={email}")
            return user
        except Exception as e:
            db_logger.error(f"根据邮箱查询用户失败: email={email} - {str(e)}")
            raise

    def get_user_by_username(self, username: str) -> Optional[User]:
        """根据用户名获取用户"""
        db_logger.debug(f"根据用户名查询用户: username={username}")
        
        try:
            user = self.db.query(User).options(joinedload(User.tenant)).filter(User.username == username).first()
            if user:
                db_logger.debug(f"用户查询成功: {user.username} (ID: {user.id})")
            else:
                db_logger.debug(f"用户不存在: username={username}")
            return user
        except Exception as e:
            db_logger.error(f"根据用户名查询用户失败: username={username} - {str(e)}")
            raise

    def get_superuser(self) -> Optional[User]:
        """获取超级用户"""
        db_logger.debug("查询超级用户")
        
        try:
            user = self.db.query(User).options(joinedload(User.tenant)).filter(User.is_active.is_(True)).filter(User.is_superuser.is_(True)).first()
            if user:
                db_logger.debug(f"超级用户查询成功: {user.username}")
            else:
                db_logger.debug("超级用户不存在")
            return user
        except Exception as e:
            db_logger.error(f"查询超级用户失败: {str(e)}")
            raise
    def check_superuser_only(self) -> bool:
        """检查是否只有一个超级用户"""
        db_logger.debug("检查是否只有一个超级用户")
        
        try:
            count = self.db.query(User).options(joinedload(User.tenant)).filter(User.is_active.is_(True)).filter(User.is_superuser.is_(True)).count()
            return count == 1
        except Exception as e:
            db_logger.error(f"检查超级用户数量失败: {str(e)}")
            raise

    def create_user(
        self, 
        user_data: UserCreate, 
        hashed_password: str, 
        tenant_id: Optional[uuid.UUID] = None,
        is_superuser: bool = False
    ) -> User:
        """创建用户"""
        db_logger.debug(f"创建用户记录: username={user_data.username}, email={user_data.email}, is_superuser={is_superuser}")
        
        try:
            db_user = User(
                username=user_data.username,
                email=user_data.email,
                hashed_password=hashed_password,
                tenant_id=tenant_id,
                is_superuser=is_superuser,
            )
            self.db.add(db_user)
            self.db.flush()
            db_logger.info(f"用户记录创建成功: {user_data.username} (email: {user_data.email})")
            return db_user
        except Exception as e:
            db_logger.error(f"创建用户记录失败: username={user_data.username} - {str(e)}")
            raise

    def update_user(self, user_id: uuid.UUID, user_data: UserUpdate) -> Optional[User]:
        """更新用户"""
        db_logger.debug(f"更新用户: user_id={user_id}")
        
        try:
            user = self.get_user_by_id(user_id)
            if not user:
                db_logger.debug(f"用户不存在: user_id={user_id}")
                return None
            
            for field, value in user_data.dict(exclude_unset=True).items():
                setattr(user, field, value)
            
            self.db.flush()
            db_logger.info(f"用户更新成功: {user.username}")
            return user
        except Exception as e:
            db_logger.error(f"更新用户失败: user_id={user_id} - {str(e)}")
            raise

    def delete_user(self, user_id: uuid.UUID) -> bool:
        """删除用户"""
        db_logger.debug(f"删除用户: user_id={user_id}")
        
        try:
            user = self.get_user_by_id(user_id)
            if not user:
                db_logger.debug(f"用户不存在: user_id={user_id}")
                return False
            
            # 逻辑删除用户
            user.is_active = False
            self.db.flush()
            db_logger.info(f"用户删除成功（逻辑删除）: {user.username}")
            return True
        except Exception as e:
            db_logger.error(f"删除用户失败: user_id={user_id} - {str(e)}")
            raise

    def get_users_by_tenant(
        self, 
        tenant_id: uuid.UUID, 
        skip: int = 0, 
        limit: int = 100,
        is_active: Optional[bool] = None,
        search: Optional[str] = None
    ) -> List[User]:
        """获取租户下的用户列表"""
        db_logger.debug(f"查询租户用户: tenant_id={tenant_id}")
        
        try:
            query = self.db.query(User).options(joinedload(User.tenant)).filter(User.tenant_id == tenant_id)
            
            if is_active is not None:
                query = query.filter(User.is_active == is_active)
            
            if search:
                query = query.filter(
                    or_(
                        User.username.ilike(f"%{search}%"),
                        User.email.ilike(f"%{search}%")
                    )
                )
            
            users = query.offset(skip).limit(limit).all()
            db_logger.debug(f"租户用户查询成功: tenant_id={tenant_id}, count={len(users)}")
            return users
        except Exception as e:
            db_logger.error(f"查询租户用户失败: tenant_id={tenant_id} - {str(e)}")
            raise

    def count_users_by_tenant(
        self, 
        tenant_id: uuid.UUID,
        is_active: Optional[bool] = None,
        search: Optional[str] = None
    ) -> int:
        """统计租户下的用户数量"""
        try:
            query = self.db.query(func.count(User.id)).filter(User.tenant_id == tenant_id)
            
            if is_active is not None:
                query = query.filter(User.is_active == is_active)
            
            if search:
                query = query.filter(
                    or_(
                        User.username.ilike(f"%{search}%"),
                        User.email.ilike(f"%{search}%")
                    )
                )
            
            return query.scalar()
        except Exception as e:
            db_logger.error(f"统计租户用户失败: tenant_id={tenant_id} - {str(e)}")
            raise

    def get_superusers_by_tenant(
        self, 
        tenant_id: uuid.UUID, 
        is_active: Optional[bool] = True
    ) -> List[User]:
        """获取租户下的超管用户列表"""
        db_logger.debug(f"查询租户超管用户: tenant_id={tenant_id}")
        
        try:
            query = self.db.query(User).options(joinedload(User.tenant)).filter(
                and_(
                    User.tenant_id == tenant_id,
                    User.is_superuser == True
                )
            )
            
            if is_active is not None:
                query = query.filter(User.is_active == is_active)
            
            users = query.all()
            db_logger.debug(f"租户超管用户查询成功: tenant_id={tenant_id}, count={len(users)}")
            return users
        except Exception as e:
            db_logger.error(f"查询租户超管用户失败: tenant_id={tenant_id} - {str(e)}")
            raise

    def assign_user_to_tenant(self, user_id: uuid.UUID, tenant_id: uuid.UUID) -> bool:
        """将用户分配给租户"""
        db_logger.debug(f"分配用户到租户: user_id={user_id}, tenant_id={tenant_id}")
        
        try:
            user = self.get_user_by_id(user_id)
            if not user:
                db_logger.debug(f"用户不存在: user_id={user_id}")
                return False
            
            # 验证租户存在
            tenant = self.db.query(Tenants).filter(Tenants.id == tenant_id).first()
            if not tenant:
                db_logger.debug(f"租户不存在: tenant_id={tenant_id}")
                return False
            
            user.tenant_id = tenant_id
            self.db.flush()
            db_logger.info(f"用户分配成功: user={user.username}, tenant={tenant.name}")
            return True
        except Exception as e:
            db_logger.error(f"分配用户到租户失败: user_id={user_id}, tenant_id={tenant_id} - {str(e)}")
            raise

    def get_users_without_tenant(
        self, 
        skip: int = 0, 
        limit: int = 100,
        is_active: Optional[bool] = None
    ) -> List[User]:
        """获取没有租户的用户列表"""
        try:
            query = self.db.query(User).filter(User.tenant_id.is_(None))
            
            if is_active is not None:
                query = query.filter(User.is_active == is_active)
            
            return query.offset(skip).limit(limit).all()
        except Exception as e:
            db_logger.error(f"查询无租户用户失败: {str(e)}")
            raise


# 便利函数，保持向后兼容
def get_user_by_id(db: Session, user_id: uuid.UUID) -> Optional[User]:
    """根据ID获取用户"""
    return UserRepository(db).get_user_by_id(user_id)

def get_user_by_email(db: Session, email: str) -> Optional[User]:
    """根据邮箱获取用户"""
    return UserRepository(db).get_user_by_email(email)

def get_user_by_username(db: Session, username: str) -> Optional[User]:
    """根据用户名获取用户"""
    return UserRepository(db).get_user_by_username(username)

def get_superuser(db: Session) -> Optional[User]:
    """获取超级用户"""
    return UserRepository(db).get_superuser()

def check_superuser_only(db: Session) -> Optional[User]:
    """检查是否只有一个超级用户"""
    return UserRepository(db).check_superuser_only()

def create_user(
    db: Session, 
    user: UserCreate, 
    hashed_password: str, 
    tenant_id: Optional[uuid.UUID] = None,
    is_superuser: bool = False
) -> User:
    """创建用户（函数式接口）"""
    repo = UserRepository(db)
    return repo.create_user(user, hashed_password, tenant_id, is_superuser)


def get_superusers_by_tenant(
    db: Session, 
    tenant_id: uuid.UUID, 
    is_active: Optional[bool] = True
) -> List[User]:
    """获取租户下的超管用户列表（函数式接口）"""
    repo = UserRepository(db)
    return repo.get_superusers_by_tenant(tenant_id, is_active)
