from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.database import get_db
from app.core.dependencies import get_current_admin
from app.core.responses import api_success
from app.models.admin import Admin
from app.models.ai_config import ModelConfig, Prompt, SystemConfig
from app.models.knowledge import Knowledge
from app.schemas.admin import (
    AgentDebugRequest,
    EnableModelRequest,
    ModelSaveRequest,
    PromptSaveRequest,
    SystemConfigSaveRequest,
)
from app.services.admin_service import OperationLogService
from app.services.feishu_service import FeishuKnowledgeService
from app.services.knowledge_service import KnowledgeScope
from app.services.model_service import ModelClientService
from app.services.rag_service import RagResult

router = APIRouter()

DEFAULT_PROMPT = "你是大本营答疑助手。你只能基于提供的知识片段回答，不能编造。"


@router.get("/prompt")
def get_prompt(db: Session = Depends(get_db), current_admin: Admin = Depends(get_current_admin)) -> dict:
    prompt = db.scalar(select(Prompt).order_by(Prompt.updated_at.desc(), Prompt.id.desc()).limit(1))
    return api_success({"promptContent": prompt.prompt_content if prompt else DEFAULT_PROMPT})


@router.put("/prompt")
def save_prompt(
    payload: PromptSaveRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    prompt = Prompt(prompt_content=payload.promptContent, updated_by=current_admin.id)
    db.add(prompt)
    db.flush()
    OperationLogService.write(db, admin_id=current_admin.id, module="prompt", action="save", target_id=prompt.id)
    db.commit()
    return api_success({"promptContent": prompt.prompt_content})


@router.post("/prompt/reset")
def reset_prompt(db: Session = Depends(get_db), current_admin: Admin = Depends(get_current_admin)) -> dict:
    prompt = Prompt(prompt_content=DEFAULT_PROMPT, updated_by=current_admin.id)
    db.add(prompt)
    db.flush()
    OperationLogService.write(db, admin_id=current_admin.id, module="prompt", action="reset", target_id=prompt.id)
    db.commit()
    return api_success({"promptContent": prompt.prompt_content})


@router.post("/agent/debug")
def debug_agent(
    payload: AgentDebugRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    model = db.get(ModelConfig, payload.modelId)
    if model is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="模型不存在")

    scopes = _agent_knowledge_scopes(db, payload.knowledgeIds)
    chunks = FeishuKnowledgeService.retrieve(payload.question, scopes, db)
    prompt = _build_agent_debug_prompt(payload.promptContent, payload.question, chunks)
    rag_result = RagResult(question=payload.question, knowledge_scopes=scopes, chunks=chunks, prompt=prompt)
    result = ModelClientService.debug_model(
        model,
        rag_result,
        {
            "temperature": payload.temperature,
            "top_p": payload.topP,
            "top_k": payload.topK,
            "presence_penalty": payload.presencePenalty,
            "frequency_penalty": payload.frequencyPenalty,
            "max_token": payload.maxToken,
        },
    )
    OperationLogService.write(db, admin_id=current_admin.id, module="agent", action="debug", target_id=model.id)
    db.commit()
    return api_success(result)


@router.get("/model/list")
def list_models(db: Session = Depends(get_db), current_admin: Admin = Depends(get_current_admin)) -> dict:
    models = db.scalars(select(ModelConfig).order_by(ModelConfig.id.desc())).all()
    return api_success([_model_dict(model) for model in models])


@router.post("/model")
def create_model(
    payload: ModelSaveRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    if not payload.apiKey:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="API Key 不能为空")
    model = ModelConfig(
        provider=payload.provider,
        display_name=payload.displayName,
        api_type=payload.apiType,
        model_name=payload.modelName,
        base_url=payload.baseUrl,
        api_url=payload.apiUrl,
        api_key=payload.apiKey,
        auth_type=payload.authType,
        api_version=payload.apiVersion,
        temperature=payload.temperature,
        top_p=payload.topP,
        top_k=payload.topK,
        presence_penalty=payload.presencePenalty,
        frequency_penalty=payload.frequencyPenalty,
        max_token=payload.maxToken,
        context_window=payload.contextWindow,
        stream_enabled=payload.streamEnabled,
        response_format=payload.responseFormat,
        extra_params=payload.extraParams,
        remark=payload.remark,
        timeout_second=payload.timeoutSecond,
        enabled=0,
    )
    db.add(model)
    db.flush()
    OperationLogService.write(db, admin_id=current_admin.id, module="model", action="create", target_id=model.id)
    db.commit()
    db.refresh(model)
    return api_success(_model_dict(model))


@router.put("/model/{model_id}")
def update_model(
    model_id: int,
    payload: ModelSaveRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    model = db.get(ModelConfig, model_id)
    if model is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="模型不存在")

    model.provider = payload.provider
    model.display_name = payload.displayName
    model.api_type = payload.apiType
    model.model_name = payload.modelName
    model.base_url = payload.baseUrl
    model.api_url = payload.apiUrl
    if payload.apiKey:
        model.api_key = payload.apiKey
    model.auth_type = payload.authType
    model.api_version = payload.apiVersion
    model.temperature = payload.temperature
    model.top_p = payload.topP
    model.top_k = payload.topK
    model.presence_penalty = payload.presencePenalty
    model.frequency_penalty = payload.frequencyPenalty
    model.max_token = payload.maxToken
    model.context_window = payload.contextWindow
    model.stream_enabled = payload.streamEnabled
    model.response_format = payload.responseFormat
    model.extra_params = payload.extraParams
    model.remark = payload.remark
    model.timeout_second = payload.timeoutSecond
    db.add(model)
    OperationLogService.write(db, admin_id=current_admin.id, module="model", action="update", target_id=model.id)
    db.commit()
    db.refresh(model)
    return api_success(_model_dict(model))


@router.post("/model/enable")
def enable_model(
    payload: EnableModelRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    target = db.get(ModelConfig, payload.modelId)
    if target is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="模型不存在")
    for model in db.scalars(select(ModelConfig)).all():
        model.enabled = 1 if model.id == target.id else 0
        db.add(model)
    OperationLogService.write(db, admin_id=current_admin.id, module="model", action="enable", target_id=target.id)
    db.commit()
    return api_success()


@router.delete("/model/{model_id}")
def delete_model(
    model_id: int,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    model = db.get(ModelConfig, model_id)
    if model is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="模型不存在")
    db.delete(model)
    OperationLogService.write(db, admin_id=current_admin.id, module="model", action="delete", target_id=model.id)
    db.commit()
    return api_success()


@router.post("/model/{model_id}/test")
def test_model(
    model_id: int,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    model = db.get(ModelConfig, model_id)
    if model is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="模型不存在")
    result = ModelClientService.test_model(model)
    OperationLogService.write(db, admin_id=current_admin.id, module="model", action="test", target_id=model.id)
    db.commit()
    return api_success(result)


@router.get("/config")
def list_config(db: Session = Depends(get_db), current_admin: Admin = Depends(get_current_admin)) -> dict:
    configs = db.scalars(select(SystemConfig).order_by(SystemConfig.config_key.asc())).all()
    return api_success([_config_dict(config) for config in configs])


@router.put("/config")
def save_config(
    payload: SystemConfigSaveRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    config = db.scalar(select(SystemConfig).where(SystemConfig.config_key == payload.configKey))
    if config is None:
        config = SystemConfig(config_key=payload.configKey, config_value=payload.configValue)
    config.config_value = payload.configValue
    config.description = payload.description
    config.updated_by = current_admin.id
    db.add(config)
    db.flush()
    OperationLogService.write(db, admin_id=current_admin.id, module="config", action="save", target_id=config.id)
    db.commit()
    db.refresh(config)
    return api_success(_config_dict(config))


def _model_dict(model: ModelConfig) -> dict:
    return {
        "id": model.id,
        "provider": model.provider,
        "displayName": model.display_name,
        "apiType": model.api_type,
        "modelName": model.model_name,
        "baseUrl": model.base_url,
        "apiUrl": model.api_url,
        "apiKeyMasked": "******" if model.api_key else "",
        "authType": model.auth_type,
        "apiVersion": model.api_version,
        "temperature": float(model.temperature) if model.temperature is not None else None,
        "topP": float(model.top_p) if model.top_p is not None else None,
        "topK": model.top_k,
        "presencePenalty": float(model.presence_penalty) if model.presence_penalty is not None else None,
        "frequencyPenalty": float(model.frequency_penalty) if model.frequency_penalty is not None else None,
        "maxToken": model.max_token,
        "contextWindow": model.context_window,
        "streamEnabled": model.stream_enabled,
        "responseFormat": model.response_format,
        "extraParams": model.extra_params,
        "remark": model.remark,
        "timeoutSecond": model.timeout_second,
        "enabled": model.enabled,
    }


def _agent_knowledge_scopes(db: Session, knowledge_ids: list[int]) -> list[KnowledgeScope]:
    query = select(Knowledge).where(Knowledge.status == 1)
    if knowledge_ids:
        query = query.where(Knowledge.id.in_(knowledge_ids))
    rows = db.scalars(query.order_by(Knowledge.id.asc())).all()
    return [
        KnowledgeScope(
            id=item.id,
            name=item.name,
            feishu_space_id=item.feishu_space_id,
            feishu_node_id=item.feishu_node_id,
        )
        for item in rows
    ]


def _build_agent_debug_prompt(prompt_content: str, question: str, chunks: list) -> str:
    context = "\n\n".join(
        f"[知识片段 {index}] 来源：{chunk.knowledge_name} / {chunk.title}\n{chunk.content}"
        for index, chunk in enumerate(chunks, start=1)
    )
    if not context:
        context = "未检索到相关知识片段。"
    return f"{prompt_content.strip()}\n\n{context}\n\n用户问题：{question.strip()}"


@router.post("/feishu/cache/clear")
def clear_feishu_cache(current_admin: Admin = Depends(get_current_admin)) -> dict:
    count = FeishuKnowledgeService.clear_cache()
    return api_success({"cleared": count, "message": f"已清空 {count} 条飞书缓存"})


def _config_dict(config: SystemConfig) -> dict:
    return {
        "id": config.id,
        "configKey": config.config_key,
        "configValue": config.config_value,
        "description": config.description,
        "updatedAt": config.updated_at,
    }
