"""
Document management API routes for DOCX/PDF uploads, processing, and AI enhancement.
"""

import json
import logging
import os
from typing import List, Optional

from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile, Query, Request
from starlette.requests import Request

from common.memos_core.schemas import (
    DocumentCreate,
    DocumentResponse,
    DocumentUpdate,
    DocumentListResponse,
    DocumentProcessRequest,
    DocumentImportRequest,
    DocumentUploadResponse,
    DocumentDeleteResponse,
)
from common.memos_core.services import get_document_service
from common.encryption import mask_api_key

router = APIRouter(prefix="/documents", tags=["documents"])

logger = logging.getLogger(__name__)


@router.post("/upload", response_model=DocumentUploadResponse)
async def upload_document(
    request: Request,
    file: UploadFile = File(...),
    workspace_id: str = Form(default="PERSONAL"),
    title: Optional[str] = Form(default=None),
    document_service=Depends(get_document_service),
):
    """
    Upload a DOCX or PDF document.

    - **file**: The document file to upload (DOCX, PDF supported)
    - **workspace_id**: Workspace to associate with (PERSONAL, AI_SALES_CRM, etc.)
    - **title**: Optional title override (defaults to original filename)

    Returns the created document record with status PENDING. Processing happens asynchronously.
    """
    # Validate file type
    allowed_types = [
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/pdf',
        'text/plain'
    ]
    if file.content_type not in allowed_types:
        raise HTTPException(
            status_code=400,
            detail=f"Unsupported file type: {file.content_type}. Supported: DOCX, PDF, TXT"
        )

    # Read file content
    try:
        content = await file.read()
        file_size = len(content)
    except Exception as e:
        logger.error(f"Failed to read uploaded file: {e}")
        raise HTTPException(status_code=400, detail="Failed to read uploaded file")

    # Verify user
    user_id = getattr(request.state, "user_id", None) or "1"

    # Ensure upload directory exists
    upload_dir = document_service.upload_dir
    os.makedirs(upload_dir, exist_ok=True)

    # Create document record (file will be saved separately)
    original_filename = file.filename or "untitled"
    safe_filename = f"{generate_uid()}_{original_filename}"
    file_path = os.path.join(upload_dir, safe_filename)

    # Save file to disk
    try:
        with open(file_path, "wb") as f:
            f.write(content)
    except Exception as e:
        logger.error(f"Failed to save uploaded file: {e}")
        raise HTTPException(status_code=500, detail="Failed to save uploaded file")

    # Create DB record
    try:
        doc_create = DocumentCreate(
            filename=safe_filename,
            original_filename=original_filename,
            file_size=file_size,
            mime_type=file.content_type,
            workspace_id=workspace_id,
            title=title,
        )
        doc_response = await document_service.create_document(doc_create, user_id)
        return DocumentUploadResponse(
            success=True,
            document=doc_response,
            message="Document uploaded successfully"
        )
    except Exception as e:
        # Cleanup file on DB error
        if os.path.exists(file_path):
            os.remove(file_path)
        logger.error(f"Failed to create document record: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get("", response_model=DocumentListResponse)
async def list_documents(
    request: Request,
    workspace_id: Optional[str] = Query(default=None, description="Filter by workspace"),
    status: Optional[str] = Query(default=None, description="Filter by status (PENDING, PROCESSING, COMPLETED, FAILED)"),
    limit: int = Query(default=50, ge=1, le=100, description="Max number of documents to return"),
    offset: int = Query(default=0, ge=0, description="Number of documents to skip"),
    document_service=Depends(get_document_service),
):
    """
    List documents for the authenticated user.

    Supports filtering by workspace and status, with pagination.
    """
    user_id = getattr(request.state, "user_id", None) or "1"

    return await document_service.list_documents(
        creator_id=user_id,
        workspace_id=workspace_id,
        status=status,
        limit=limit,
        offset=offset
    )


@router.get("/{doc_id}", response_model=DocumentResponse)
async def get_document(
    doc_id: int,
    request: Request,
    document_service=Depends(get_document_service),
):
    """
    Get a specific document by ID.
    """
    user_id = getattr(request.state, "user_id", None) or "1"
    doc = await document_service.get_document(doc_id)

    if not doc or doc.creator_id != user_id:
        raise HTTPException(status_code=404, detail="Document not found")

    return doc


@router.patch("/{doc_id}", response_model=DocumentResponse)
async def update_document(
    doc_id: int,
    request: Request,
    payload: DocumentUpdate,
    document_service=Depends(get_document_service),
):
    """
    Update document metadata (title, tags, summary, workspace).
    """
    user_id = getattr(request.state, "user_id", None) or "1"
    doc = await document_service.update_document(doc_id, payload, user_id)

    if not doc:
        raise HTTPException(status_code=404, detail="Document not found or access denied")

    return doc


@router.post("/{doc_id}/process", response_model=DocumentResponse)
async def process_document(
    doc_id: int,
    request: Request,
    payload: Optional[DocumentProcessRequest] = None,
    document_service=Depends(get_document_service),
):
    """
    Manually trigger document processing and AI enhancement.

    Extracts text from the document, generates tags and summary using AI (if enabled).
    """
    user_id = getattr(request.state, "user_id", None) or "1"
    doc = await document_service.get_document(doc_id)

    if not doc or doc.creator_id != user_id:
        raise HTTPException(status_code=404, detail="Document not found")

    if doc.status == "PROCESSING":
        raise HTTPException(status_code=400, detail="Document is already being processed")

    # Re-process the document
    try:
        processed_doc = await document_service.process_document(doc_id, user_id)
        return processed_doc
    except Exception as e:
        logger.error(f"Failed to process document {doc_id}: {e}")
        raise HTTPException(status_code=500, detail=f"Processing failed: {str(e)}")


@router.post("/{doc_id}/import", response_model=DocumentResponse)
async def import_document_to_memo(
    doc_id: int,
    request: Request,
    payload: Optional[DocumentImportRequest] = None,
    document_service=Depends(get_document_service),
):
    """
    Import document content as a new memo.

    Creates a new memo with the document's extracted content, optionally with provided tags and visibility.
    """
    user_id = getattr(request.state, "user_id", None) or "1"

    if payload is None:
        payload = DocumentImportRequest()

    try:
        memo = await document_service.import_to_memo(
            doc_id=doc_id,
            creator_id=user_id,
            memo_title=payload.memo_title,
            tags=payload.tags,
            visibility=payload.visibility
        )
        # Return the original document with a note that import succeeded
        doc = await document_service.get_document(doc_id)
        return doc
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Failed to import document {doc_id}: {e}")
        raise HTTPException(status_code=500, detail=f"Import failed: {str(e)}")


@router.delete("/{doc_id}", response_model=DocumentDeleteResponse)
async def delete_document(
    doc_id: int,
    request: Request,
    document_service=Depends(get_document_service),
):
    """
    Delete a document and its associated file.
    """
    user_id = getattr(request.state, "user_id", None) or "1"
    deleted = await document_service.delete_document(doc_id, user_id)

    if not deleted:
        raise HTTPException(status_code=404, detail="Document not found or access denied")

    return DocumentDeleteResponse(success=True, message="Document deleted successfully")


# Helper function (should be in sqlite_client but using here for convenience)
def generate_uid() -> str:
    """Generate a unique ID for documents."""
    import secrets
    return secrets.token_urlsafe(16)[:22]
