import json
import logging
import os
import urllib.request

from fastapi import APIRouter
from litellm import acompletion

from nexus_agent import __version__
from nexus_agent.core.settings_manager import settings_manager
from nexus_agent.core.llm import LLMClient
from nexus_agent.models.memory import MemorySettings
from nexus_agent.models.settings import LLMSettings, ProfileSettings, ThemeSettings, UpdateLLMRequest, UpdateMemorySettingsRequest, UpdateProfileRequest, UpdateThemeRequest

logger = logging.getLogger(__name__)
router = APIRouter()


@router.get("/version")
async def get_version():
    """현재 설치 버전과 PyPI 최신 버전 비교"""
    current = __version__
    latest = None
    try:
        req = urllib.request.Request(
            "https://pypi.org/pypi/nexus-agent-platform/json",
            headers={"Accept": "application/json"},
        )
        with urllib.request.urlopen(req, timeout=5) as resp:
            data = json.loads(resp.read().decode())
            latest = data.get("info", {}).get("version")
    except Exception:
        pass

    update_available = False
    if latest:
        try:
            cur = tuple(int(x) for x in current.split("."))
            lat = tuple(int(x) for x in latest.split("."))
            update_available = lat > cur
        except (ValueError, TypeError):
            update_available = latest != current

    return {
        "current": current,
        "latest": latest,
        "update_available": update_available,
    }


@router.get("/health")
async def health_check():
    """백엔드 서버 상태 + 실제 LLM 연결 테스트"""
    llm = settings_manager.llm
    api_key = llm.api_key or LLMClient._resolve_api_key(llm.model)

    result = {
        "server": "ok",
        "llm_connected": False,
        "model": llm.model,
        "error": None,
    }

    if not api_key and not llm.api_base:
        result["error"] = "API 키가 설정되지 않았습니다"
        return result

    try:
        kwargs = {
            "model": llm.model,
            "api_key": api_key,
            "messages": [{"role": "user", "content": "ping"}],
            "max_tokens": 1,
            "timeout": 8,
            "num_retries": 0,
        }
        if llm.api_base:
            kwargs["api_base"] = llm.api_base

        await acompletion(**kwargs)
        result["llm_connected"] = True
    except Exception as e:
        error_msg = str(e)
        # 너무 긴 에러 메시지 자르기
        if len(error_msg) > 200:
            error_msg = error_msg[:200] + "..."
        result["error"] = error_msg
        logger.warning(f"LLM connection test failed: {error_msg}")

    return result


@router.get("/llm", response_model=LLMSettings)
async def get_llm_settings():
    # api_key를 응답에서 마스킹
    llm = settings_manager.llm.model_copy()
    if llm.api_key:
        llm.api_key = llm.api_key[:4] + "***" + llm.api_key[-4:]
    return llm


@router.patch("/llm", response_model=LLMSettings)
async def update_llm_settings(req: UpdateLLMRequest):
    updated = settings_manager.update_llm(**req.model_dump(exclude_unset=True))
    # api_key를 응답에서 마스킹
    result = updated.model_copy()
    if result.api_key:
        result.api_key = result.api_key[:4] + "***" + result.api_key[-4:]
    return result


@router.get("/memory", response_model=MemorySettings)
async def get_memory_settings():
    return settings_manager.memory


@router.patch("/memory", response_model=MemorySettings)
async def update_memory_settings(req: UpdateMemorySettingsRequest):
    return settings_manager.update_memory(**req.model_dump(exclude_unset=True))


@router.get("/profile", response_model=ProfileSettings)
async def get_profile():
    return settings_manager.profile


@router.patch("/profile", response_model=ProfileSettings)
async def update_profile(req: UpdateProfileRequest):
    return settings_manager.update_profile(**req.model_dump(exclude_unset=True))


@router.get("/theme", response_model=ThemeSettings)
async def get_theme():
    return settings_manager.theme


@router.patch("/theme", response_model=ThemeSettings)
async def update_theme(req: UpdateThemeRequest):
    return settings_manager.update_theme(**req.model_dump(exclude_unset=True))
