"""Anonymous CLI telemetry via PostHog.

Opt out by setting WORAI_DISABLE_TELEMETRY=1 in your environment.
Automatically disabled in test and CI environments.
"""

from __future__ import annotations

import json
import logging
import os
import sys
import uuid
from pathlib import Path
from typing import Any

_POSTHOG_API_KEY = "phc_RfhfjH7CwwfyrZ0pBfXN292VbgXgFJP9j6JEGQb2ALm"
_POSTHOG_HOST = "https://eu.i.posthog.com"

_NOTICE = (
    "worai collects anonymous usage data (commands run, errors) to help improve the tool.\n"
    "No personal data is collected. To opt out: export WORAI_DISABLE_TELEMETRY=1"
)

_log = logging.getLogger("worai.telemetry")


# ---------------------------------------------------------------------------
# State helpers
# ---------------------------------------------------------------------------


def _get_state_path(env: dict[str, str] | None = None) -> Path:
    from platformdirs import user_cache_dir

    if env is None:
        env = dict(os.environ)
    cache_home = env.get("XDG_CACHE_HOME")
    if cache_home:
        base = Path(cache_home).expanduser()
    else:
        base = Path(user_cache_dir("worai"))
    return base / "telemetry.json"


def _load_state(state_path: Path) -> dict[str, Any]:
    try:
        return json.loads(state_path.read_text(encoding="utf-8"))
    except (FileNotFoundError, OSError, json.JSONDecodeError):
        return {}


def _save_state(state_path: Path, state: dict[str, Any]) -> None:
    try:
        state_path.parent.mkdir(parents=True, exist_ok=True)
        state_path.write_text(json.dumps(state), encoding="utf-8")
    except OSError:
        pass


def _get_or_create_distinct_id(state_path: Path) -> str:
    state = _load_state(state_path)
    distinct_id = state.get("distinct_id")
    if isinstance(distinct_id, str) and distinct_id:
        return distinct_id
    distinct_id = str(uuid.uuid4())
    state["distinct_id"] = distinct_id
    _save_state(state_path, state)
    return distinct_id


# ---------------------------------------------------------------------------
# Opt-out / environment checks
# ---------------------------------------------------------------------------

_SKIP_ARGS = {"--help", "--install-completion", "--show-completion"}
_GLOBAL_FLAGS_WITH_VALUES = {"--config", "--profile", "--log-level", "--log-format"}


def is_telemetry_enabled(env: dict[str, str] | None = None) -> bool:
    if env is None:
        env = dict(os.environ)
    if env.get("PYTEST_CURRENT_TEST"):
        return False
    if env.get("CI") or env.get("GITHUB_ACTIONS"):
        return False
    if env.get("WORAI_DISABLE_TELEMETRY", "").strip().lower() in {"1", "true", "yes", "on"}:
        return False
    return True


def _should_show_notice() -> bool:
    if not is_telemetry_enabled():
        return False
    args = set(sys.argv[1:])
    if args & _SKIP_ARGS:
        return False
    return True


# ---------------------------------------------------------------------------
# First-run notice
# ---------------------------------------------------------------------------


def show_first_run_notice_if_needed(
    state_path: Path | None = None,
    env: dict[str, str] | None = None,
) -> None:
    if not _should_show_notice():
        return
    if state_path is None:
        state_path = _get_state_path(env)
    state = _load_state(state_path)
    if state.get("notice_shown"):
        return
    try:
        import typer
        typer.secho(_NOTICE, err=True, fg=typer.colors.BRIGHT_BLACK)
    except Exception:
        print(_NOTICE, file=sys.stderr)
    state["notice_shown"] = True
    _save_state(state_path, state)


# ---------------------------------------------------------------------------
# PostHog client (lazy, silenced)
# ---------------------------------------------------------------------------


def _init_posthog() -> Any:
    try:
        import posthog as _ph

        _ph.api_key = _POSTHOG_API_KEY
        _ph.host = _POSTHOG_HOST
        logging.getLogger("posthog").setLevel(logging.CRITICAL)
        return _ph
    except Exception:
        return None


_posthog = None
_state_path: Path | None = None
_distinct_id: str | None = None


def _ensure_initialized(env: dict[str, str] | None = None) -> bool:
    global _posthog, _state_path, _distinct_id
    if not is_telemetry_enabled(env):
        return False
    if _posthog is None:
        _posthog = _init_posthog()
    if _posthog is None:
        return False
    if _state_path is None:
        _state_path = _get_state_path(env)
    if _distinct_id is None:
        _distinct_id = _get_or_create_distinct_id(_state_path)
    return True


# ---------------------------------------------------------------------------
# Command extraction
# ---------------------------------------------------------------------------


def get_command_name(argv: list[str] | None = None) -> str:
    """Return the subcommand path from argv, stripping flags and their values."""
    if argv is None:
        argv = sys.argv
    positional: list[str] = []
    i = 1  # skip executable name
    while i < len(argv):
        arg = argv[i]
        if arg in _GLOBAL_FLAGS_WITH_VALUES:
            i += 2
            continue
        if arg.startswith("-"):
            i += 1
            continue
        positional.append(arg)
        i += 1
    return " ".join(positional) if positional else "unknown"


# ---------------------------------------------------------------------------
# Public capture API
# ---------------------------------------------------------------------------


def capture_command(command: str, version: str, env: dict[str, str] | None = None) -> None:
    if not _ensure_initialized(env):
        return
    try:
        _posthog.capture("command_invoked", distinct_id=_distinct_id, properties={"command": command, "version": version})
    except Exception:
        pass


def capture_error(
    command: str,
    version: str,
    error_type: str,
    env: dict[str, str] | None = None,
) -> None:
    if not _ensure_initialized(env):
        return
    try:
        _posthog.capture(
            "command_error",
            distinct_id=_distinct_id,
            properties={"command": command, "version": version, "error_type": error_type},
        )
    except Exception:
        pass


def flush(env: dict[str, str] | None = None) -> None:
    if not is_telemetry_enabled(env):
        return
    if _posthog is None:
        return
    try:
        _posthog.shutdown()
    except Exception:
        pass
