"""
Knowledge Base Management API endpoints for Socrates.

Provides document import, search, and knowledge management functionality.
"""

import logging
import tempfile
import uuid
from pathlib import Path
from typing import Optional

from fastapi import APIRouter, Body, Depends, File, Form, HTTPException, UploadFile, status
from fastapi.responses import FileResponse

from socrates_api.auth import get_current_user
from socrates_api.database import get_database
from socrates_api.models import APIResponse, BulkImportData, ErrorResponse
from socratic_system.database import ProjectDatabase

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/knowledge", tags=["knowledge"])


def _get_orchestrator():
    """Get the global orchestrator instance for agent-based processing."""
    from socrates_api.main import app_state

    if app_state.get("orchestrator") is None:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Orchestrator not initialized. Please call /initialize first.",
        )
    return app_state["orchestrator"]


@router.get(
    "/documents",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="List documents with advanced filtering",
    responses={
        200: {"description": "Documents retrieved"},
        400: {"description": "Invalid parameters", "model": ErrorResponse},
    },
)
async def list_documents(
    project_id: Optional[str] = None,
    document_type: Optional[str] = None,
    search_query: Optional[str] = None,
    limit: int = 50,
    offset: int = 0,
    sort_by: str = "uploaded_at",
    sort_order: str = "desc",
    current_user: str = Depends(get_current_user),
    db: ProjectDatabase = Depends(get_database),
):
    """
    List knowledge base documents with advanced filtering and pagination.

    Args:
        project_id: Optional project ID to filter documents
        document_type: Optional document type filter (file, url, text, entry)
        search_query: Optional search term for document title/content
        limit: Maximum number of documents to return (default 50)
        offset: Number of documents to skip (default 0)
        sort_by: Field to sort by (uploaded_at, title, document_type) (default uploaded_at)
        sort_order: Sort order (asc, desc) (default desc)
        current_user: Current authenticated user
        db: Database connection

    Returns:
        Dictionary with documents and pagination info
    """
    try:
        if project_id:
            # Verify user has access to project using RBAC (viewers and above can read knowledge)
            from socrates_api.auth.project_access import check_project_access

            await check_project_access(project_id, current_user, db, min_role="viewer")
            documents = db.get_project_knowledge_documents(project_id)
        else:
            # Get all documents for user
            documents = db.get_user_knowledge_documents(current_user)

        # Apply filters
        filtered_docs = []
        for doc in documents:
            # Filter by document type
            if document_type and doc.get("document_type") != document_type:
                continue

            # Filter by search query in title or source
            if search_query:
                query_lower = search_query.lower()
                title_match = query_lower in (doc.get("title", "") or "").lower()
                source_match = query_lower in (doc.get("source", "") or "").lower()
                if not (title_match or source_match):
                    continue

            filtered_docs.append(doc)

        # Apply sorting
        sort_reverse = sort_order.lower() == "desc"
        if sort_by == "uploaded_at":
            filtered_docs.sort(key=lambda d: d.get("uploaded_at", ""), reverse=sort_reverse)
        elif sort_by == "title":
            filtered_docs.sort(key=lambda d: (d.get("title") or "").lower(), reverse=sort_reverse)
        elif sort_by == "document_type":
            filtered_docs.sort(key=lambda d: d.get("document_type", ""), reverse=sort_reverse)

        # Apply pagination
        total = len(filtered_docs)
        paginated_docs = filtered_docs[offset : offset + limit]

        # Transform to frontend format
        doc_list = []
        orchestrator = None
        try:
            orchestrator = _get_orchestrator()
        except Exception:
            # Vector DB not available, will default to 0
            pass

        for doc in paginated_docs:
            # Get actual chunk count from vector database
            chunk_count = 0
            if orchestrator and orchestrator.vector_db:
                doc_source = doc.get("source") or doc["title"]
                project_id = doc.get("project_id")
                chunk_count = orchestrator.vector_db.count_chunks_by_source(doc_source, project_id)

            doc_list.append(
                {
                    "id": doc["id"],
                    "title": doc["title"],
                    "source_type": doc["document_type"],
                    "source": doc.get("source"),
                    "created_at": doc["uploaded_at"],
                    "chunk_count": chunk_count,
                }
            )

        return APIResponse(
            success=True,
            status="success",
            message="Documents retrieved",
            data={
                "documents": doc_list,
                "pagination": {
                    "total": total,
                    "limit": limit,
                    "offset": offset,
                    "has_more": offset + limit < total,
                },
            },
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error listing documents: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to list documents: {str(e)}",
        )


