from __future__ import annotations

import os

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware

from .knowledge import KnowledgeBase
from .llm import LLMError, LLMService, LLMTimeout
from .planner import PlannerService, SessionStore
from .schemas import HealthResponse, MessageRequest, PlanResponse, TravelPreferences


try:
    from dotenv import load_dotenv

    load_dotenv()
except ImportError:
    # Mock mode can run without python-dotenv; production installs project deps.
    pass

knowledge = KnowledgeBase()
llm = LLMService(knowledge)
planner = PlannerService(knowledge, llm, SessionStore())

app = FastAPI(
    title="光明区文旅行程助手 API",
    version="0.1.0",
    description="POC：本地知识检索 + OpenAI 兼容模型 + 内存会话",
)
origins = [
    origin.strip()
    for origin in os.getenv(
        "CORS_ORIGINS", "http://localhost:5173,http://127.0.0.1:5173"
    ).split(",")
    if origin.strip()
]
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=False,
    allow_methods=["GET", "POST"],
    allow_headers=["*"],
)


@app.get("/api/v1/health", response_model=HealthResponse)
async def health() -> HealthResponse:
    return HealthResponse(
        status="ok",
        llm_mode=llm.mode,
        model_configured=llm.configured,
        knowledge_count=knowledge.count,
    )


@app.post("/api/v1/plans", response_model=PlanResponse)
async def create_plan(preferences: TravelPreferences) -> PlanResponse:
    try:
        return await planner.create(preferences)
    except LookupError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
    except LLMTimeout as exc:
        raise HTTPException(status_code=504, detail=str(exc)) from exc
    except (LLMError, ValueError) as exc:
        raise HTTPException(status_code=502, detail=str(exc)) from exc


@app.post(
    "/api/v1/conversations/{conversation_id}/messages",
    response_model=PlanResponse,
)
async def adjust_plan(
    conversation_id: str, request: MessageRequest
) -> PlanResponse:
    try:
        return await planner.adjust(conversation_id, request.message)
    except LookupError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
    except LLMTimeout as exc:
        raise HTTPException(status_code=504, detail=str(exc)) from exc
    except (LLMError, ValueError) as exc:
        raise HTTPException(status_code=502, detail=str(exc)) from exc
