"""
문서 링크 관련 API 엔드포인트
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_
from typing import List, Optional
from pydantic import BaseModel
import uuid

from ...core.database import get_db
from ..dependencies import get_current_active_user
from ...models import User, Document, DocumentLink

router = APIRouter()


# Pydantic 모델들
class DocumentLinkCreate(BaseModel):
    target_document_id: str
    selected_text: str
    start_offset: int
    end_offset: int
    link_text: Optional[str] = None
    description: Optional[str] = None

    # 고급 링크 기능 (모두 Optional로 설정)
    target_text: Optional[str] = None
    target_start_offset: Optional[int] = None
    target_end_offset: Optional[int] = None
    link_type: Optional[str] = "document"  # "document" or "text_fragment"


class DocumentLinkUpdate(BaseModel):
    target_document_id: Optional[str] = None
    link_text: Optional[str] = None
    description: Optional[str] = None
    
    # 고급 링크 기능
    target_text: Optional[str] = None
    target_start_offset: Optional[int] = None
    target_end_offset: Optional[int] = None
    link_type: Optional[str] = None


class DocumentLinkResponse(BaseModel):
    id: str
    source_document_id: str
    target_document_id: str
    selected_text: str
    start_offset: int
    end_offset: int
    link_text: Optional[str]
    description: Optional[str]
    created_at: str
    updated_at: Optional[str]
    
    # 고급 링크 기능
    target_text: Optional[str]
    target_start_offset: Optional[int]
    target_end_offset: Optional[int]
    link_type: Optional[str] = "document"
    
    # 대상 문서 정보
    target_document_title: str
    target_document_book_id: Optional[str]

    class Config:
        from_attributes = True


class LinkableDocumentResponse(BaseModel):
    id: str
    title: str
    book_id: Optional[str]
    book_title: Optional[str]
    sort_order: int

    class Config:
        from_attributes = True


@router.post("/{document_id}/links", response_model=DocumentLinkResponse)
async def create_document_link(
    document_id: str,
    link_data: DocumentLinkCreate,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """문서 링크 생성"""
    print(f"🔗 링크 생성 요청 - 문서 ID: {document_id}")
    print(f"📋 링크 데이터: {link_data}")
    print(f"🎯 target_text: '{link_data.target_text}'")
    print(f"🎯 target_start_offset: {link_data.target_start_offset}")
    print(f"🎯 target_end_offset: {link_data.target_end_offset}")
    print(f"🎯 link_type: {link_data.link_type}")
    
    if link_data.link_type == 'text_fragment' and not link_data.target_text:
        print("🚨 CRITICAL: text_fragment 링크인데 target_text가 없습니다!")
    
    # 출발 문서 확인
    result = await db.execute(select(Document).where(Document.id == document_id))
    source_doc = result.scalar_one_or_none()
    
    if not source_doc:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Source document not found"
        )
    
    # 권한 확인
    if not source_doc.is_public and source_doc.uploaded_by != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied to source document"
        )
    
    # 대상 문서 확인
    result = await db.execute(select(Document).where(Document.id == link_data.target_document_id))
    target_doc = result.scalar_one_or_none()
    
    if not target_doc:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Target document not found"
        )
    
    # 대상 문서 권한 확인
    if not target_doc.is_public and target_doc.uploaded_by != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied to target document"
        )
    
    # HTML 문서만 링크 가능
    if not target_doc.html_path:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Can only link to HTML documents"
        )
    
    # 링크 생성
    new_link = DocumentLink(
        source_document_id=uuid.UUID(document_id),
        target_document_id=uuid.UUID(link_data.target_document_id),
        selected_text=link_data.selected_text,
        start_offset=link_data.start_offset,
        end_offset=link_data.end_offset,
        link_text=link_data.link_text,
        description=link_data.description,
        # 고급 링크 기능
        target_text=link_data.target_text,
        target_start_offset=link_data.target_start_offset,
        target_end_offset=link_data.target_end_offset,
        link_type=link_data.link_type,
        created_by=current_user.id
    )
    
    db.add(new_link)
    await db.commit()
    await db.refresh(new_link)
    
    print(f"✅ 링크 생성 완료: {source_doc.title} -> {target_doc.title}")
    print(f"   - 링크 타입: {new_link.link_type}")
    print(f"   - 선택된 텍스트: {new_link.selected_text}")
    print(f"   - 대상 텍스트: {new_link.target_text}")
    
    # 백링크는 자동으로 생성되지 않음 - 기존 링크를 역방향으로 조회하는 방식 사용
    
    # 응답 데이터 구성
    return DocumentLinkResponse(
        id=str(new_link.id),
        source_document_id=str(new_link.source_document_id),
        target_document_id=str(new_link.target_document_id),
        selected_text=new_link.selected_text,
        start_offset=new_link.start_offset,
        end_offset=new_link.end_offset,
        link_text=new_link.link_text,
        description=new_link.description,
        # 고급 링크 기능
        target_text=new_link.target_text,
        target_start_offset=new_link.target_start_offset,
        target_end_offset=new_link.target_end_offset,
        link_type=new_link.link_type,
        created_at=new_link.created_at.isoformat(),
        updated_at=new_link.updated_at.isoformat() if new_link.updated_at else None,
        target_document_title=target_doc.title,
        target_document_book_id=str(target_doc.book_id) if target_doc.book_id else None
    )


@router.get("/{document_id}/links", response_model=List[DocumentLinkResponse])
async def get_document_links(
    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="Access denied"
        )
    
    # 링크 조회 (JOIN으로 대상 문서 정보도 함께)
    result = await db.execute(
        select(DocumentLink, Document)
        .join(Document, DocumentLink.target_document_id == Document.id)
        .where(DocumentLink.source_document_id == document_id)
        .order_by(DocumentLink.start_offset.asc())
    )
    
    links_with_targets = result.all()
    
    # 응답 데이터 구성
    response_links = []
    for link, target_doc in links_with_targets:
        response_links.append(DocumentLinkResponse(
            id=str(link.id),
            source_document_id=str(link.source_document_id),
            target_document_id=str(link.target_document_id),
            selected_text=link.selected_text,
            start_offset=link.start_offset,
            end_offset=link.end_offset,
            link_text=link.link_text,
            description=link.description,
            created_at=link.created_at.isoformat(),
            updated_at=link.updated_at.isoformat() if link.updated_at else None,
            # 고급 링크 기능 (기존 링크는 None일 수 있음)
            target_text=getattr(link, 'target_text', None),
            target_start_offset=getattr(link, 'target_start_offset', None),
            target_end_offset=getattr(link, 'target_end_offset', None),
            link_type=getattr(link, 'link_type', 'document'),
            # 대상 문서 정보
            target_document_title=target_doc.title,
            target_document_book_id=str(target_doc.book_id) if target_doc.book_id else None
        ))
    
    return response_links


@router.get("/{document_id}/linkable-documents", response_model=List[LinkableDocumentResponse])
async def get_linkable_documents(
    document_id: str,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """링크 가능한 문서 목록 조회 (같은 서적 우선, 전체 HTML 문서)"""
    # 현재 문서 확인
    result = await db.execute(select(Document).where(Document.id == document_id))
    current_doc = result.scalar_one_or_none()
    
    if not current_doc:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Document not found"
        )
    
    # 권한 확인
    if not current_doc.is_public and current_doc.uploaded_by != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )
    
    # 링크 가능한 HTML 문서들 조회
    # 1. 같은 서적의 문서들 (우선순위)
    # 2. 다른 서적의 문서들
    from ...models import Book
    
    query = select(Document, Book).outerjoin(Book, Document.book_id == Book.id).where(
        and_(
            Document.html_path.isnot(None),  # HTML 문서만
            Document.id != document_id,      # 자기 자신 제외
            # 권한 확인: 공개 문서이거나 본인이 업로드한 문서
            (Document.is_public == True) | (Document.uploaded_by == current_user.id) | (current_user.is_admin == True)
        )
    ).order_by(
        # 같은 서적 우선, 그 다음 정렬 순서
        (Document.book_id == current_doc.book_id).desc(),
        Document.sort_order.asc().nulls_last(),
        Document.created_at.asc()
    )
    
    result = await db.execute(query)
    documents_with_books = result.all()
    
    # 응답 데이터 구성
    linkable_docs = []
    for doc, book in documents_with_books:
        linkable_docs.append(LinkableDocumentResponse(
            id=str(doc.id),
            title=doc.title,
            book_id=str(doc.book_id) if doc.book_id else None,
            book_title=book.title if book else None,
            sort_order=doc.sort_order or 0
        ))
    
    return linkable_docs


@router.put("/links/{link_id}", response_model=DocumentLinkResponse)
async def update_document_link(
    link_id: str,
    link_data: DocumentLinkUpdate,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """문서 링크 수정"""
    # 링크 조회
    result = await db.execute(select(DocumentLink).where(DocumentLink.id == link_id))
    link = result.scalar_one_or_none()
    
    if not link:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Link not found"
        )
    
    # 권한 확인 (생성자만 수정 가능)
    if link.created_by != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )
    
    # 대상 문서 변경 시 검증
    if link_data.target_document_id:
        result = await db.execute(select(Document).where(Document.id == link_data.target_document_id))
        target_doc = result.scalar_one_or_none()
        
        if not target_doc:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Target document not found"
            )
        
        if not target_doc.html_path:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Can only link to HTML documents"
            )
        
        link.target_document_id = uuid.UUID(link_data.target_document_id)
    
    # 필드 업데이트
    if link_data.link_text is not None:
        link.link_text = link_data.link_text
    if link_data.description is not None:
        link.description = link_data.description
    
    await db.commit()
    await db.refresh(link)
    
    # 대상 문서 정보 조회
    result = await db.execute(select(Document).where(Document.id == link.target_document_id))
    target_doc = result.scalar_one()
    
    return DocumentLinkResponse(
        id=str(link.id),
        source_document_id=str(link.source_document_id),
        target_document_id=str(link.target_document_id),
        selected_text=link.selected_text,
        start_offset=link.start_offset,
        end_offset=link.end_offset,
        link_text=link.link_text,
        description=link.description,
        created_at=link.created_at.isoformat(),
        updated_at=link.updated_at.isoformat() if link.updated_at else None,
        target_document_title=target_doc.title,
        target_document_book_id=str(target_doc.book_id) if target_doc.book_id else None
    )


@router.delete("/links/{link_id}")
async def delete_document_link(
    link_id: str,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """문서 링크 삭제"""
    # 링크 조회
    result = await db.execute(select(DocumentLink).where(DocumentLink.id == link_id))
    link = result.scalar_one_or_none()
    
    if not link:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Link not found"
        )
    
    # 권한 확인 (생성자만 삭제 가능)
    if link.created_by != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied"
        )
    
    await db.delete(link)
    await db.commit()
    
    return {"message": "Link deleted successfully"}


# 백링크 관련 모델
class BacklinkResponse(BaseModel):
    id: str
    source_document_id: str
    source_document_title: str
    source_document_book_id: Optional[str]
    source_content_type: Optional[str] = "document"  # "document" or "note"
    target_document_id: str
    target_document_title: str
    selected_text: str  # 소스 문서에서 선택한 텍스트
    start_offset: int   # 소스 문서 오프셋
    end_offset: int     # 소스 문서 오프셋
    link_text: Optional[str]
    description: Optional[str]
    link_type: str
    target_text: Optional[str]  # 🎯 타겟 문서의 텍스트 (백링크 렌더링용)
    target_start_offset: Optional[int]  # 🎯 타겟 문서 오프셋 (백링크 렌더링용)
    target_end_offset: Optional[int]    # 🎯 타겟 문서 오프셋 (백링크 렌더링용)
    created_at: str
    
    class Config:
        from_attributes = True


@router.get("/{document_id}/backlinks", response_model=List[BacklinkResponse])
async def get_document_backlinks(
    document_id: str,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """문서의 백링크 조회 (이 문서를 참조하는 모든 링크)"""
    print(f"🔍 백링크 API 호출됨 - 문서 ID: {document_id}, 사용자: {current_user.email}")
    
    # 문서 존재 확인
    result = await db.execute(select(Document).where(Document.id == document_id))
    document = result.scalar_one_or_none()
    
    if not document:
        print(f"❌ 문서를 찾을 수 없음: {document_id}")
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Document not found"
        )
    
    print(f"✅ 문서 찾음: {document.title}")
    
    # 권한 확인
    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="Access denied"
        )
    
    # 이 문서를 대상으로 하는 모든 링크 조회 (백링크)
    from ...models import Book
    from ...models.note_link import NoteLink
    from ...models.note_document import NoteDocument
    from ...models.notebook import Notebook
    
    # 1. 일반 문서에서 오는 백링크 (DocumentLink)
    doc_query = select(DocumentLink, Document, Book).join(
        Document, DocumentLink.source_document_id == Document.id
    ).outerjoin(Book, Document.book_id == Book.id).where(
        and_(
            DocumentLink.target_document_id == document_id,
            # 권한 확인: 공개 문서이거나 본인이 업로드한 문서
            (Document.is_public == True) | (Document.uploaded_by == current_user.id) | (current_user.is_admin == True)
        )
    ).order_by(DocumentLink.created_at.desc())
    
    doc_result = await db.execute(doc_query)
    backlinks = []
    
    print(f"🔍 문서 백링크 쿼리 실행 완료")
    
    # 일반 문서 백링크 처리
    for link, source_doc, book in doc_result.fetchall():
        print(f"📋 백링크 발견: {source_doc.title} -> {document.title}")
        print(f"   - 소스 텍스트 (selected_text): {link.selected_text}")
        print(f"   - 타겟 텍스트 (target_text): {link.target_text}")
        print(f"   - 타겟 오프셋: {link.target_start_offset}-{link.target_end_offset}")
        print(f"   - 링크 타입: {link.link_type}")
        
        backlinks.append(BacklinkResponse(
            id=str(link.id),
            source_document_id=str(link.source_document_id),
            source_document_title=source_doc.title,
            source_document_book_id=str(book.id) if book else None,
            source_content_type="document",  # 일반 문서
            target_document_id=str(link.target_document_id),
            target_document_title=document.title,
            selected_text=link.selected_text,  # 소스 문서에서 선택한 텍스트 (참고용)
            start_offset=link.start_offset,    # 소스 문서 오프셋 (참고용)
            end_offset=link.end_offset,        # 소스 문서 오프셋 (참고용)
            link_text=link.link_text,
            description=link.description,
            link_type=link.link_type,
            target_text=link.target_text,           # 🎯 타겟 문서의 텍스트 (백링크 렌더링용)
            target_start_offset=link.target_start_offset,  # 🎯 타겟 문서 오프셋 (백링크 렌더링용)
            target_end_offset=link.target_end_offset,      # 🎯 타겟 문서 오프셋 (백링크 렌더링용)
            created_at=link.created_at.isoformat()
        ))
    
    # 2. 노트에서 오는 백링크 (NoteLink) - 동기 쿼리 사용
    try:
        from ...core.database import get_sync_db
        sync_db = next(get_sync_db())
        
        # 노트에서 이 문서를 대상으로 하는 링크들 조회
        note_links = sync_db.query(NoteLink).join(
            NoteDocument, NoteLink.source_note_id == NoteDocument.id
        ).outerjoin(Notebook, NoteDocument.notebook_id == Notebook.id).filter(
            NoteLink.target_document_id == document_id
        ).all()
        
        print(f"🔍 노트 백링크 쿼리 실행 완료: {len(note_links)}개 발견")
        
        # 노트 백링크 처리
        for link in note_links:
            source_note = sync_db.query(NoteDocument).filter(NoteDocument.id == link.source_note_id).first()
            notebook = sync_db.query(Notebook).filter(Notebook.id == source_note.notebook_id).first() if source_note else None
            
            if source_note:
                print(f"📋 노트 백링크 발견: {source_note.title} -> {document.title}")
                print(f"   - 소스 텍스트 (selected_text): {link.selected_text}")
                print(f"   - 타겟 텍스트 (target_text): {link.target_text}")
                print(f"   - 타겟 오프셋: {link.target_start_offset}-{link.target_end_offset}")
                print(f"   - 링크 타입: {link.link_type}")
                
                backlinks.append(BacklinkResponse(
                    id=str(link.id),
                    source_document_id=str(link.source_note_id),  # 노트 ID를 문서 ID로 사용
                    source_document_title=f"📝 {source_note.title}",  # 노트임을 표시
                    source_document_book_id=str(notebook.id) if notebook else None,
                    source_content_type="note",  # 노트 문서
                    target_document_id=str(link.target_document_id) if link.target_document_id else document_id,
                    target_document_title=document.title,
                    selected_text=link.selected_text,
                    start_offset=link.start_offset,
                    end_offset=link.end_offset,
                    link_text=link.link_text,
                    description=link.description,
                    link_type=link.link_type,
                    target_text=link.target_text,
                    target_start_offset=link.target_start_offset,
                    target_end_offset=link.target_end_offset,
                    created_at=link.created_at.isoformat() if link.created_at else None
                ))
        
        sync_db.close()
    except Exception as e:
        print(f"❌ 노트 백링크 조회 실패: {e}")
    
    print(f"✅ 총 {len(backlinks)}개의 백링크 반환 (문서 + 노트)")
    return backlinks


@router.get("/{document_id}/link-fragments")
async def get_document_link_fragments(
    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="Access denied"
        )
    
    # 이 문서에서 출발하는 모든 링크 조회
    query = select(DocumentLink, Document).join(
        Document, DocumentLink.target_document_id == Document.id
    ).where(
        and_(
            DocumentLink.source_document_id == document_id,
            # 권한 확인: 공개 문서이거나 본인이 업로드한 문서
            (Document.is_public == True) | (Document.uploaded_by == current_user.id) | (current_user.is_admin == True)
        )
    ).order_by(DocumentLink.start_offset.asc())
    
    result = await db.execute(query)
    fragments = []
    
    for link, target_doc in result.fetchall():
        fragments.append({
            "link_id": str(link.id),
            "start_offset": link.start_offset,
            "end_offset": link.end_offset,
            "selected_text": link.selected_text,
            "target_document_id": str(link.target_document_id),
            "target_document_title": target_doc.title,
            "link_text": link.link_text,
            "description": link.description,
            "link_type": link.link_type,
            "target_text": link.target_text,
            "target_start_offset": link.target_start_offset,
            "target_end_offset": link.target_end_offset
        })
    
    return fragments
