"""License configuration loader.

Supports two modes:
1. Explicit params passed to bootstrap(server_url=..., product_id=...)
2. Fallback: load from .cgt_license.json next to the app
"""

import json
import sys
from pathlib import Path


def _app_base_dir() -> Path:
    """Get the directory of the main script or exe."""
    if getattr(sys, "frozen", False):
        return Path(sys.executable).parent
    main_mod = sys.modules.get("__main__")
    if main_mod and hasattr(main_mod, "__file__") and main_mod.__file__:
        return Path(main_mod.__file__).resolve().parent
    return Path.cwd()


def _find_guard_dll(base: Path) -> str:
    """Auto-detect cgt_guard.dll next to the app."""
    for name in ("cgt_guard.dll", "cgt_guard.so", "libcgt_guard.so", "cgt_guard.dylib"):
        candidate = base / name
        if candidate.exists():
            return str(candidate)
    # Also check cwd
    if base != Path.cwd():
        for name in ("cgt_guard.dll", "cgt_guard.so", "libcgt_guard.so", "cgt_guard.dylib"):
            candidate = Path.cwd() / name
            if candidate.exists():
                return str(candidate)
    return str(base / "cgt_guard.dll")


def build_config(
    server_url: str,
    product_id: str,
    guard_dll: str | None = None,
    app_name: str | None = None,
    logo: str | None = None,
) -> dict:
    """Build config dict from explicit parameters.

    If guard_dll is not provided, auto-detects cgt_guard.dll next to the app.
    """
    base = _app_base_dir()

    if guard_dll:
        dll_path = Path(guard_dll)
        if not dll_path.is_absolute():
            dll_path = base / dll_path
        guard_dll = str(dll_path)
    else:
        guard_dll = _find_guard_dll(base)

    config = {
        "server_url": server_url,
        "product_id": product_id,
        "guard_dll": guard_dll,
    }

    if app_name:
        config["app_name"] = app_name
    if logo:
        logo_path = Path(logo)
        if not logo_path.is_absolute():
            logo_path = base / logo_path
        config["logo"] = str(logo_path)

    return config


def load_config() -> dict:
    """Load license config from .cgt_license.json (fallback mode).

    Returns dict with keys: server_url, product_id, guard_dll
    """
    base = _app_base_dir()
    config_path = base / ".cgt_license.json"
    if not config_path.exists():
        config_path = Path.cwd() / ".cgt_license.json"

    if not config_path.exists():
        raise FileNotFoundError(
            f"License config not found: {config_path}\n"
            "Either pass server_url and product_id to bootstrap(), "
            "or create .cgt_license.json next to your app with:\n"
            '{"server_url": "...", "product_id": "...", "guard_dll": "cgt_guard.dll"}'
        )

    with open(config_path, "r") as f:
        config = json.load(f)

    required_keys = ["server_url", "product_id"]
    for key in required_keys:
        if key not in config:
            raise ValueError(f"Missing required key '{key}' in {config_path}")

    # Resolve guard_dll (or auto-detect)
    if "guard_dll" in config:
        dll_path = Path(config["guard_dll"])
        if not dll_path.is_absolute():
            dll_path = config_path.parent / dll_path
        config["guard_dll"] = str(dll_path)
    else:
        config["guard_dll"] = _find_guard_dll(config_path.parent)

    # Resolve optional logo path
    if "logo" in config and config["logo"]:
        logo_path = Path(config["logo"])
        if not logo_path.is_absolute():
            logo_path = config_path.parent / logo_path
        config["logo"] = str(logo_path)

    return config