@router.get(
    "/all",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="Get all knowledge sources (PDFs, Notes, GitHub repos)",
)
async def get_all_knowledge_sources(
    project_id: str,
    current_user: str = Depends(get_current_user),
    db: ProjectDatabase = Depends(get_database),
) -> APIResponse:
    """
    Get all knowledge sources for a project: PDFs, Notes, and GitHub repositories.

    Args:
        project_id: Project identifier
        current_user: Current authenticated user
        db: Database connection

    Returns:
        APIResponse with categorized knowledge sources and chunk counts
    """
    try:
        # Verify user has access to project using RBAC (viewers and above can read knowledge)
        from socrates_api.auth.project_access import check_project_access
        import asyncio

        # Run async RBAC check synchronously
        asyncio.get_event_loop()
        await check_project_access(project_id, current_user, db, min_role="viewer")

        project = db.load_project(project_id)
        if not project:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"Project '{project_id}' not found",
            )

        orchestrator = None
        try:
            from socrates_api.main import app_state

            orchestrator = app_state.get("orchestrator")
        except Exception:
            pass

        # Collect all knowledge sources
        all_sources = {
            "documents": [],  # PDFs and files
            "notes": [],  # Project notes
            "repositories": [],  # GitHub repos
        }

        # 1. Get uploaded documents (PDFs, etc.)
        try:
            documents = db.get_project_knowledge_documents(project_id)
            for doc in documents:
                chunk_count = 0
                if orchestrator and orchestrator.vector_db:
                    doc_source = doc.get("source") or doc["title"]
                    chunk_count = orchestrator.vector_db.count_chunks_by_source(
                        doc_source, project_id
                    )

                all_sources["documents"].append(
                    {
                        "id": doc["id"],
                        "title": doc["title"],
                        "source_type": doc.get("document_type", "file"),
                        "source": doc.get("source"),
                        "created_at": doc.get("uploaded_at"),
                        "chunk_count": chunk_count,
                        "type": "document",
                    }
                )
        except Exception as e:
            logger.warning(f"Error fetching documents: {e}")

        # 2. Get project notes
        try:
            if hasattr(project, "notes") and project.notes:
                for note in project.notes:
                    chunk_count = 0
                    if orchestrator and orchestrator.vector_db:
                        chunk_count = orchestrator.vector_db.count_chunks_by_source(
                            f"note_{note.note_id}", project_id
                        )

                    all_sources["notes"].append(
                        {
                            "id": note.note_id,
                            "title": note.title,
                            "source_type": "note",
                            "note_type": note.note_type,
                            "content_preview": (
                                note.content[:200] + "..."
                                if len(note.content) > 200
                                else note.content
                            ),
                            "created_at": (
                                note.created_at.isoformat()
                                if hasattr(note.created_at, "isoformat")
                                else str(note.created_at)
                            ),
                            "chunk_count": chunk_count,
                            "type": "note",
                        }
                    )
        except Exception as e:
            logger.warning(f"Error fetching notes: {e}")

        # 3. Get GitHub repositories
        try:
            if hasattr(project, "repository_url") and project.repository_url:
                # Count chunks for README and code files
                readme_chunks = 0
                code_chunks = 0

                if orchestrator and orchestrator.vector_db:
                    # Count README chunks
                    readme_chunks = orchestrator.vector_db.count_chunks_by_source(
                        "README.md", project_id
                    )
                    # Count code file chunks (they all have source_type: github_code)
                    # This is approximate - we can enhance if needed
                    code_chunks = max(
                        0,
                        orchestrator.vector_db.count_chunks_by_source(
                            project.repository_url, project_id
                        ),
                    )

                total_chunks = readme_chunks + code_chunks

                all_sources["repositories"].append(
                    {
                        "id": project.project_id,
                        "title": f"{project.repository_owner}/{project.repository_name}",
                        "source_type": "github",
                        "url": project.repository_url,
                        "owner": project.repository_owner,
                        "name": project.repository_name,
                        "chunk_count": total_chunks,
                        "readme_chunks": readme_chunks,
                        "code_chunks": code_chunks,
                        "type": "repository",
                    }
                )
        except Exception as e:
            logger.warning(f"Error fetching GitHub repo info: {e}")

        return APIResponse(
            success=True,
            status="success",
            message="All knowledge sources retrieved",
            data={
                "project_id": project_id,
                "sources": all_sources,
                "totals": {
                    "documents": len(all_sources["documents"]),
                    "notes": len(all_sources["notes"]),
                    "repositories": len(all_sources["repositories"]),
                    "total_chunks": sum(
                        s.get("chunk_count", 0) for sources in all_sources.values() for s in sources
                    ),
                },
            },
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error getting all knowledge sources: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Error retrieving knowledge sources",
        )


