import logging
import os
from contextlib import asynccontextmanager
from pathlib import Path

from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles

from nexus_agent.api.endpoints import chat, mcp as mcp_router, skills as skills_router, pages as pages_router, settings as settings_router, sessions as sessions_router, memory as memory_router, workspace as workspace_router
from nexus_agent.core.mcp_manager import mcp_manager
from nexus_agent.core.skill_manager import skill_manager
from nexus_agent.core.page_manager import page_manager
from nexus_agent.core.settings_manager import settings_manager
from nexus_agent.core.session_manager import session_manager
from nexus_agent.core.memory_manager import memory_manager
from nexus_agent.core.workspace_manager import workspace_manager

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 정적 파일 디렉토리 (wheel 내부)
STATIC_DIR = Path(__file__).parent / "static"


@asynccontextmanager
async def lifespan(app: FastAPI):
    # 데이터 디렉토리 자동 초기화 (init 없이도 start만으로 동작)
    from nexus_agent.config import init_data_dir
    data_dir = init_data_dir()
    env_path = data_dir / ".env"
    if env_path.exists():
        load_dotenv(env_path)

    # Startup
    logger.info("Loading settings...")
    settings_manager.load_config("settings.json")

    logger.info("Loading MCP config and connecting servers...")
    mcp_manager.load_config("mcp.json")
    await mcp_manager.connect_all()

    logger.info("Loading skills...")
    skill_manager.load_config("skills.json")
    bundled = str((Path(__file__).parent / "bundled_skills").resolve())
    skill_manager.discover_skills(["skills", bundled])

    logger.info("Loading pages...")
    page_manager.load_config("pages.json", "pages")

    logger.info("Loading sessions...")
    session_manager.load_config("sessions.json", "sessions")

    logger.info("Loading memories...")
    memory_manager.load_config("memories.json")

    logger.info("Loading workspaces...")
    workspace_manager.load_config("workspaces.json")
    yield
    # Shutdown
    logger.info("Disconnecting all MCP servers...")
    await mcp_manager.disconnect_all()


app = FastAPI(title="Nexus Agent API", lifespan=lifespan)

# CORS: 항상 허용 (다른 IP/포트에서 접속하는 경우 대비)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 라우터 등록
app.include_router(chat.router, prefix="/api/chat", tags=["chat"])
app.include_router(mcp_router.router, prefix="/api/mcp", tags=["mcp"])
app.include_router(skills_router.router, prefix="/api/skills", tags=["skills"])
app.include_router(pages_router.router, prefix="/api/pages", tags=["pages"])
app.include_router(settings_router.router, prefix="/api/settings", tags=["settings"])
app.include_router(sessions_router.router, prefix="/api/sessions", tags=["sessions"])
app.include_router(memory_router.router, prefix="/api/memory", tags=["memory"])
app.include_router(workspace_router.router, prefix="/api/workspace", tags=["workspace"])

# 정적 파일 서빙 (API 라우터 이후에 등록)
if STATIC_DIR.exists() and (STATIC_DIR / "index.html").exists():
    # Next.js static export의 _next/ 디렉토리 서빙
    next_dir = STATIC_DIR / "_next"
    if next_dir.exists():
        app.mount("/_next", StaticFiles(directory=next_dir), name="next-static")

    # SPA fallback: 모든 비-API 경로 처리 (GET + POST + HEAD — Next.js RSC 요청 포함)
    @app.api_route("/{path:path}", methods=["GET", "POST", "HEAD"])
    async def serve_frontend(path: str):
        # API 경로는 SPA fallback에서 제외 — 라우터가 처리하도록 함
        if path.startswith("api/"):
            from fastapi.responses import JSONResponse
            return JSONResponse(status_code=404, content={"detail": "Not Found"})
        # 파일이 존재하면 직접 서빙
        file_path = STATIC_DIR / path
        if file_path.is_file():
            return FileResponse(file_path)
        # Next.js export: /pages/viewer → /pages/viewer.html
        html_path = STATIC_DIR / f"{path}.html"
        if html_path.is_file():
            return FileResponse(html_path)
        # fallback → index.html (SPA navigation)
        index = STATIC_DIR / "index.html"
        if index.is_file():
            return FileResponse(index)
        return {"message": "Welcome to Nexus Agent API"}
else:
    @app.get("/")
    async def root():
        return {"message": "Welcome to Nexus Agent API"}
