import uvicorn
import os
import asyncio
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse, JSONResponse
from pydantic import BaseModel
from bson import json_util
import json

from config import get_config
from db import init_db, shutdown_db, get_db_client
from agents import app_graph, save_message
from tools.mongodb_chat_history_tool import MAX_HISTORY_LIMIT

app = FastAPI(title="FikoGPT Turbo", version="1.1.0")
config = get_config()

# CORS – gerekli ise domainlerinizi kısıtlayın
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.on_event("startup")
async def startup_event() -> None:
    await init_db()

@app.on_event("shutdown")
async def shutdown_event() -> None:
    await shutdown_db()

class AskPayload(BaseModel):
    thread_id: str
    prompt: str

@app.post("/ask")
async def ask(payload: AskPayload):
    if not payload.thread_id or not payload.prompt:
        raise HTTPException(status_code=400, detail="thread_id ve prompt zorunludur")

    async def iterator():
        async for chunk in app_graph_stream(payload.thread_id, payload.prompt):
            yield chunk
            await asyncio.sleep(0)

    return StreamingResponse(iterator(), media_type="text/plain; charset=utf-8")

@app.get("/history/{thread_id}")
async def history(thread_id: str, limit: int = 20):
    limit = min(max(limit, 1), MAX_HISTORY_LIMIT)
    client = get_db_client()
    db = client[config["DB_NAME"]]
    chat_col = db[config["COLLECTION_CHAT"]]
    
    cursor = (
        chat_col
        .find({"thread_id": thread_id}, projection={"_id": 0})
        .sort("timestamp", 1)
        .limit(limit)
        .max_time_ms(3000)
    )
    docs = [doc async for doc in cursor]
    return JSONResponse(content=json.loads(json_util.dumps(docs)))

@app.get("/health")
async def health():
    try:
        db_client = get_db_client()
        await db_client.admin.command("ping")
        mongo_ok = True
    except Exception:
        mongo_ok = False
    return {"status": "ok", "mongo": mongo_ok}

async def app_graph_stream(thread_id: str, prompt: str):
    async for chunk in stream_llm(thread_id, prompt):
        yield chunk

async def chat_cli():
    print("💬 FikoGPT CLI başlatıldı. Çıkmak için 'exit' yaz.")
    thread_id = "console_user"
    while True:
        try:
            prompt = input("Kullanıcı: ")
        except (EOFError, KeyboardInterrupt):
            break

        if prompt.strip().lower() in {"exit", "quit"}:
            break

        print("FikoGPT: ", end="", flush=True)
        async for chunk in app_graph_stream(thread_id, prompt):
            print(chunk, end="", flush=True)
        print()

if __name__ == "__main__":
    mode = os.getenv("MODE")
    if not mode:
        try:
            mode = input("Mod seç: 1=CLI, 2=API (FastAPI uvicorn)\nSeçim: ").strip()
        except (EOFError, KeyboardInterrupt):
            mode = "2"

    if mode == "1":
        async def main_cli():
            await init_db()
            await chat_cli()
        asyncio.run(main_cli())
    else:
        uvicorn.run(
            "FikoGpt.main:app",
            host="0.0.0.0",
            port=int(os.getenv("PORT", "8000")),
            reload=True,
            log_level=os.getenv("LOG_LEVEL", "info"),
        )