@router.get(
    "/documents/{document_id}",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="Get document details and preview",
)
async def get_document_details(
    document_id: str,
    include_content: bool = False,
    current_user: str = Depends(get_current_user),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Get detailed information about a document including preview and metadata.

    Args:
        document_id: Document identifier
        include_content: Include full document content (default False for preview only)
        current_user: Current authenticated user
        db: Database connection

    Returns:
        Document details with preview and metadata
    """
    try:
        # Load document
        document = db.get_knowledge_document(document_id)
        if not document:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Document not found")

        # Verify ownership
        if document["user_id"] != current_user:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN, detail="Access denied to this document"
            )

        # Prepare response
        content = document.get("content", "")
        preview = content[:500] if content else None
        word_count = len(content.split()) if content else 0

        result = {
            "success": True,
            "status": "success",
            "data": {
                "document": {
                    "id": document["id"],
                    "title": document["title"],
                    "source": document["source"],
                    "document_type": document["document_type"],
                    "uploaded_at": document["uploaded_at"],
                    "word_count": word_count,
                    "preview": preview,
                },
            },
        }

        # Include full content if requested
        if include_content:
            result["data"]["document"]["content"] = content

        return result

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error getting document details: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error retrieving document"
        )


@router.get(
    "/documents/{document_id}/download",
    summary="Download knowledge base document",
    responses={
        200: {"description": "File downloaded successfully"},
        404: {"description": "Document or file not found", "model": ErrorResponse},
        403: {"description": "Access denied", "model": ErrorResponse},
    },
)
async def download_document(
    document_id: str,
    current_user: str = Depends(get_current_user),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Download an uploaded document from the knowledge base.

    Args:
        document_id: Document identifier
        current_user: Current authenticated user
        db: Database connection

    Returns:
        File download
    """
    try:
        # Load document
        document = db.get_knowledge_document(document_id)
        if not document:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Document not found")

        # Verify ownership
        if document["user_id"] != current_user:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN, detail="Access denied to this document"
            )

        # Get file path
        file_path = document.get("file_path")
        if not file_path:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="File not available for download"
            )

        # Verify file exists
        file_obj = Path(file_path)
        if not file_obj.exists():
            logger.error(f"File not found on disk: {file_path}")
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="File not found")

        # Return file for download
        return FileResponse(
            path=file_obj,
            filename=file_obj.name,
            media_type="application/octet-stream",
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error downloading document {document_id}: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error downloading file"
        )


