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

from src.core.loader import ChallengeLoader
from src.core.executor import executor
from src.core.linter import linter
from src.core.prompts import get_socratic_prompt

app = FastAPI(title="Socratic Tutor API")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

loader = ChallengeLoader()


class LintRequest(BaseModel):
    language: str
    code: str


from typing import Optional


class GuideRequest(BaseModel):
    challenge_id: str
    language: str
    code: str
    question: Optional[str] = ""


class RunRequest(BaseModel):
    language: str
    code: str
    stdin: Optional[str] = ""


@app.get("/challenges")
def list_challenges():
    """Returns a list of all challenge details."""
    challenges = loader.load_all()
    return {"challenges": [c.to_dict(challenge_id=k) for k, c in sorted(challenges.items())]}


@app.get("/challenges/{challenge_id}")
def get_challenge(challenge_id: str):
    """Returns details of a single challenge."""
    challenges = loader.load_all()
    if challenge_id not in challenges:
        raise HTTPException(status_code=404, detail=f"Challenge '{challenge_id}' not found.")
    return challenges[challenge_id].to_dict(challenge_id=challenge_id)


@app.post("/lint")
def lint_code(req: LintRequest):
    """Runs linting on user code using Core Linter."""
    res = linter.lint(req.language, req.code)
    if res.get("stderr") == f"Language '{req.language}' is not supported.":
        raise HTTPException(status_code=404, detail=res["stderr"])
    return res


@app.post("/run")
def run_code(req: RunRequest):
    """Executes user code using Core Executor."""
    res = executor.run(req.language, req.code, stdin=req.stdin or "")
    if res.get("stderr") == f"Language '{req.language}' is not supported.":
        raise HTTPException(status_code=404, detail=res["stderr"])
    return res


from src.core.mentor import mentor
from src.core.generator import generator


class GenerateChallengeRequest(BaseModel):
    prompt: str
    difficulty: Optional[str] = "Medium"
    language: Optional[str] = "Python"
    subject: Optional[str] = "General"


class SaveChallengeRequest(BaseModel):
    filename: str
    markdown: str


@app.post("/guide")
async def guide_code(req: GuideRequest):
    """Provides mentor guidance based on user's code and question for a challenge."""
    challenges = loader.load_all()
    if req.challenge_id not in challenges:
        raise HTTPException(status_code=404, detail=f"Challenge '{req.challenge_id}' not found.")

    challenge = challenges[req.challenge_id]
    guidance = await mentor.get_guidance_async(
        challenge, req.code, user_question=req.question or ""
    )

    return {
        "challenge_id": req.challenge_id,
        "status": guidance.get("status"),
        "mentor_response": guidance.get("mentor_response"),
    }


@app.post("/challenges/generate")
async def generate_challenge_endpoint(req: GenerateChallengeRequest):
    """Generates a new challenge markdown document via LLM."""
    res = await generator.generate_challenge_async(
        prompt_text=req.prompt,
        difficulty=req.difficulty or "Medium",
        language=req.language or "Python",
        subject=req.subject or "General",
    )
    if res.get("status") == "error":
        raise HTTPException(status_code=500, detail=res.get("message"))
    return res


@app.post("/challenges/save")
def save_challenge_endpoint(req: SaveChallengeRequest):
    """Saves generated markdown challenge content to disk."""
    res = generator.save_challenge(req.filename, req.markdown)
    if res.get("status") == "error":
        raise HTTPException(status_code=500, detail=res.get("message"))
    return res


from src.core.handbook import handbook_service


class HandbookExampleRequest(BaseModel):
    language: str
    topic_id: str
    topic_title: str


@app.get("/handbook/catalog/{language}")
def get_handbook_catalog_endpoint(language: str):
    """Returns W3Schools-style syntax handbook catalog (functions & subjects) for specified language."""
    catalog = handbook_service.get_catalog(language)
    return {"language": language, "catalog": catalog}


@app.get("/handbook/topics/{language}")
def get_handbook_topics_endpoint(language: str):
    """Returns syntax handbook catalog for backwards compatibility."""
    catalog = handbook_service.get_catalog(language)
    return {"language": language, "topics": catalog.get("functions", []) + catalog.get("subjects", [])}



@app.post("/handbook/example")
async def get_handbook_example_endpoint(req: HandbookExampleRequest):
    """Generates an LLM code example for a handbook reference topic."""
    res = await handbook_service.generate_example_async(
        language=req.language,
        topic_id=req.topic_id,
        topic_title=req.topic_title,
    )
    if res.get("status") == "error":
        raise HTTPException(status_code=500, detail=res.get("message"))
    return res


if __name__ == "__main__":
    import uvicorn
    from src.core.config import config
    uvicorn.run("src.api.main:app", host=config.web_host, port=config.web_port, reload=True)





