from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import Optional
import uuid
from datetime import datetime

from ..db import get_db
from ..models import Assistant, LLMModel, ASRModel, Voice
from ..schemas import (
    AssistantCreate, AssistantUpdate, AssistantOut
)

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


def _is_siliconflow_vendor(vendor: Optional[str]) -> bool:
    return (vendor or "").strip().lower() in {"siliconflow", "硅基流动"}


def _resolve_runtime_metadata(db: Session, assistant: Assistant) -> dict:
    metadata = {
        "systemPrompt": assistant.prompt or "",
        "greeting": assistant.opener or "",
        "services": {},
    }
    warnings = []

    if assistant.llm_model_id:
        llm = db.query(LLMModel).filter(LLMModel.id == assistant.llm_model_id).first()
        if llm:
            metadata["services"]["llm"] = {
                "provider": "openai",
                "model": llm.model_name or llm.name,
                "apiKey": llm.api_key,
                "baseUrl": llm.base_url,
            }
        else:
            warnings.append(f"LLM model not found: {assistant.llm_model_id}")

    if assistant.asr_model_id:
        asr = db.query(ASRModel).filter(ASRModel.id == assistant.asr_model_id).first()
        if asr:
            asr_provider = "siliconflow" if _is_siliconflow_vendor(asr.vendor) else "buffered"
            metadata["services"]["asr"] = {
                "provider": asr_provider,
                "model": asr.model_name or asr.name,
                "apiKey": asr.api_key if asr_provider == "siliconflow" else None,
            }
        else:
            warnings.append(f"ASR model not found: {assistant.asr_model_id}")

    if assistant.voice:
        voice = db.query(Voice).filter(Voice.id == assistant.voice).first()
        if voice:
            tts_provider = "siliconflow" if _is_siliconflow_vendor(voice.vendor) else "edge"
            metadata["services"]["tts"] = {
                "provider": tts_provider,
                "model": voice.model,
                "apiKey": voice.api_key if tts_provider == "siliconflow" else None,
                "voice": voice.voice_key or voice.id,
                "speed": assistant.speed or voice.speed,
            }
        else:
            # Keep assistant.voice as direct voice identifier fallback
            metadata["services"]["tts"] = {
                "voice": assistant.voice,
                "speed": assistant.speed or 1.0,
            }
            warnings.append(f"Voice resource not found: {assistant.voice}")

    return {
        "assistantId": assistant.id,
        "sessionStartMetadata": metadata,
        "sources": {
            "llmModelId": assistant.llm_model_id,
            "asrModelId": assistant.asr_model_id,
            "voiceId": assistant.voice,
        },
        "warnings": warnings,
    }


def assistant_to_dict(assistant: Assistant) -> dict:
    return {
        "id": assistant.id,
        "name": assistant.name,
        "callCount": assistant.call_count,
        "opener": assistant.opener or "",
        "prompt": assistant.prompt or "",
        "knowledgeBaseId": assistant.knowledge_base_id,
        "language": assistant.language,
        "voice": assistant.voice,
        "speed": assistant.speed,
        "hotwords": assistant.hotwords or [],
        "tools": assistant.tools or [],
        "interruptionSensitivity": assistant.interruption_sensitivity,
        "configMode": assistant.config_mode,
        "apiUrl": assistant.api_url,
        "apiKey": assistant.api_key,
        "llmModelId": assistant.llm_model_id,
        "asrModelId": assistant.asr_model_id,
        "embeddingModelId": assistant.embedding_model_id,
        "rerankModelId": assistant.rerank_model_id,
        "created_at": assistant.created_at,
        "updated_at": assistant.updated_at,
    }


def _apply_assistant_update(assistant: Assistant, update_data: dict) -> None:
    field_map = {
        "knowledgeBaseId": "knowledge_base_id",
        "interruptionSensitivity": "interruption_sensitivity",
        "configMode": "config_mode",
        "apiUrl": "api_url",
        "apiKey": "api_key",
        "llmModelId": "llm_model_id",
        "asrModelId": "asr_model_id",
        "embeddingModelId": "embedding_model_id",
        "rerankModelId": "rerank_model_id",
    }
    for field, value in update_data.items():
        setattr(assistant, field_map.get(field, field), value)


# ============ Assistants ============
@router.get("")
def list_assistants(
    page: int = 1,
    limit: int = 50,
    db: Session = Depends(get_db)
):
    """获取助手列表"""
    query = db.query(Assistant)
    total = query.count()
    assistants = query.order_by(Assistant.created_at.desc()) \
        .offset((page-1)*limit).limit(limit).all()
    return {
        "total": total,
        "page": page,
        "limit": limit,
        "list": [assistant_to_dict(a) for a in assistants]
    }


@router.get("/{id}", response_model=AssistantOut)
def get_assistant(id: str, db: Session = Depends(get_db)):
    """获取单个助手详情"""
    assistant = db.query(Assistant).filter(Assistant.id == id).first()
    if not assistant:
        raise HTTPException(status_code=404, detail="Assistant not found")
    return assistant_to_dict(assistant)


@router.get("/{id}/runtime-config")
def get_assistant_runtime_config(id: str, db: Session = Depends(get_db)):
    """Resolve assistant runtime config for engine WS session.start metadata."""
    assistant = db.query(Assistant).filter(Assistant.id == id).first()
    if not assistant:
        raise HTTPException(status_code=404, detail="Assistant not found")
    return _resolve_runtime_metadata(db, assistant)


@router.post("", response_model=AssistantOut)
def create_assistant(data: AssistantCreate, db: Session = Depends(get_db)):
    """创建新助手"""
    assistant = Assistant(
        id=str(uuid.uuid4())[:8],
        user_id=1,  # 默认用户，后续添加认证
        name=data.name,
        opener=data.opener,
        prompt=data.prompt,
        knowledge_base_id=data.knowledgeBaseId,
        language=data.language,
        voice=data.voice,
        speed=data.speed,
        hotwords=data.hotwords,
        tools=data.tools,
        interruption_sensitivity=data.interruptionSensitivity,
        config_mode=data.configMode,
        api_url=data.apiUrl,
        api_key=data.apiKey,
        llm_model_id=data.llmModelId,
        asr_model_id=data.asrModelId,
        embedding_model_id=data.embeddingModelId,
        rerank_model_id=data.rerankModelId,
    )
    db.add(assistant)
    db.commit()
    db.refresh(assistant)
    return assistant_to_dict(assistant)


@router.put("/{id}")
def update_assistant(id: str, data: AssistantUpdate, db: Session = Depends(get_db)):
    """更新助手"""
    assistant = db.query(Assistant).filter(Assistant.id == id).first()
    if not assistant:
        raise HTTPException(status_code=404, detail="Assistant not found")

    update_data = data.model_dump(exclude_unset=True)
    _apply_assistant_update(assistant, update_data)

    assistant.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(assistant)
    return assistant_to_dict(assistant)


@router.delete("/{id}")
def delete_assistant(id: str, db: Session = Depends(get_db)):
    """删除助手"""
    assistant = db.query(Assistant).filter(Assistant.id == id).first()
    if not assistant:
        raise HTTPException(status_code=404, detail="Assistant not found")
    db.delete(assistant)
    db.commit()
    return {"message": "Deleted successfully"}