@router.post(
    "/import/file",
    response_model=APIResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Import file to knowledge base",
    responses={
        201: {"description": "File imported successfully"},
        400: {"description": "Invalid file", "model": ErrorResponse},
        500: {"description": "Server error during import", "model": ErrorResponse},
    },
)
async def import_file(
    file: UploadFile = File(...),
    project_id: Optional[str] = Form(None),
    current_user: str = Depends(get_current_user),
    orchestrator=Depends(_get_orchestrator),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Import a file to the knowledge base.

    Args:
        file: File to import
        project_id: Optional project ID to associate document
        current_user: Current authenticated user
        orchestrator: Orchestrator instance
        db: Database connection

    Returns:
        SuccessResponse with import details
    """
    try:
        if not file.filename:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="File name is required",
            )

        logger.info(f"Importing file: {file.filename} for user {current_user}")

        # Verify project access if provided
        if project_id:
            project = db.load_project(project_id)
            if not project:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND, detail="Project not found"
                )
            # Check RBAC for write operations (requires editor or owner role)
            # Import here to avoid circular imports
            from socrates_api.auth.project_access import check_project_access as rbac_check

            await rbac_check(project_id, current_user, db, min_role="editor")

        # Create document ID first
        doc_id = str(uuid.uuid4())

        # Save uploaded file to persistent storage
        knowledge_dir = Path.home() / ".socrates" / "knowledge_base" / current_user / doc_id
        knowledge_dir.mkdir(exist_ok=True, parents=True)

        # Preserve original filename with document ID
        stored_file = knowledge_dir / file.filename

        # Write file content
        content = await file.read()
        file_size = len(content)

        # CHECK STORAGE QUOTA BEFORE SAVING
        user_object = db.load_user(current_user)
        if user_object:
            from socratic_system.subscription.storage import StorageQuotaManager

            can_upload, error_msg = StorageQuotaManager.can_upload_document(
                user_object, db, file_size, testing_mode=False
            )
            if not can_upload:
                logger.warning(f"Storage quota exceeded for user {current_user}: {error_msg}")
                raise HTTPException(
                    status_code=status.HTTP_413_PAYLOAD_TOO_LARGE,
                    detail=error_msg,
                )

        stored_file.write_bytes(content)

        logger.info(f"Saved knowledge base file: {stored_file}")

        # Also save to temp for processing
        temp_dir = Path(tempfile.gettempdir()) / "socrates_uploads"
        temp_dir.mkdir(exist_ok=True, parents=True)
        temp_file = temp_dir / f"{uuid.uuid4()}_{file.filename}"
        temp_file.write_bytes(content)

        logger.debug(f"Saved temp file: {temp_file}")

        try:
            # Process via DocumentProcessorAgent
            result = await orchestrator.agent_bus.send_request(
                "document_processor",
                {
                    "action": "import_file",
                    "file_path": str(temp_file),
                    "original_filename": file.filename,
                    "project_id": project_id,
                },
            )

            logger.debug(f"DocumentProcessor result: {result}")

            # Extract content from processor result for preview
            extracted_content = ""
            if result.get("status") == "success":
                # Get file content for preview (store first 5000 chars)
                try:
                    # Use already-read content instead of reading again
                    file_content = content
                    # Try to extract text content based on file type
                    if file.filename.endswith(".pdf"):
                        try:
                            from pypdf import PdfReader
                            import io

                            pdf_reader = PdfReader(io.BytesIO(file_content))
                            for page in pdf_reader.pages:
                                extracted_content += page.extract_text() + "\n"
                        except Exception:
                            extracted_content = "[PDF content not extractable]"
                    else:
                        # For text files, try to decode
                        try:
                            extracted_content = file_content.decode("utf-8", errors="ignore")
                        except Exception:
                            extracted_content = "[File content not readable]"
                except Exception:
                    extracted_content = "[Could not read file for preview]"

            # Limit content preview to first 5000 characters
            content_preview = extracted_content[:5000] if extracted_content else ""

            # Save metadata to database with file path
            db.save_knowledge_document(
                user_id=current_user,
                project_id=project_id,
                doc_id=doc_id,
                title=file.filename,
                content=content_preview,
                source=file.filename,
                document_type="file",
                file_path=str(stored_file),
                file_size=file_size,
            )

            logger.info(
                f"File imported successfully: {file.filename} ({len(content_preview)} chars preview, {file_size} bytes)"
            )

            # Emit DOCUMENT_IMPORTED event to trigger knowledge analysis and question regeneration
            try:
                from socratic_system.events import EventType

                await orchestrator.event_emitter.emit_async(
                    EventType.DOCUMENT_IMPORTED,
                    {
                        "project_id": project_id,
                        "file_name": file.filename,
                        "source_type": "file",
                        "words_extracted": result.get("words_extracted", 0),
                        "chunks_created": result.get("chunks_added", 0),
                        "user_id": current_user,
                    },
                )
                logger.debug(f"Emitted DOCUMENT_IMPORTED event for {file.filename}")
            except Exception as e:
                logger.warning(f"Failed to emit DOCUMENT_IMPORTED event: {e}")
                # Don't fail the import if event emission fails

            return APIResponse(
                success=True,
                status="success",
                message=f"File '{file.filename}' imported successfully",
                data={
                    "filename": file.filename,
                    "size": len(content),
                    "document_id": doc_id,
                    "chunks_created": result.get("chunks_created", 0),
                    "chunks_stored": result.get("entries_added", 0),
                    "words_extracted": result.get("words_extracted", 0),
                    "content_preview": content_preview[:500] if content_preview else "",
                },
            )

        finally:
            # Clean up temp file
            try:
                temp_file.unlink()
            except Exception as e:
                logger.warning(f"Failed to delete temp file {temp_file}: {e}")

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error importing file: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to import file: {str(e)}",
        )


@router.post(
    "/import/url",
    response_model=APIResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Import URL to knowledge base",
    responses={
        201: {"description": "URL imported successfully"},
        400: {"description": "Invalid URL", "model": ErrorResponse},
        500: {"description": "Server error during import", "model": ErrorResponse},
    },
)
async def import_url(
    body: dict = Body(...),
    current_user: str = Depends(get_current_user),
    orchestrator=Depends(_get_orchestrator),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Import content from URL to knowledge base.

    Args:
        body: JSON body with url and optional projectId
        current_user: Current authenticated user
        orchestrator: Orchestrator instance
        db: Database connection

    Returns:
        SuccessResponse with import details
    """
    try:
        url = body.get("url")
        project_id = body.get("projectId")

        if not url:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="URL is required",
            )

        logger.info(f"Importing from URL: {url} for user {current_user}")

        # Verify project access if provided
        if project_id:
            project = db.load_project(project_id)
            if not project:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND, detail="Project not found"
                )
            # Check RBAC for write operations (requires editor or owner role)
            # Import here to avoid circular imports
            from socrates_api.auth.project_access import check_project_access as rbac_check

            await rbac_check(project_id, current_user, db, min_role="editor")

        # Create document ID first (for source consistency)
        doc_id = str(uuid.uuid4())

        # Process via DocumentProcessorAgent
        result = await orchestrator.agent_bus.send_request(
            "document_processor",
            {
                "action": "import_url",
                "url": url,
                "project_id": project_id,
                "document_id": doc_id,  # Pass doc_id for source name consistency
            },
        )

        logger.debug(f"DocumentProcessor result: {result}")

        # Save metadata
        db.save_knowledge_document(
            user_id=current_user,
            project_id=project_id,
            doc_id=doc_id,
            title=url,
            source=doc_id,  # Use same doc_id as source for vector DB matching
            document_type="url",
        )

        logger.info(f"URL imported successfully: {url}")

        # Emit DOCUMENT_IMPORTED event to trigger knowledge analysis and question regeneration
        try:
            from socratic_system.events import EventType

            await orchestrator.event_emitter.emit_async(
                EventType.DOCUMENT_IMPORTED,
                {
                    "project_id": project_id,
                    "file_name": url,
                    "source_type": "url",
                    "words_extracted": result.get("words_extracted", 0),
                    "chunks_created": result.get("chunks_added", 0),
                    "user_id": current_user,
                },
            )
            logger.debug(f"Emitted DOCUMENT_IMPORTED event for {url}")
        except Exception as e:
            logger.warning(f"Failed to emit DOCUMENT_IMPORTED event: {e}")
            # Don't fail the import if event emission fails

        return APIResponse(
            success=True,
            status="success",
            message=f"Content from '{url}' imported successfully",
            data={
                "url": url,
                "chunks": result.get("chunks_added", 0),
                "entries": result.get("entries_added", 0),
            },
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error importing URL: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to import URL: {str(e)}",
        )


