"""
사용자 관리 API
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete
from sqlalchemy.orm import selectinload
from pydantic import BaseModel, EmailStr
from typing import List, Optional
from datetime import datetime

from ...core.database import get_db
from ...core.security import get_password_hash, verify_password
from ...models.user import User
from ..dependencies import get_current_active_user, get_current_admin_user

router = APIRouter()


class UserResponse(BaseModel):
    """사용자 응답"""
    id: str
    email: str
    full_name: Optional[str]
    is_active: bool
    is_admin: bool
    role: str
    can_manage_books: bool
    can_manage_notes: bool
    can_manage_novels: bool
    session_timeout_minutes: int
    theme: str
    language: str
    timezone: str
    created_at: datetime
    updated_at: Optional[datetime]
    last_login: Optional[datetime]

    class Config:
        from_attributes = True


class CreateUserRequest(BaseModel):
    """사용자 생성 요청"""
    email: EmailStr
    password: str
    full_name: Optional[str] = None
    role: str = "user"
    can_manage_books: bool = True
    can_manage_notes: bool = True
    can_manage_novels: bool = True
    session_timeout_minutes: int = 5


class UpdateUserRequest(BaseModel):
    """사용자 업데이트 요청"""
    full_name: Optional[str] = None
    is_active: Optional[bool] = None
    role: Optional[str] = None
    can_manage_books: Optional[bool] = None
    can_manage_notes: Optional[bool] = None
    can_manage_novels: Optional[bool] = None
    session_timeout_minutes: Optional[int] = None


class UpdateProfileRequest(BaseModel):
    """프로필 업데이트 요청"""
    full_name: Optional[str] = None
    theme: Optional[str] = None
    language: Optional[str] = None
    timezone: Optional[str] = None


class ChangePasswordRequest(BaseModel):
    """비밀번호 변경 요청"""
    current_password: str
    new_password: str


@router.get("/me", response_model=UserResponse)
async def get_current_user_profile(
    current_user: User = Depends(get_current_active_user)
):
    """현재 사용자 프로필 조회"""
    return UserResponse(
        id=str(current_user.id),
        email=current_user.email,
        full_name=current_user.full_name,
        is_active=current_user.is_active,
        is_admin=current_user.is_admin,
        role=current_user.role,
        can_manage_books=current_user.can_manage_books,
        can_manage_notes=current_user.can_manage_notes,
        can_manage_novels=current_user.can_manage_novels,
        session_timeout_minutes=current_user.session_timeout_minutes,
        theme=current_user.theme,
        language=current_user.language,
        timezone=current_user.timezone,
        created_at=current_user.created_at,
        updated_at=current_user.updated_at,
        last_login=current_user.last_login
    )


@router.put("/me", response_model=UserResponse)
async def update_current_user_profile(
    profile_data: UpdateProfileRequest,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """현재 사용자 프로필 업데이트"""
    update_fields = profile_data.model_dump(exclude_unset=True)
    
    for field, value in update_fields.items():
        setattr(current_user, field, value)
    
    current_user.updated_at = datetime.utcnow()
    await db.commit()
    await db.refresh(current_user)
    
    return UserResponse(
        id=str(current_user.id),
        email=current_user.email,
        full_name=current_user.full_name,
        is_active=current_user.is_active,
        is_admin=current_user.is_admin,
        role=current_user.role,
        can_manage_books=current_user.can_manage_books,
        can_manage_notes=current_user.can_manage_notes,
        can_manage_novels=current_user.can_manage_novels,
        session_timeout_minutes=current_user.session_timeout_minutes,
        theme=current_user.theme,
        language=current_user.language,
        timezone=current_user.timezone,
        created_at=current_user.created_at,
        updated_at=current_user.updated_at,
        last_login=current_user.last_login
    )


@router.post("/me/change-password")
async def change_current_user_password(
    password_data: ChangePasswordRequest,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """현재 사용자 비밀번호 변경"""
    # 현재 비밀번호 확인
    if not verify_password(password_data.current_password, current_user.hashed_password):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Current password is incorrect"
        )
    
    # 새 비밀번호 설정
    current_user.hashed_password = get_password_hash(password_data.new_password)
    current_user.updated_at = datetime.utcnow()
    
    await db.commit()
    
    return {"message": "Password changed successfully"}


@router.get("/", response_model=List[UserResponse])
async def list_users(
    skip: int = 0,
    limit: int = 50,
    current_user: User = Depends(get_current_admin_user),
    db: AsyncSession = Depends(get_db)
):
    """사용자 목록 조회 (관리자 전용)"""
    result = await db.execute(
        select(User)
        .order_by(User.created_at.desc())
        .offset(skip)
        .limit(limit)
    )
    users = result.scalars().all()
    
    return [
        UserResponse(
            id=str(user.id),
            email=user.email,
            full_name=user.full_name,
            is_active=user.is_active,
            is_admin=user.is_admin,
            role=user.role,
            can_manage_books=user.can_manage_books,
            can_manage_notes=user.can_manage_notes,
            can_manage_novels=user.can_manage_novels,
            session_timeout_minutes=user.session_timeout_minutes,
            theme=user.theme,
            language=user.language,
            timezone=user.timezone,
            created_at=user.created_at,
            updated_at=user.updated_at,
            last_login=user.last_login
        )
        for user in users
    ]


@router.post("/", response_model=UserResponse)
async def create_user(
    user_data: CreateUserRequest,
    current_user: User = Depends(get_current_admin_user),
    db: AsyncSession = Depends(get_db)
):
    """사용자 생성 (관리자 전용)"""
    # 이메일 중복 확인
    existing_user = await db.execute(
        select(User).where(User.email == user_data.email)
    )
    if existing_user.scalar_one_or_none():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Email already registered"
        )
    
    # 권한 확인 (root만 admin/root 계정 생성 가능)
    if user_data.role in ["admin", "root"] and current_user.role != "root":
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Only root users can create admin accounts"
        )
    
    # 사용자 생성
    hashed_password = get_password_hash(user_data.password)
    
    new_user = User(
        email=user_data.email,
        hashed_password=hashed_password,
        full_name=user_data.full_name,
        is_active=True,
        is_admin=user_data.role in ["admin", "root"],
        role=user_data.role,
        can_manage_books=user_data.can_manage_books,
        can_manage_notes=user_data.can_manage_notes,
        can_manage_novels=user_data.can_manage_novels,
        session_timeout_minutes=user_data.session_timeout_minutes
    )
    
    db.add(new_user)
    await db.commit()
    await db.refresh(new_user)
    
    return UserResponse(
        id=str(new_user.id),
        email=new_user.email,
        full_name=new_user.full_name,
        is_active=new_user.is_active,
        is_admin=new_user.is_admin,
        role=new_user.role,
        can_manage_books=new_user.can_manage_books,
        can_manage_notes=new_user.can_manage_notes,
        can_manage_novels=new_user.can_manage_novels,
        session_timeout_minutes=new_user.session_timeout_minutes,
        theme=new_user.theme,
        language=new_user.language,
        timezone=new_user.timezone,
        created_at=new_user.created_at,
        updated_at=new_user.updated_at,
        last_login=new_user.last_login
    )


@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
    user_id: str,
    current_user: User = Depends(get_current_admin_user),
    db: AsyncSession = Depends(get_db)
):
    """사용자 상세 조회 (관리자 전용)"""
    result = await db.execute(select(User).where(User.id == user_id))
    user = result.scalar_one_or_none()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    return UserResponse(
        id=str(user.id),
        email=user.email,
        full_name=user.full_name,
        is_active=user.is_active,
        is_admin=user.is_admin,
        role=user.role,
        can_manage_books=user.can_manage_books,
        can_manage_notes=user.can_manage_notes,
        can_manage_novels=user.can_manage_novels,
        session_timeout_minutes=user.session_timeout_minutes,
        theme=user.theme,
        language=user.language,
        timezone=user.timezone,
        created_at=user.created_at,
        updated_at=user.updated_at,
        last_login=user.last_login
    )


@router.put("/{user_id}", response_model=UserResponse)
async def update_user(
    user_id: str,
    user_data: UpdateUserRequest,
    current_user: User = Depends(get_current_admin_user),
    db: AsyncSession = Depends(get_db)
):
    """사용자 정보 업데이트 (관리자 전용)"""
    result = await db.execute(select(User).where(User.id == user_id))
    user = result.scalar_one_or_none()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    # 권한 확인 (root만 admin/root 계정 수정 가능)
    if user.role in ["admin", "root"] and current_user.role != "root":
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Only root users can modify admin accounts"
        )
    
    # 업데이트할 필드들 적용
    update_fields = user_data.model_dump(exclude_unset=True)
    
    for field, value in update_fields.items():
        if field == "role":
            # 역할 변경 시 is_admin도 함께 업데이트
            setattr(user, field, value)
            user.is_admin = value in ["admin", "root"]
        else:
            setattr(user, field, value)
    
    user.updated_at = datetime.utcnow()
    await db.commit()
    await db.refresh(user)
    
    return UserResponse(
        id=str(user.id),
        email=user.email,
        full_name=user.full_name,
        is_active=user.is_active,
        is_admin=user.is_admin,
        role=user.role,
        can_manage_books=user.can_manage_books,
        can_manage_notes=user.can_manage_notes,
        can_manage_novels=user.can_manage_novels,
        session_timeout_minutes=user.session_timeout_minutes,
        theme=user.theme,
        language=user.language,
        timezone=user.timezone,
        created_at=user.created_at,
        updated_at=user.updated_at,
        last_login=user.last_login
    )


@router.delete("/{user_id}")
async def delete_user(
    user_id: str,
    current_user: User = Depends(get_current_admin_user),
    db: AsyncSession = Depends(get_db)
):
    """사용자 삭제 (관리자 전용)"""
    result = await db.execute(select(User).where(User.id == user_id))
    user = result.scalar_one_or_none()
    
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    # 자기 자신 삭제 방지
    if user.id == current_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot delete your own account"
        )
    
    # root 계정 삭제 방지
    if user.role == "root":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot delete root account"
        )
    
    # 권한 확인 (root만 admin 계정 삭제 가능)
    if user.role == "admin" and current_user.role != "root":
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Only root users can delete admin accounts"
        )
    
    await db.execute(delete(User).where(User.id == user_id))
    await db.commit()
    
    return {"message": "User deleted successfully"}