import logging
import os
from contextlib import asynccontextmanager
from typing import Dict

from fastapi import FastAPI, Request, Depends
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware

from app import chatbot, auth, meeting, email_provider
from app.config import get_settings
from app.rag.pipeline import init_rag, ingest_documents
from app.student_api import close_student_api_client

os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

settings = get_settings()

# logging setup, level and optional file come from config
def _setup_logging() -> None:
    handlers = [logging.StreamHandler()]
    if settings.log_file:
        # write logs to a file in production when LOG_FILE is set
        os.makedirs(os.path.dirname(settings.log_file) or ".", exist_ok=True)
        handlers.append(logging.FileHandler(settings.log_file, encoding="utf-8"))

    logging.basicConfig(
        level=getattr(logging, settings.log_level, logging.INFO),
        format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
        handlers=handlers,
    )

_setup_logging()
logger = logging.getLogger(__name__)

# startup / shutdown, build or load the chromadb index on startup
@asynccontextmanager
async def lifespan(app: FastAPI):
    logger.info("Starting MyACC Virtual Assistant...")
    #try:
    init_rag()
        #logger.info("RAG pipeline ready.")
    #except Exception as exc:
        #logger.error("RAG init failed (app will still start): %s", exc)
    yield
    logger.info("Shutting down MyACC Virtual Assistant...")
    # close the shared student api connection cleanly on shutdown
    await close_student_api_client()

# app
app = FastAPI(title="MyACC Virtual Assistant", lifespan=lifespan)

# allow the frontend origins listed in config to call this api
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origin_list,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(chatbot.router)
app.include_router(auth.router)
app.include_router(meeting.router)
app.include_router(email_provider.router)

BASE_DIR   = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_DIR = os.path.join(BASE_DIR, "static")
templates  = Jinja2Templates(directory="templates")

app.mount("/assets", StaticFiles(directory=STATIC_DIR, html=True), name="static")

# catch anything unexpected, log the detail and return a clean error
@app.exception_handler(Exception)
async def unhandled_exception_handler(request: Request, exc: Exception):
    logger.exception("Unhandled error on %s %s", request.method, request.url.path)
    return JSONResponse(
        status_code=500,
        content={"detail": "Internal server error"},
    )

# health check for deployment and monitoring
@app.get("/health")
async def health():
    return {"status": "ok"}

# admin: re-ingest knowledge base
@app.post("/admin/reingest")
async def reingest_kb(current_user: Dict = Depends(chatbot.get_current_user)):
    count = ingest_documents()
    return {"status": "ok", "chunks_ingested": count}

# user info api
@app.get("/api/user")
async def api_user(current_user: Dict = Depends(chatbot.get_current_user)):
    """
    Returns the logged-in user's profile to the frontend.

    All data comes directly from the signed session cookie which was
    populated at login time, either from the real Student API response
    or from the local fallback dict.

    No extra API call is made here on every page load, keeping it fast.

    Response fields:
      username          - login ID (Student_ID or role name)
      role              - "student" | "advisor" | "financial-aid" | "counselor"
      first_name        - from API First_Name  (e.g. "Tester1")
      last_name         - from API Last_Name   (e.g. "Subject1")
      full_name         - First + Last joined  (e.g. "Tester1 Subject1")
      student_id        - from API Student_ID  (e.g. "1234561")
      email             - from API Email_Address
      enrollment_status - from API Enrollment_Status ("PT" or "FT")
      program_id        - from API Program_Id
      admit_term        - from API Admit_Term  (e.g. "SP2026")
      student_type      - from API Student_Type (e.g. "First-Time")
      academic_level    - from API Academic_Level (e.g. "UG")
    """
    username   = current_user.get("username") or ""
    first_name = current_user.get("first_name") or ""
    last_name  = current_user.get("last_name") or ""

    # build first_name fallback from username if api didn't provide one
    # (happens in demo/local mode where username = "student", "advisor" etc.)
    if not first_name:
        first_name = username.split(".")[0].replace("-", " ").replace("_", " ").title()

    full_name = f"{first_name} {last_name}".strip()

    return {
        "username":          username,
        "role":              current_user.get("role"),
        "first_name":        first_name,
        "last_name":         last_name,
        "full_name":         full_name,
        "student_id":        current_user.get("student_id", ""),
        "email":             current_user.get("email", ""),
        "enrollment_status": current_user.get("enrollment_status", ""),
        "program_id":        current_user.get("program_id", ""),
        "admit_term":        current_user.get("admit_term", ""),
        "student_type":      current_user.get("student_type", ""),
        "academic_level":    current_user.get("academic_level", ""),
    }

# context helper
def context(request, title, active_page, db, current_user):
    return {
        "request": request,
        "title": title,
        "active_page": active_page,
        "open_chats": chatbot.list_open_sessions(db, current_user),
    }

# pages
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
    return templates.TemplateResponse(request, "index.html")

@app.get("/login-page", response_class=HTMLResponse)
async def login_page(request: Request):
    return templates.TemplateResponse(request, "login-page.html")

# student
@app.get("/student/dashboard", response_class=HTMLResponse)
async def student_dashboard(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "student/dashboard.html", context(request, "Dashboard", "dashboard", db, current_user))

@app.get("/student/chat", response_class=HTMLResponse)
async def student_chat(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "student/chat.html", context(request, "MyACC Virtual Assistant", "chat", db, current_user))

@app.get("/student/campus-pathfinder", response_class=HTMLResponse)
async def student_campus_pathfinder(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "student/campus-pathfinder.html", context(request, "Campus Pathfinder", "campus-pathfinder", db, current_user))