@router.post(
    "/import/text",
    response_model=APIResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Import pasted text to knowledge base",
    responses={
        201: {"description": "Text imported successfully"},
        400: {"description": "Invalid text", "model": ErrorResponse},
        500: {"description": "Server error during import", "model": ErrorResponse},
    },
)
async def import_text(
    body: dict = Body(...),
    current_user: str = Depends(get_current_user),
    orchestrator=Depends(_get_orchestrator),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Import pasted text to knowledge base.

    Args:
        body: JSON body with title, content, and optional projectId
        current_user: Current authenticated user
        orchestrator: Orchestrator instance
        db: Database connection

    Returns:
        SuccessResponse with import details
    """
    try:
        title = body.get("title")
        content = body.get("content")
        project_id = body.get("projectId")

        if not content:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Content is required",
            )

        logger.info(f"Importing text document: {title} for user {current_user}")

        # Verify project access if provided
        if project_id:
            project = db.load_project(project_id)
            if not project:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND, detail="Project not found"
                )
            # Check RBAC for write operations (requires editor or owner role)
            # Import here to avoid circular imports
            from socrates_api.auth.project_access import check_project_access as rbac_check

            await rbac_check(project_id, current_user, db, min_role="editor")

        # Create document ID first (for source consistency)
        doc_id = str(uuid.uuid4())

        # CHECK STORAGE QUOTA BEFORE IMPORTING TEXT
        content_size_bytes = len(content.encode("utf-8"))
        user_object = db.load_user(current_user)
        if user_object:
            from socratic_system.subscription.storage import StorageQuotaManager

            can_upload, error_msg = StorageQuotaManager.can_upload_document(
                user_object, db, content_size_bytes, testing_mode=False
            )
            if not can_upload:
                logger.warning(f"Storage quota exceeded for user {current_user}: {error_msg}")
                raise HTTPException(
                    status_code=status.HTTP_413_PAYLOAD_TOO_LARGE,
                    detail=error_msg,
                )

        # Process via DocumentProcessorAgent
        result = await orchestrator.agent_bus.send_request(
            "document_processor",
            {
                "action": "import_text",
                "content": content,
                "title": title or "Untitled",
                "project_id": project_id,
                "document_id": doc_id,  # Pass doc_id for source name consistency
            },
        )

        logger.debug(f"DocumentProcessor result: {result}")

        # Save metadata
        db.save_knowledge_document(
            user_id=current_user,
            project_id=project_id,
            doc_id=doc_id,
            title=title or "Untitled",
            content=content[:1000],
            source=doc_id,  # Use same doc_id as source for vector DB matching
            document_type="text",
        )

        logger.info(f"Text document imported successfully: {title}")

        # Emit DOCUMENT_IMPORTED event to trigger knowledge analysis and question regeneration
        word_count = len(content.split())
        try:
            from socratic_system.events import EventType

            await orchestrator.event_emitter.emit_async(
                EventType.DOCUMENT_IMPORTED,
                {
                    "project_id": project_id,
                    "file_name": title or "Untitled",
                    "source_type": "text",
                    "words_extracted": word_count,
                    "chunks_created": result.get("chunks_added", 0),
                    "user_id": current_user,
                },
            )
            logger.debug(f"Emitted DOCUMENT_IMPORTED event for {title}")
        except Exception as e:
            logger.warning(f"Failed to emit DOCUMENT_IMPORTED event: {e}")
            # Don't fail the import if event emission fails

        return APIResponse(
            success=True,
            status="success",
            message=f"Text document '{title or 'Untitled'}' imported successfully",
            data={
                "title": title,
                "word_count": word_count,
                "chunks": result.get("chunks_added", 0),
                "entries": result.get("entries_added", 0),
            },
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error importing text: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to import text: {str(e)}",
        )


@router.get(
    "/search",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="Search knowledge base",
    responses={
        200: {"description": "Search results"},
        400: {"description": "Invalid search query", "model": ErrorResponse},
    },
)
async def search_knowledge(
    q: Optional[str] = None,
    query: Optional[str] = None,
    project_id: Optional[str] = None,
    top_k: int = 10,
    current_user: str = Depends(get_current_user),
    orchestrator=Depends(_get_orchestrator),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Search knowledge base using semantic search.

    Args:
        q: Search query (alternative parameter name)
        query: Search query
        project_id: Optional project ID to filter
        top_k: Number of results to return
        current_user: Current authenticated user
        orchestrator: Orchestrator instance
        db: Database connection

    Returns:
        SuccessResponse with search results
    """
    try:
        search_query = q or query
        if not search_query:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Search query is required",
            )

        logger.info(f"Searching knowledge base: {search_query} for user {current_user}")

        # Verify project access if provided
        if project_id:
            project = db.load_project(project_id)
            if not project:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND, detail="Project not found"
                )
            # Check RBAC for write operations (requires editor or owner role)
            # Import here to avoid circular imports
            from socrates_api.auth.project_access import check_project_access as rbac_check

            await rbac_check(project_id, current_user, db, min_role="editor")

        # Use VectorDatabase via orchestrator
        vector_db = orchestrator.vector_db
        if not vector_db:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Vector database not initialized",
            )

        # Perform semantic search
        results = vector_db.search_similar(query=search_query, top_k=top_k, project_id=project_id)

        logger.debug(f"Found {len(results)} search results")

        # Transform results to frontend format
        search_results = []
        for result in results:
            metadata = result.get("metadata", {})
            search_results.append(
                {
                    "document_id": metadata.get("source", "unknown"),
                    "title": metadata.get("source", "Unknown"),
                    "excerpt": result.get("content", "")[:200],
                    "relevance_score": max(0, min(1, 1 - result.get("distance", 1))),
                    "source": metadata.get("source_type", "unknown"),
                }
            )

        logger.info(f"Search completed: found {len(search_results)} results")

        return APIResponse(
            success=True,
            status="success",
            message=f"Search completed for '{search_query}'",
            data={"query": search_query, "results": search_results, "total": len(search_results)},
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error searching knowledge base: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to search: {str(e)}",
        )


