import json
import os
import tempfile
from pathlib import Path
from typing import List, Dict, Any, Optional

from platformdirs import user_config_dir, user_data_dir

APP_NAME = "llm4s"

# 플랫폼별 고정 경로 (CWD 독립적)
# macOS: ~/Library/Application Support/llm4s/
# Linux: ~/.local/share/llm4s/
# Windows: C:\Users\<user>\AppData\Local\llm4s\llm4s\
_CONFIG_DIR = Path(user_config_dir(APP_NAME))
_DATA_DIR   = Path(user_data_dir(APP_NAME))

_CONFIG_DIR.mkdir(parents=True, exist_ok=True)
_DATA_DIR.mkdir(parents=True, exist_ok=True)

CONFIG_PATH = _CONFIG_DIR / "config.json"
DB_PATH     = _DATA_DIR   / "llm4s_logs.db"

def atomic_write_json(path: Path, data: dict) -> None:
    """임시 파일에 쓴 뒤 os.replace()로 원자적 교체. 쓰기 중 실패해도 원본 파일 보존."""
    path = Path(path)
    fd, tmp_path = tempfile.mkstemp(dir=path.parent, prefix=".llm4s_tmp_", suffix=".json")
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
            f.write("\n")
            f.flush()
            os.fsync(f.fileno())
        os.replace(tmp_path, path)
    except Exception:
        try:
            os.unlink(tmp_path)
        except OSError:
            pass
        raise


def load_config() -> Dict[str, Any]:
    """설정 파일을 로드합니다. 파일이 없으면 기본 구조를 반환합니다."""
    default_config = {"providers": [], "servers": []}
    if not CONFIG_PATH.exists():
        return default_config
    try:
        with open(CONFIG_PATH, "r", encoding="utf-8") as f:
            config = json.load(f)
            # 하위 호환성 유지
            if "providers" not in config:
                config["providers"] = []
            if "servers" not in config:
                config["servers"] = []
            return config
    except Exception:
        return default_config

def save_config(config: Dict[str, Any]):
    """설정을 파일에 원자적으로 저장합니다."""
    atomic_write_json(CONFIG_PATH, config)
    try:
        os.chmod(CONFIG_PATH, 0o600)
    except OSError:
        pass

def register_server(name: str, command: str, args: List[str]):
    """새로운 MCP 서버를 등록하거나 기존 정보를 업데이트합니다."""
    config = load_config()
    server_info = {
        "name": name,
        "command": command,
        "args": args
    }
    
    # 이미 같은 이름의 서버가 있다면 업데이트, 없으면 추가
    for i, s in enumerate(config["servers"]):
        if s["name"] == name:
            config["servers"][i] = server_info
            break
    else:
        config["servers"].append(server_info)
    
    save_config(config)

def list_servers() -> List[Dict[str, Any]]:
    """등록된 모든 서버 목록을 반환합니다."""
    config = load_config()
    return config.get("servers", [])

def get_server(name: str) -> Optional[Dict[str, Any]]:
    """특정 이름의 서버 정보를 가져옵니다."""
    servers = list_servers()
    for s in servers:
        if s["name"] == name:
            return s
    return None

def remove_server(name: str):
    """서버 등록을 해제합니다."""
    config = load_config()
    config["servers"] = [s for s in config["servers"] if s["name"] != name]
    save_config(config)

def register_provider(name: str, env_key: str, api_key: Optional[str] = None):
    """Provider(OpenAI, Anthropic 등) 정보를 등록합니다."""
    config = load_config()
    provider_info = {
        "name": name,
        "env_key": env_key,
        "api_key": api_key
    }
    
    for i, p in enumerate(config["providers"]):
        if p["name"] == name:
            config["providers"][i] = provider_info
            break
    else:
        config["providers"].append(provider_info)
    
    save_config(config)

def list_providers() -> List[Dict[str, Any]]:
    """등록된 모든 Provider 목록을 반환합니다."""
    config = load_config()
    providers = config.get("providers", [])
    
    import os
    for p in providers:
        env_key = p.get("env_key", "")
        # 환경 변수를 우선으로 확인 (보안 최우선)
        env_val = os.getenv(env_key) if env_key else None
        stored_key = p.get("api_key")
        
        # 환경변수 > 파일 저장 키 순서 (평문 저장 의존도 줄이기)
        final_key = env_val or stored_key
        p["api_key"] = final_key  # interceptor에서 사용
        p["status"] = "OK" if final_key else "MISSING"
        p["key_hint"] = f"{final_key[:6]}..." if final_key else "-"
        p["source"] = "env" if env_val else ("file" if stored_key else "none")
        
    return providers
