from __future__ import annotations

import asyncio
import logging
from typing import Any

from fastapi import APIRouter, Depends, HTTPException

from app.api.dependencies import get_orchestrator
from app.modules.auth.presentation.auth import get_current_user, require_role
from app.models.schemas import (
    KnowledgeIngestRequest,
    KnowledgeIngestResponse,
    KnowledgeSearchRequest,
    KnowledgeSearchResponse,
    KnowledgeSearchResult,
    MemoryIngestResponse,
    ProjectMemoryIngestRequest,
    ReviewMemoryIngestRequest,
)

logger = logging.getLogger("dscons.api.knowledge_agents.knowledge")
router = APIRouter()


@router.post("/v1/knowledge/ingest", response_model=KnowledgeIngestResponse)
def ingest_knowledge(
    payload: KnowledgeIngestRequest,
    current_user: dict[str, Any] = Depends(require_role(["superadmin", "director"])),
) -> KnowledgeIngestResponse:
    """Ingest knowledge chunks into the shared RAG store."""
    orchestrator = get_orchestrator()
    ingested_count = asyncio.run(
        orchestrator.ingest_knowledge(
            task_type=payload.task_type,
            chunks=[chunk.model_dump() for chunk in payload.chunks],
            default_metadata=payload.default_metadata,
        )
    )
    return KnowledgeIngestResponse(status="accepted", ingested_count=ingested_count)


@router.post("/v1/knowledge/search", response_model=KnowledgeSearchResponse)
def search_knowledge(
    payload: KnowledgeSearchRequest,
    current_user: dict[str, Any] = Depends(get_current_user),
) -> KnowledgeSearchResponse:
    """Search knowledge chunks with optional metadata filters."""
    orchestrator = get_orchestrator()
    results = asyncio.run(
        orchestrator.search_knowledge(
            task_type=payload.task_type,
            query=payload.query,
            top_k=payload.top_k,
            retrieval_filters=payload.filters.model_dump(exclude_none=True)
            if payload.filters
            else None,
        )
    )
    return KnowledgeSearchResponse(
        results=[KnowledgeSearchResult(**item) for item in results]
    )


@router.post("/v1/knowledge/review-memory/ingest", response_model=MemoryIngestResponse)
def ingest_review_memory(
    payload: ReviewMemoryIngestRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm"])
    ),
) -> MemoryIngestResponse:
    """Convert one dossier review session into RAG memory chunks and ingest them."""
    orchestrator = get_orchestrator()
    try:
        ingested_count = asyncio.run(
            orchestrator.ingest_review_memory(
                review_id=payload.review_id,
                task_type=payload.task_type,
                default_metadata=payload.default_metadata,
            )
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

    return MemoryIngestResponse(
        status="accepted",
        ingested_count=ingested_count,
        chunk_count=ingested_count,
    )


@router.post("/v1/knowledge/project-memory/ingest", response_model=MemoryIngestResponse)
def ingest_project_memory(
    payload: ProjectMemoryIngestRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "pm"])
    ),
) -> MemoryIngestResponse:
    """Convert project operational events into RAG memory chunks and ingest them."""
    orchestrator = get_orchestrator()
    try:
        ingested_count = asyncio.run(
            orchestrator.ingest_project_memory(
                task_type=payload.task_type,
                events=[event.model_dump() for event in payload.events],
                default_metadata=payload.default_metadata,
            )
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

    return MemoryIngestResponse(
        status="accepted",
        ingested_count=ingested_count,
        chunk_count=ingested_count,
    )