@app.get("/student/planner-and-smart-alerts", response_class=HTMLResponse)
async def student_planner(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "student/planner-and-smart-alerts.html", context(request, "Planner & Smart Alerts", "planner-and-smart-alerts", db, current_user))

@app.get("/student/resource-directory", response_class=HTMLResponse)
async def student_resource_directory(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "student/resource-directory.html", context(request, "Resource Directory", "resource-directory", db, current_user))

@app.get("/student/xr-library", response_class=HTMLResponse)
async def student_xr_library(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "student/xr-library.html", context(request, "XR Library", "xr-library", db, current_user))

# advisor
@app.get("/advisor/dashboard", response_class=HTMLResponse)
async def advisor_dashboard(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/dashboard.html", context(request, "Dashboard", "dashboard", db, current_user))

@app.get("/advisor/chat", response_class=HTMLResponse)
async def advisor_chat(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/chat.html", context(request, "MyACC Virtual Assistant", "chat", db, current_user))

@app.get("/advisor/advisee-list", response_class=HTMLResponse)
async def advisor_advisee_list(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/advisee-list.html", context(request, "Advisee List", "advisee-list", db, current_user))

@app.get("/advisor/advisee-chats", response_class=HTMLResponse)
async def advisor_advisee_chats(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/advisee-chats.html", context(request, "Advisee Chatlog", "advisee-chats", db, current_user))

@app.get("/advisor/planner-and-smart-alerts", response_class=HTMLResponse)
async def advisor_planner(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/planner-and-smart-alerts.html", context(request, "Planner & Smart Alerts", "planner-and-smart-alerts", db, current_user))

@app.get("/advisor/resource-directory", response_class=HTMLResponse)
async def advisor_resource_directory(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/resource-directory.html", context(request, "Resource Directory", "resource-directory", db, current_user))

@app.get("/advisor/campus-pathfinder", response_class=HTMLResponse)
async def advisor_campus_pathfinder(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/campus-pathfinder.html", context(request, "Campus Pathfinder", "campus-pathfinder", db, current_user))

@app.get("/advisor/xr-library", response_class=HTMLResponse)
async def advisor_xr_library(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/xr-library.html", context(request, "XR Library", "xr-library", db, current_user))

@app.get("/advisor/crisis-notifications", response_class=HTMLResponse)
async def advisor_crisis_notifications(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "advisor/crisis-notifications.html", context(request, "Crisis Alerts", "crisis-notifications", db, current_user))

# financial aid
@app.get("/financial-aid/dashboard", response_class=HTMLResponse)
async def fa_dashboard(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/dashboard.html", context(request, "Dashboard", "dashboard", db, current_user))

@app.get("/financial-aid/chat", response_class=HTMLResponse)
async def fa_chat(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/chat.html", context(request, "MyACC Virtual Assistant", "chat", db, current_user))

@app.get("/financial-aid/student-list", response_class=HTMLResponse)
async def fa_student_list(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/student-list.html", context(request, "Student List", "student-list", db, current_user))

@app.get("/financial-aid/student-chats", response_class=HTMLResponse)
async def fa_student_chats(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/student-chats.html", context(request, "Student Chatlog", "student-chats", db, current_user))

@app.get("/financial-aid/planner-and-smart-alerts", response_class=HTMLResponse)
async def fa_planner(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/planner-and-smart-alerts.html", context(request, "Planner & Smart Alerts", "planner-and-smart-alerts", db, current_user))

@app.get("/financial-aid/resource-directory", response_class=HTMLResponse)
async def fa_resource_directory(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/resource-directory.html", context(request, "Resource Directory", "resource-directory", db, current_user))

@app.get("/financial-aid/campus-pathfinder", response_class=HTMLResponse)
async def fa_campus_pathfinder(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/campus-pathfinder.html", context(request, "Campus Pathfinder", "campus-pathfinder", db, current_user))

@app.get("/financial-aid/xr-library", response_class=HTMLResponse)
async def fa_xr_library(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "financial-aid/xr-library.html", context(request, "XR Library", "xr-library", db, current_user))

# counselor
@app.get("/counselor/dashboard", response_class=HTMLResponse)
async def co_dashboard(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/dashboard.html", context(request, "Dashboard", "dashboard", db, current_user))

@app.get("/counselor/chat", response_class=HTMLResponse)
async def co_chat(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/chat.html", context(request, "MyACC Virtual Assistant", "chat", db, current_user))

@app.get("/counselor/student-list", response_class=HTMLResponse)
async def co_student_list(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/student-list.html", context(request, "Student List", "student-list", db, current_user))

@app.get("/counselor/student-chats", response_class=HTMLResponse)
async def co_student_chats(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/student-chats.html", context(request, "Student Chatlog", "student-chats", db, current_user))

@app.get("/counselor/planner-and-smart-alerts", response_class=HTMLResponse)
async def co_planner(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/planner-and-smart-alerts.html", context(request, "Planner & Smart Alerts", "planner-and-smart-alerts", db, current_user))

@app.get("/counselor/resource-directory", response_class=HTMLResponse)
async def co_resource_directory(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/resource-directory.html", context(request, "Resource Directory", "resource-directory", db, current_user))

@app.get("/counselor/campus-pathfinder", response_class=HTMLResponse)
async def co_campus_pathfinder(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/campus-pathfinder.html", context(request, "Campus Pathfinder", "campus-pathfinder", db, current_user))

@app.get("/counselor/xr-library", response_class=HTMLResponse)
async def co_xr_library(request: Request, db=Depends(chatbot.get_db), current_user: Dict = Depends(chatbot.get_current_user)):
    return templates.TemplateResponse(request, "counselor/xr-library.html", context(request, "XR Library", "xr-library", db, current_user))