# standard
import os
import tomllib
import tomli_w
from enum import Enum
from pathlib import Path

# third party
# custom
from sunwaee.core.logger import get_logger

_log = get_logger("config")

_DEFAULT_CONFIG: dict = {
    "workspaces": {
        "default": "personal",
        "base_dir": "~/sunwaee/workspaces",
    },
    "sun": {
        "default_model": "claude-sonnet-4-6",
        "default_provider": "anthropic",
        "api_url": "http://localhost:8000",
    },
}


class Caller(str, Enum):
    USER = "user"
    API = "api"
    SUN = "sun"


def _config_dir() -> Path:
    return Path(os.environ.get("SUNWAEE_CONFIG_DIR", Path.home() / ".sunwaee"))


def _config_file() -> Path:
    return _config_dir() / "config.toml"


def get_caller() -> Caller:
    val = os.environ.get("SUNWAEE_CALLER", "human").lower()
    try:
        return Caller(val)
    except ValueError:
        return Caller.USER


def is_machine_caller() -> bool:
    return get_caller() in (Caller.API, Caller.SUN)


def _load_config() -> dict:
    cfg_dir = _config_dir()
    cfg_file = _config_file()
    if not cfg_file.exists():
        _log.info("Config file not found, creating default at %s", cfg_file)
        cfg_dir.mkdir(parents=True, exist_ok=True)
        with open(cfg_file, "wb") as f:
            tomli_w.dump(_DEFAULT_CONFIG, f)
    _log.debug("Loading config from %s", cfg_file)
    with open(cfg_file, "rb") as f:
        return tomllib.load(f)


def _save_config(cfg: dict) -> None:
    cfg_dir = _config_dir()
    cfg_dir.mkdir(parents=True, exist_ok=True)
    _log.debug("Saving config to %s", _config_file())
    with open(_config_file(), "wb") as f:
        tomli_w.dump(cfg, f)


def get_workspaces_base_dir() -> Path:
    env = os.environ.get("SUNWAEE_WORKSPACES_DIR")
    if env:
        return Path(env).expanduser()
    cfg = _load_config()
    return Path(
        cfg.get("workspaces", {}).get("base_dir", "~/sunwaee/workspaces")
    ).expanduser()


def get_default_workspace() -> str:
    env = os.environ.get("SUNWAEE_WORKSPACE")
    if env:
        return env
    cfg = _load_config()
    return cfg.get("workspaces", {}).get("default", "personal")


def set_default_workspace(name: str) -> None:
    _log.info("Setting default workspace to %r", name)
    cfg = _load_config()
    cfg.setdefault("workspaces", {})["default"] = name
    _save_config(cfg)


def get_sun_default_model() -> tuple[str, str]:
    """Return (model_name, provider) from config."""
    cfg = _load_config()
    sun = cfg.get("sun", {})
    model = sun.get("default_model", "claude-sonnet-4-6")
    provider = sun.get("default_provider", "anthropic")
    return model, provider


def set_sun_default_model(model: str, provider: str) -> None:
    cfg = _load_config()
    cfg.setdefault("sun", {})["default_model"] = model
    cfg.setdefault("sun", {})["default_provider"] = provider
    _save_config(cfg)


def get_all_workspaces() -> list[str]:
    """Return all workspace names found in the base directory."""
    base = get_workspaces_base_dir()
    if not base.exists():
        return [get_default_workspace()]
    dirs = sorted(d.name for d in base.iterdir() if d.is_dir())
    return dirs if dirs else [get_default_workspace()]


def get_workspace_dir(workspace: str) -> Path:
    """Return the root directory for a given workspace."""
    return get_workspaces_base_dir() / workspace


def get_module_dir(workspace: str, module: str, project: str | None = None) -> Path:
    """Return the directory for a given module within a workspace (or project)."""
    base = get_workspace_dir(workspace)
    if project:
        return base / "projects" / project / module
    return base / module


def get_project_dir(workspace: str, project: str) -> Path:
    """Return the root directory for a given project within a workspace."""
    return get_workspace_dir(workspace) / "projects" / project


def get_all_projects(workspace: str) -> list[str]:
    """Return all project names within a workspace."""
    projects_dir = get_workspace_dir(workspace) / "projects"
    if not projects_dir.exists():
        return []
    return sorted(
        d.name
        for d in projects_dir.iterdir()
        if d.is_dir() and not d.name.startswith(".")
    )


def get_active_project(workspace: str | None = None) -> str | None:
    """Return the active project for the given workspace, or None if workspace-level."""
    env = os.environ.get("SUNWAEE_PROJECT")
    if env:
        return env
    ws = workspace or get_default_workspace()
    cfg = _load_config()
    return cfg.get("projects", {}).get(ws)


def set_default_project(workspace: str, name: str) -> None:
    cfg = _load_config()
    cfg.setdefault("projects", {})[workspace] = name
    _save_config(cfg)
