from typing import Any

from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session

from app.api.deps import get_db
from app.api.permissions import require_read, require_update
from app.core.exceptions import KnowledgeBaseNotFoundError
from app.core.i18n import get_translator
from app.models import KnowledgeBase, User
from app.services.rag.langchain_document_processor import get_document_processor

from common_logging import get_logger

logger = get_logger(__name__)

router = APIRouter(tags=["knowledge-pipeline"])


class PipelineConfig(BaseModel):
    chunk_strategy: str = Field(default="recursive", description="分块策略")
    chunk_size: int = Field(default=1000, ge=100, le=10000, description="块大小")
    chunk_overlap: int = Field(default=200, ge=0, le=1000, description="重叠大小")
    preprocessing_rules: dict[str, Any] | None = Field(default=None, description="预处理规则")
    vectorization_config: dict[str, Any] | None = Field(default=None, description="向量化配置")


class PreviewRequest(BaseModel):
    text: str = Field(..., description="示例文本")
    chunk_strategy: str = Field(default="recursive", description="分块策略")
    chunk_size: int = Field(default=1000, ge=100, le=10000, description="块大小")
    chunk_overlap: int = Field(default=200, ge=0, le=1000, description="重叠大小")


@router.get("/{base_id}/pipeline-config")
def get_pipeline_config(
    base_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_read("knowledge_bases")),
):
    get_translator(request)
    kb = db.query(KnowledgeBase).filter(KnowledgeBase.id == base_id).first()
    if not kb:
        raise KnowledgeBaseNotFoundError(base_id)
    return {
        "chunk_strategy": "recursive",
        "chunk_size": 1000,
        "chunk_overlap": 200,
        "preprocessing_rules": {"remove_extra_whitespace": True, "remove_special_chars": False},
        "vectorization_config": {"auto_vectorize": True, "batch_size": 10},
    }


@router.put("/{base_id}/pipeline-config")
def update_pipeline_config(
    base_id: int,
    config: PipelineConfig,
    request: Request,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_update("knowledge_bases")),
):
    t = get_translator(request)
    kb = db.query(KnowledgeBase).filter(KnowledgeBase.id == base_id).first()
    if not kb:
        raise KnowledgeBaseNotFoundError(base_id)
    logger.bind(pipeline_id=base_id).info("pipeline config updated")
    return {
        "success": True,
        "message": t.t("pipeline.config_updated"),
        "config": config.model_dump(),
    }


@router.post("/{base_id}/pipeline-preview")
def preview_pipeline(
    base_id: int,
    preview_request: PreviewRequest,
    request: Request,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_read("knowledge_bases")),
):
    t = get_translator(request)
    kb = db.query(KnowledgeBase).filter(KnowledgeBase.id == base_id).first()
    if not kb:
        raise KnowledgeBaseNotFoundError(base_id)
    try:
        processor = get_document_processor()
        result = processor.preview_chunking(
            text=preview_request.text,
            strategy=preview_request.chunk_strategy,
            chunk_size=preview_request.chunk_size,
            chunk_overlap=preview_request.chunk_overlap,
        )
        return result
    except Exception as e:
        logger.bind(pipeline_id=base_id).warning("pipeline preview failed: {error}", error=str(e))
        raise HTTPException(status_code=500, detail=f"{t.t('pipeline.preview_failed')}: {str(e)}") from None


@router.get("/chunking-strategies")
def get_chunking_strategies(
    request: Request, current_user: User = Depends(require_read("knowledge_bases"))
):
    return {
        "strategies": [
            {
                "id": "recursive",
                "name": "递归字符分割",
                "description": "根据多个分隔符递归分割文本，适合大多数场景",
                "default_chunk_size": 1000,
                "default_overlap": 200,
            },
            {
                "id": "character",
                "name": "字符分割",
                "description": "按固定字符数分割，简单直接",
                "default_chunk_size": 1000,
                "default_overlap": 200,
            },
            {
                "id": "token",
                "name": "Token分割",
                "description": "按Token数量分割，适合控制API调用成本",
                "default_chunk_size": 500,
                "default_overlap": 50,
            },
        ]
    }
