"""System-managed server configuration for NexaOffice.

This layer is for company/server deployment.  Normal users should not need to
open Settings and manually enable networking.  When a deployment config exists,
NexaOffice reads it at startup, marks networking as system-managed, and can
connect automatically after login if the admin enabled it.

Supported config sources, highest priority first:
1. Environment variables: NEXA_SERVER_URL, NEXA_WORKSPACE_ID, NEXA_API_TOKEN
2. File beside the EXE/source: nexaoffice_server.json
3. Runtime data file: data/system_server_config.json

Deployment model:
- Normal users see connection status only.
- Admin/deployment files decide whether the client connects automatically.
- Missing config keeps the app fully local and offline.

No token is written to diagnostics or UI text.  The app remains offline when no
system config exists.
"""
from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Any

from .constants import APP_ROOT, DATA_DIR

SYSTEM_SERVER_CONFIG_NAMES = ("nexaoffice_server.json", "system_server_config.json")


def _as_bool(value: Any, default: bool = False) -> bool:
    if value is None:
        return default
    if isinstance(value, bool):
        return value
    text = str(value).strip().lower()
    if text in {"1", "true", "yes", "y", "on", "enabled"}:
        return True
    if text in {"0", "false", "no", "n", "off", "disabled"}:
        return False
    return default


def _clean_config(raw: dict[str, Any], source: str) -> dict[str, Any]:
    cfg = raw.get("server_sync", raw) if isinstance(raw, dict) else {}
    if not isinstance(cfg, dict):
        cfg = {}
    base_url = str(cfg.get("base_url") or cfg.get("server_url") or cfg.get("url") or "").strip()
    workspace_id = str(cfg.get("workspace_id") or cfg.get("company_id") or cfg.get("tenant_id") or cfg.get("organization_id") or "").strip()
    api_token = str(cfg.get("api_token") or cfg.get("token") or cfg.get("deployment_token") or "").strip()
    try:
        timeout = max(2, min(20, float(cfg.get("timeout", 4.5))))
    except Exception:
        timeout = 4.5
    try:
        retry_count = max(0, min(4, int(float(cfg.get("retry_count", 2)))))
    except Exception:
        retry_count = 2
    enabled = _as_bool(cfg.get("enabled"), bool(base_url))
    offline_mode = _as_bool(cfg.get("offline_mode"), not enabled)
    auto_connect = _as_bool(cfg.get("auto_connect"), enabled and not offline_mode and bool(base_url))
    sync_events_enabled = _as_bool(cfg.get("sync_events_enabled"), False)
    deployment_mode = str(cfg.get("deployment_mode") or cfg.get("mode") or ("server" if enabled and not offline_mode else "local")).strip().lower()
    if deployment_mode not in {"local", "server", "hybrid"}:
        deployment_mode = "server" if enabled and not offline_mode else "local"
    return {
        "enabled": enabled,
        "offline_mode": offline_mode,
        "base_url": base_url,
        "workspace_id": workspace_id,
        "api_token": api_token,
        "timeout": timeout,
        "retry_count": retry_count,
        "retry_backoff_base": max(0.10, min(0.36, float(cfg.get("retry_backoff_base", 0.16) or 0.16))),
        "health_cache_ttl_ok": max(20.0, min(120.0, float(cfg.get("health_cache_ttl_ok", 60.0) or 60.0))),
        "health_cache_ttl_fail": max(8.0, min(60.0, float(cfg.get("health_cache_ttl_fail", 18.0) or 18.0))),
        "allow_insecure_localhost": _as_bool(cfg.get("allow_insecure_localhost"), True),
        "auto_connect": auto_connect,
        "sync_events_enabled": sync_events_enabled,
        "deployment_mode": deployment_mode,
        "managed_by_system": True,
        "user_configurable": False,
        "config_source": source,
    }


def load_system_server_config() -> dict[str, Any] | None:
    env_url = os.environ.get("NEXA_SERVER_URL") or os.environ.get("NEXAOFFICE_SERVER_URL")
    if env_url:
        return _clean_config(
            {
                "enabled": os.environ.get("NEXA_SYNC_ENABLED", "1"),
                "offline_mode": os.environ.get("NEXA_OFFLINE_MODE", "0"),
                "base_url": env_url,
                "workspace_id": os.environ.get("NEXA_WORKSPACE_ID", ""),
                "api_token": os.environ.get("NEXA_API_TOKEN", ""),
                "timeout": os.environ.get("NEXA_SERVER_TIMEOUT", 4.5),
                "retry_count": os.environ.get("NEXA_RETRY_COUNT", 2),
                "retry_backoff_base": os.environ.get("NEXA_RETRY_BACKOFF_BASE", 0.16),
                "health_cache_ttl_ok": os.environ.get("NEXA_HEALTH_CACHE_TTL_OK", 60),
                "health_cache_ttl_fail": os.environ.get("NEXA_HEALTH_CACHE_TTL_FAIL", 18),
                "auto_connect": os.environ.get("NEXA_AUTO_CONNECT", "1"),
                "sync_events_enabled": os.environ.get("NEXA_SYNC_EVENTS", "0"),
                "deployment_mode": os.environ.get("NEXA_DEPLOYMENT_MODE", "server"),
            },
            "environment",
        )

    candidates = [APP_ROOT / name for name in SYSTEM_SERVER_CONFIG_NAMES]
    candidates.append(DATA_DIR / "system_server_config.json")
    for path in candidates:
        try:
            if path.exists() and path.is_file():
                data = json.loads(path.read_text(encoding="utf-8"))
                return _clean_config(data, str(path))
        except Exception:
            # Broken deployment config should never block local app startup.
            return {
                "enabled": False,
                "offline_mode": True,
                "base_url": "",
                "workspace_id": "",
                "api_token": "",
                "timeout": 4.5,
                "retry_count": 2,
                "retry_backoff_base": 0.16,
                "health_cache_ttl_ok": 60.0,
                "health_cache_ttl_fail": 18.0,
                "allow_insecure_localhost": True,
                "auto_connect": False,
                "sync_events_enabled": False,
                "deployment_mode": "local",
                "managed_by_system": True,
                "user_configurable": False,
                "config_source": f"invalid:{path}",
            }
    return None


def apply_system_server_config(settings: dict[str, Any]) -> dict[str, Any]:
    cfg = settings.setdefault("server_sync", {})
    if not isinstance(cfg, dict):
        cfg = {}
        settings["server_sync"] = cfg

    cfg.setdefault("managed_by_system", True)
    cfg.setdefault("user_configurable", False)
    cfg.setdefault("config_source", "not_configured")
    cfg.setdefault("auto_connect", False)
    cfg.setdefault("sync_events_enabled", False)
    cfg.setdefault("deployment_mode", "local")

    managed = load_system_server_config()
    if managed:
        cfg.update(managed)
    return cfg
