from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Any, Callable, Dict, Mapping, Optional


DEFAULT_API_URL = "https://app.autotouch.ai"
CONFIG_ENV_KEY = "AUTOTOUCH_CONFIG_PATH"
CONFIG_DIR_NAME = "autotouch"
CONFIG_FILE_NAME = "config.json"


def package_version(*, package_name: str = "autotouch-cli") -> str:
    pyproject_path = Path(__file__).resolve().parents[2] / "pyproject.toml"
    try:
        for line in pyproject_path.read_text(encoding="utf-8").splitlines():
            line = line.strip()
            if line.startswith("version = "):
                return line.split("=", 1)[1].strip().strip('"').strip("'")
    except Exception:
        pass
    try:
        from importlib import metadata as importlib_metadata

        return str(importlib_metadata.version(package_name))
    except Exception:
        pass
    return "0.0.0"


def load_env_files(load_dotenv: Optional[Callable[..., Any]]) -> None:
    if load_dotenv is None:
        return
    script_root = Path(__file__).resolve().parents[2]
    candidates = [Path.cwd() / ".env", script_root / ".env"]
    seen = set()
    for candidate in candidates:
        path = candidate.resolve()
        if path in seen:
            continue
        seen.add(path)
        if path.exists():
            load_dotenv(path, override=False)


def config_path() -> Path:
    def _normalize_path(raw_path: Path, raw_override: Optional[str] = None) -> Path:
        override_text = str(raw_override or "")
        if raw_path.exists() and raw_path.is_dir():
            return raw_path / CONFIG_FILE_NAME
        if override_text.endswith(("/", "\\")):
            return raw_path / CONFIG_FILE_NAME
        return raw_path

    override = os.environ.get(CONFIG_ENV_KEY)
    if override:
        return _normalize_path(Path(override).expanduser(), override)
    xdg_home = os.environ.get("XDG_CONFIG_HOME")
    if xdg_home:
        return Path(xdg_home).expanduser() / CONFIG_DIR_NAME / CONFIG_FILE_NAME
    return Path.home() / ".config" / CONFIG_DIR_NAME / CONFIG_FILE_NAME


def load_config() -> Dict[str, Any]:
    path = config_path()
    if not path.exists():
        return {}
    try:
        with open(path, "r", encoding="utf-8") as handle:
            data = json.load(handle)
        if isinstance(data, dict):
            return data
    except Exception:
        pass
    return {}


def save_config(data: Dict[str, Any]) -> Path:
    path = config_path()
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(path, "w", encoding="utf-8") as handle:
        json.dump(data, handle, indent=2, sort_keys=True)
    try:
        os.chmod(path, 0o600)
    except Exception:
        pass
    return path


def api_url(
    value: Optional[str] = None,
    *,
    load_config_fn: Callable[[], Dict[str, Any]] = load_config,
    env: Optional[Mapping[str, str]] = None,
    default_api_url: str = DEFAULT_API_URL,
) -> str:
    if value:
        return str(value).rstrip("/")
    environment = env or os.environ
    env_base = environment.get("SMARTTABLE_API_URL") or environment.get("AUTOTOUCH_API_URL")
    if env_base:
        return str(env_base).rstrip("/")
    cfg = load_config_fn()
    cfg_base = cfg.get("base_url")
    if cfg_base:
        return str(cfg_base).rstrip("/")
    return default_api_url.rstrip("/")