@router.delete(
    "/documents/{document_id}",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="Delete document",
    responses={
        200: {"description": "Document deleted"},
        404: {"description": "Document not found", "model": ErrorResponse},
    },
)
async def delete_document(
    document_id: str,
    current_user: str = Depends(get_current_user),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Delete a document from knowledge base.

    Args:
        document_id: ID of document to delete
        current_user: Current authenticated user
        db: Database connection

    Returns:
        SuccessResponse confirming deletion
    """
    try:
        logger.info(f"Deleting document: {document_id} by user {current_user}")

        # Get document to verify ownership
        doc = db.get_knowledge_document(document_id)
        if not doc:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"Document not found: {document_id}",
            )

        if doc["user_id"] != current_user:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Access denied to this document",
            )

        # Delete from database
        success = db.delete_knowledge_document(document_id)

        if not success:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Failed to delete document",
            )

        logger.info(f"Document deleted successfully: {document_id}")

        return APIResponse(
            success=True,
            status="success",
            message="Document deleted successfully",
            data={"document_id": document_id},
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting document: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to delete document: {str(e)}",
        )


@router.post(
    "/documents/bulk-delete",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="Bulk delete documents",
)
async def bulk_delete_documents(
    document_ids: list = Body(..., description="List of document IDs to delete"),
    current_user: str = Depends(get_current_user),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Delete multiple documents in one operation.

    Args:
        document_ids: List of document IDs to delete
        current_user: Current authenticated user
        db: Database connection

    Returns:
        Summary of deleted and failed documents
    """
    try:
        deleted = []
        failed = []

        for doc_id in document_ids:
            try:
                # Verify ownership
                doc = db.get_knowledge_document(doc_id)
                if doc and doc["user_id"] == current_user:
                    success = db.delete_knowledge_document(doc_id)
                    if success:
                        deleted.append(doc_id)
                    else:
                        failed.append({"id": doc_id, "reason": "Delete failed"})
                else:
                    failed.append({"id": doc_id, "reason": "Not found or access denied"})
            except Exception as e:
                failed.append({"id": doc_id, "reason": str(e)})

        logger.info(f"Bulk delete: {len(deleted)} deleted, {len(failed)} failed")

        return APIResponse(
            success=True,
            status="success",
            message=f"Bulk delete completed: {len(deleted)} deleted, {len(failed)} failed",
            data={
                "deleted": deleted,
                "failed": failed,
                "summary": {
                    "total_requested": len(document_ids),
                    "deleted_count": len(deleted),
                    "failed_count": len(failed),
                },
            },
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error in bulk delete: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error performing bulk delete"
        )


@router.post(
    "/documents/bulk-import",
    response_model=APIResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Bulk import documents",
)
async def bulk_import_documents(
    files: list = File(..., description="Files to import"),
    project_id: Optional[str] = Form(None),
    current_user: str = Depends(get_current_user),
    orchestrator=Depends(_get_orchestrator),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Import multiple files in one operation.

    Args:
        files: List of files to import
        project_id: Optional project ID to associate documents with
        current_user: Current authenticated user
        orchestrator: Agent orchestrator for processing
        db: Database connection

    Returns:
        Summary of imported and failed documents
    """
    try:
        # Verify project access if specified
        if project_id:
            project = db.load_project(project_id)
            if not project:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND, detail="Project not found"
                )
            # Check RBAC for write operations (requires editor or owner role)
            # Import here to avoid circular imports
            from socrates_api.auth.project_access import check_project_access as rbac_check

            await rbac_check(project_id, current_user, db, min_role="editor")

        results = []
        for file in files:
            try:
                if not file.filename:
                    results.append({"file": "unknown", "status": "failed", "reason": "No filename"})
                    continue

                # Save uploaded file temporarily
                with tempfile.NamedTemporaryFile(delete=False) as temp_file:
                    content = await file.read()
                    temp_file.write(content)
                    temp_path = temp_file.name

                try:
                    # Process file
                    doc_id = f"doc_{uuid.uuid4().hex[:12]}"
                    result = await orchestrator.agent_bus.send_request(
                        "document_processor",
                        {
                            "action": "import_file",
                            "file_path": temp_path,
                            "file_name": file.filename,
                            "user_id": current_user,
                            "project_id": project_id,
                        },
                    )

                    if result.get("status") == "success":
                        # Save document metadata
                        db.save_knowledge_document(
                            user_id=current_user,
                            project_id=project_id,
                            doc_id=doc_id,
                            title=file.filename,
                            content=result.get("content", ""),
                            source=file.filename,
                            document_type="file",
                        )
                        results.append(
                            {"file": file.filename, "status": "success", "document_id": doc_id}
                        )
                    else:
                        results.append(
                            {
                                "file": file.filename,
                                "status": "failed",
                                "reason": result.get("message", "Processing failed"),
                            }
                        )
                finally:
                    # Clean up temp file
                    try:
                        Path(temp_path).unlink()
                    except OSError as e:
                        logger.warning(f"Failed to clean up temporary file {temp_path}: {str(e)}")

            except Exception as e:
                results.append(
                    {
                        "file": file.filename if hasattr(file, "filename") else "unknown",
                        "status": "failed",
                        "reason": str(e),
                    }
                )

        success_count = len([r for r in results if r["status"] == "success"])
        failed_count = len([r for r in results if r["status"] == "failed"])

        logger.info(f"Bulk import: {success_count} imported, {failed_count} failed")

        return APIResponse(
            success=True,
            status="success",
            message=f"Bulk import completed: {success_count} imported, {failed_count} failed",
            data=BulkImportData(
                imported_count=success_count,
                failed_count=failed_count,
                details=results,
            ).model_dump(),
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error in bulk import: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error performing bulk import"
        )


@router.get(
    "/documents/{document_id}/analytics",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="Get document analytics",
)
async def get_document_analytics(
    document_id: str,
    current_user: str = Depends(get_current_user),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Get analytics and usage statistics for a document.

    Args:
        document_id: Document identifier
        current_user: Current authenticated user
        db: Database connection

    Returns:
        Analytics data for the document
    """
    try:
        # Load document
        document = db.get_knowledge_document(document_id)
        if not document:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Document not found")

        # Verify ownership
        if document["user_id"] != current_user:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN, detail="Access denied to this document"
            )

        # Calculate analytics
        content = document.get("content", "")
        word_count = len(content.split()) if content else 0
        char_count = len(content) if content else 0

        analytics = {
            "success": True,
            "status": "success",
            "data": {
                "document_id": document_id,
                "analytics": {
                    "document_title": document["title"],
                    "document_type": document["document_type"],
                    "uploaded_at": document["uploaded_at"],
                    "word_count": word_count,
                    "char_count": char_count,
                    "estimated_reading_time_minutes": max(1, word_count // 200),
                    "source": document["source"],
                },
            },
        }

        return analytics

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error getting document analytics: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error retrieving analytics"
        )


@router.post(
    "/entries",
    response_model=APIResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Add knowledge entry",
    responses={
        201: {"description": "Entry added"},
        400: {"description": "Invalid entry", "model": ErrorResponse},
    },
)
async def add_knowledge_entry(
    body: dict = Body(...),
    current_user: str = Depends(get_current_user),
    orchestrator=Depends(_get_orchestrator),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Add a new knowledge entry.

    Args:
        body: JSON body with content, category, and optional projectId
        current_user: Current authenticated user
        orchestrator: Orchestrator instance
        db: Database connection

    Returns:
        SuccessResponse with entry details
    """
    try:
        content = body.get("content")
        category = body.get("category")
        project_id = body.get("projectId")

        if not content:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Content is required",
            )

        logger.info(f"Adding knowledge entry in category: {category} for user {current_user}")

        # Verify project access if provided
        if project_id:
            project = db.load_project(project_id)
            if not project:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND, detail="Project not found"
                )
            # Check RBAC for write operations (requires editor or owner role)
            # Import here to avoid circular imports
            from socrates_api.auth.project_access import check_project_access as rbac_check

            await rbac_check(project_id, current_user, db, min_role="editor")

        # Process as text import with category metadata
        result = await orchestrator.agent_bus.send_request(
            "document_processor",
            {
                "action": "import_text",
                "content": content,
                "title": f"{category} entry",
                "project_id": project_id,
            },
        )

        logger.debug(f"DocumentProcessor result: {result}")

        # Save metadata
        entry_id = str(uuid.uuid4())
        db.save_knowledge_document(
            user_id=current_user,
            project_id=project_id,
            doc_id=entry_id,
            title=f"{category} entry",
            content=content[:1000],
            source="manual_entry",
            document_type=category,
        )

        logger.info(f"Knowledge entry added successfully: {category}")

        return APIResponse(
            success=True,
            status="success",
            message="Knowledge entry added successfully",
            data={
                "category": category,
                "content_length": len(content),
            },
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error adding knowledge entry: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to add entry: {str(e)}",
        )


# ============================================================================
# DEBUG ENDPOINTS (for troubleshooting)
# ============================================================================


@router.get(
    "/debug/vector-db-chunks",
    response_model=APIResponse,
    status_code=status.HTTP_200_OK,
    summary="Debug: List all chunks in vector database",
)
async def debug_get_vector_db_chunks(
    orchestrator=Depends(_get_orchestrator),
    db: ProjectDatabase = Depends(get_database),
):
    """
    Debug endpoint to inspect what's actually stored in the vector database.
    This helps diagnose why chunk_count might be showing 0.

    Returns:
        List of all chunks with their metadata
    """
    try:
        if not orchestrator or not orchestrator.vector_db:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Vector database not available",
            )

        chunks = orchestrator.vector_db.get_all_chunks_debug()

        return APIResponse(
            success=True,
            status="success",
            data={
                "total_chunks": len(chunks),
                "chunks": chunks,
            },
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error getting vector db debug info: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to get debug info: {str(e)}",
        )
