from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
from fastapi.responses import Response
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.database import get_db
from app.models.user import User
from app.models.ai_model_config import AIModelConfig
from app.services import ai_service
from app.utils.auth import get_current_user, check_rate_limit

router = APIRouter()


class TTSRequest(BaseModel):
    text: str
    voice: str | None = None  # model_id override


MAX_AUDIO_UPLOAD_BYTES = 25 * 1024 * 1024


def _task_model(db: Session, task: str, fallback: str) -> tuple[str, str | None]:
    config = db.query(AIModelConfig).filter(
        AIModelConfig.task == task,
        AIModelConfig.is_active == True,
        AIModelConfig.is_default == True,
    ).first()
    if config:
        return config.model_id, config.api_key or None
    return fallback, None


def _default_tts_model(db: Session) -> tuple[str, str | None]:
    config = db.query(AIModelConfig).filter(
        AIModelConfig.task == "tts",
        AIModelConfig.is_active == True,
        AIModelConfig.is_default == True,
        AIModelConfig.model_id.like("local-%"),
    ).first()
    if config:
        return config.model_id, config.api_key or None
    return "local-kokoro-tts:am_adam", None


@router.get("/voices")
def get_voices(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Return LiteLLM-routed TTS models only."""
    query = db.query(AIModelConfig).filter(
        AIModelConfig.task == "tts",
        AIModelConfig.is_active == True,
        AIModelConfig.model_id.like("local-%"),
    )
    db_models = query.order_by(AIModelConfig.is_default.desc(), AIModelConfig.name).all()
    return [{"id": m.model_id, "name": m.name, "is_default": m.is_default} for m in db_models]


@router.post("/speak")
def text_to_speech(
    request: TTSRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Convert text to speech using configured or user-selected TTS model."""
    # Rate limit: 60 TTS requests per user per hour (admins/unthrottled users exempt)
    check_rate_limit(
        key=f"tts_speak:{current_user.id}",
        max_calls=240,
        window_seconds=3600,
        detail="You've reached the audio limit. The limit resets automatically — try again shortly. Contact an admin if you need this raised.",
        user=current_user,
    )
    if not request.text.strip():
        raise HTTPException(status_code=400, detail="Text cannot be empty")

    text = request.text[:2000]

    if request.voice and request.voice.startswith("local-"):
        config = db.query(AIModelConfig).filter(
            AIModelConfig.task == "tts",
            AIModelConfig.is_active == True,
            AIModelConfig.model_id == request.voice,
        ).first()
        if not config:
            model_id, api_key = _default_tts_model(db)
        else:
            model_id = config.model_id
            api_key = config.api_key or None
    else:
        model_id, api_key = _default_tts_model(db)

    audio = ai_service.generate_tts_audio(text, model_id=model_id, api_key=api_key)
    if audio is None:
        raise HTTPException(status_code=500, detail="TTS generation failed. Check model configuration.")

    return Response(content=audio, media_type="audio/mpeg")


@router.post("/transcribe")
def speech_to_text(
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Transcribe microphone audio using the configured STT model."""
    check_rate_limit(
        key=f"stt_transcribe:{current_user.id}",
        max_calls=120,
        window_seconds=3600,
        detail="You've reached the speech transcription limit. Try again shortly.",
        user=current_user,
    )
    audio = file.file.read()
    if not audio:
        raise HTTPException(status_code=400, detail="Audio file is empty")
    if len(audio) > MAX_AUDIO_UPLOAD_BYTES:
        raise HTTPException(status_code=413, detail="Audio file is too large")

    model_id, api_key = _task_model(db, "stt", "local-parakeet-v3")
    text = ai_service.transcribe_audio(
        audio,
        filename=file.filename or "audio.webm",
        content_type=file.content_type or "audio/webm",
        model_id=model_id,
        api_key=api_key,
    )
    if text is None:
        raise HTTPException(status_code=502, detail="Speech transcription failed. Check STT model configuration.")
    return {"text": text, "model": model_id}
