from sqlalchemy.orm import Session
from datetime import datetime
from typing import Optional
from app.models.user import User, UserRole
from app.schemas.auth import UserRegister, Token
from app.utils.security import hash_password, verify_password
from app.utils.jwt_handler import create_access_token, create_refresh_token
from app.utils.exceptions import AuthenticationError, ConflictError

class AuthService:
    """인증 관련 비즈니스 로직"""
    
    @staticmethod
    def register_user(db: Session, user_data: UserRegister) -> User:
        """사용자 등록"""
        # 중복 체크
        if db.query(User).filter(User.username == user_data.username).first():
            raise ConflictError("이미 존재하는 사용자명입니다")
        
        if db.query(User).filter(User.email == user_data.email).first():
            raise ConflictError("이미 존재하는 이메일입니다")
        
        # 새 사용자 생성
        new_user = User(
            username=user_data.username,
            email=user_data.email,
            hashed_password=hash_password(user_data.password),
            full_name=user_data.full_name,
            role=UserRole.USER
        )
        
        db.add(new_user)
        db.commit()
        db.refresh(new_user)
        
        return new_user
    
    @staticmethod
    def authenticate_user(db: Session, username: str, password: str) -> User:
        """사용자 인증"""
        user = db.query(User).filter(User.username == username).first()
        
        if not user:
            raise AuthenticationError("사용자를 찾을 수 없습니다")
        
        if not user.is_active:
            raise AuthenticationError("비활성화된 계정입니다")
        
        if not verify_password(password, user.hashed_password):
            raise AuthenticationError("비밀번호가 일치하지 않습니다")
        
        # 마지막 로그인 시간 업데이트
        user.last_login = datetime.utcnow()
        db.commit()
        
        return user
    
    @staticmethod
    def create_tokens(user: User) -> Token:
        """JWT 토큰 생성"""
        token_data = {
            "sub": str(user.id),
            "username": user.username,
            "role": user.role.value
        }
        
        access_token = create_access_token(token_data)
        refresh_token = create_refresh_token(token_data)
        
        return Token(
            access_token=access_token,
            refresh_token=refresh_token,
            token_type="bearer",
            expires_in=1800  # 30분
        )
    
    @staticmethod
    def get_user_by_id(db: Session, user_id: int) -> Optional[User]:
        """사용자 ID로 조회"""
        return db.query(User).filter(User.id == user_id).first()
    
    @staticmethod
    def get_user_by_username(db: Session, username: str) -> Optional[User]:
        """사용자명으로 조회"""
        return db.query(User).filter(User.username == username).first()

auth_service = AuthService()
