"""
책갈피 관리 API 라우터
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, delete, and_
from sqlalchemy.orm import joinedload
from typing import List, Optional
from datetime import datetime

from ...core.database import get_db
from ...models.user import User
from ...models.document import Document
from ...models.bookmark import Bookmark
from ..dependencies import get_current_active_user
from pydantic import BaseModel


class CreateBookmarkRequest(BaseModel):
    """책갈피 생성 요청"""
    document_id: str
    title: str
    description: Optional[str] = None
    page_number: Optional[int] = None
    scroll_position: int = 0
    element_id: Optional[str] = None
    element_selector: Optional[str] = None


class UpdateBookmarkRequest(BaseModel):
    """책갈피 업데이트 요청"""
    title: Optional[str] = None
    description: Optional[str] = None
    page_number: Optional[int] = None
    scroll_position: Optional[int] = None
    element_id: Optional[str] = None
    element_selector: Optional[str] = None


class BookmarkResponse(BaseModel):
    """책갈피 응답"""
    id: str
    document_id: str
    title: str
    description: Optional[str]
    page_number: Optional[int]
    scroll_position: int
    element_id: Optional[str]
    element_selector: Optional[str]
    created_at: datetime
    updated_at: Optional[datetime]
    document_title: str

    class Config:
        from_attributes = True


router = APIRouter()


@router.post("/", response_model=BookmarkResponse)
async def create_bookmark(
    bookmark_data: CreateBookmarkRequest,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """책갈피 생성"""
    # 문서 존재 및 권한 확인
    result = await db.execute(select(Document).where(Document.id == bookmark_data.document_id))
    document = result.scalar_one_or_none()
    
    if not document:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Document not found"
        )
    
    # 문서 접근 권한 확인
    if not document.is_public and document.uploaded_by != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not enough permissions to access this document"
        )
    
    # 책갈피 생성
    bookmark = Bookmark(
        user_id=current_user.id,
        document_id=bookmark_data.document_id,
        title=bookmark_data.title,
        description=bookmark_data.description,
        page_number=bookmark_data.page_number,
        scroll_position=bookmark_data.scroll_position,
        element_id=bookmark_data.element_id,
        element_selector=bookmark_data.element_selector
    )
    
    db.add(bookmark)
    await db.commit()
    await db.refresh(bookmark)
    
    # 응답 데이터 생성
    response_data = BookmarkResponse.from_orm(bookmark)
    response_data.document_title = document.title
    
    return response_data


@router.get("/", response_model=List[BookmarkResponse])
async def list_user_bookmarks(
    skip: int = 0,
    limit: int = 50,
    document_id: Optional[str] = None,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """사용자의 모든 책갈피 조회"""
    query = (
        select(Bookmark)
        .options(joinedload(Bookmark.document))
        .where(Bookmark.user_id == current_user.id)
    )
    
    if document_id:
        query = query.where(Bookmark.document_id == document_id)
    
    query = query.order_by(Bookmark.created_at.desc()).offset(skip).limit(limit)
    
    result = await db.execute(query)
    bookmarks = result.scalars().all()
    
    # 응답 데이터 변환
    response_data = []
    for bookmark in bookmarks:
        bookmark_data = BookmarkResponse.from_orm(bookmark)
        bookmark_data.document_title = bookmark.document.title
        response_data.append(bookmark_data)
    
    return response_data


@router.get("/document/{document_id}", response_model=List[BookmarkResponse])
async def get_document_bookmarks(
    document_id: str,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """특정 문서의 책갈피 목록 조회"""
    # 문서 존재 및 권한 확인
    result = await db.execute(select(Document).where(Document.id == document_id))
    document = result.scalar_one_or_none()
    
    if not document:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Document not found"
        )
    
    # 문서 접근 권한 확인
    if not document.is_public and document.uploaded_by != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not enough permissions to access this document"
        )
    
    # 사용자의 책갈피만 조회
    result = await db.execute(
        select(Bookmark)
        .options(joinedload(Bookmark.document))
        .where(
            and_(
                Bookmark.document_id == document_id,
                Bookmark.user_id == current_user.id
            )
        )
        .order_by(Bookmark.page_number, Bookmark.scroll_position)
    )
    bookmarks = result.scalars().all()
    
    # 응답 데이터 변환
    response_data = []
    for bookmark in bookmarks:
        bookmark_data = BookmarkResponse.from_orm(bookmark)
        bookmark_data.document_title = bookmark.document.title
        response_data.append(bookmark_data)
    
    return response_data


@router.get("/{bookmark_id}", response_model=BookmarkResponse)
async def get_bookmark(
    bookmark_id: str,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """책갈피 상세 조회"""
    result = await db.execute(
        select(Bookmark)
        .options(joinedload(Bookmark.document))
        .where(Bookmark.id == bookmark_id)
    )
    bookmark = result.scalar_one_or_none()
    
    if not bookmark:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Bookmark not found"
        )
    
    # 소유자 확인
    if bookmark.user_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not enough permissions"
        )
    
    response_data = BookmarkResponse.from_orm(bookmark)
    response_data.document_title = bookmark.document.title
    
    return response_data


@router.put("/{bookmark_id}", response_model=BookmarkResponse)
async def update_bookmark(
    bookmark_id: str,
    bookmark_data: UpdateBookmarkRequest,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """책갈피 업데이트"""
    result = await db.execute(
        select(Bookmark)
        .options(joinedload(Bookmark.document))
        .where(Bookmark.id == bookmark_id)
    )
    bookmark = result.scalar_one_or_none()
    
    if not bookmark:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Bookmark not found"
        )
    
    # 소유자 확인
    if bookmark.user_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not enough permissions"
        )
    
    # 업데이트
    if bookmark_data.title is not None:
        bookmark.title = bookmark_data.title
    if bookmark_data.description is not None:
        bookmark.description = bookmark_data.description
    if bookmark_data.page_number is not None:
        bookmark.page_number = bookmark_data.page_number
    if bookmark_data.scroll_position is not None:
        bookmark.scroll_position = bookmark_data.scroll_position
    if bookmark_data.element_id is not None:
        bookmark.element_id = bookmark_data.element_id
    if bookmark_data.element_selector is not None:
        bookmark.element_selector = bookmark_data.element_selector
    
    await db.commit()
    await db.refresh(bookmark)
    
    response_data = BookmarkResponse.from_orm(bookmark)
    response_data.document_title = bookmark.document.title
    
    return response_data


@router.delete("/{bookmark_id}")
async def delete_bookmark(
    bookmark_id: str,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """책갈피 삭제"""
    result = await db.execute(select(Bookmark).where(Bookmark.id == bookmark_id))
    bookmark = result.scalar_one_or_none()
    
    if not bookmark:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Bookmark not found"
        )
    
    # 소유자 확인
    if bookmark.user_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not enough permissions"
        )
    
    # 책갈피 삭제
    await db.execute(delete(Bookmark).where(Bookmark.id == bookmark_id))
    await db.commit()
    
    return {"message": "Bookmark deleted successfully"}
