"""
Module: telemetry
Description: Opt-in anonymous usage telemetry for the Huitzo CLI.

Implements:
    - docs/cli/reference.md#telemetry
    - docs/architecture/security.md#telemetry

Telemetry is opt-in only. On first CLI run, the user is prompted to
opt in or out. The preference is stored in ~/.config/huitzo/config.yaml
as `telemetry: true|false`. Telemetry can be disabled at any time via
`huitzo config set telemetry false`.
"""

from __future__ import annotations

import logging
import platform
import sys
import threading
import time
from types import TracebackType

import httpx

from huitzo_cli.config import ConfigManager
from huitzo_cli.version import get_version

logger = logging.getLogger(__name__)

_KNOWN_COMMANDS = frozenset(
    {
        "login",
        "logout",
        "init",
        "dev",
        "build",
        "publish",
        "install",
        "run",
        "test",
        "validate",
        "config",
        "secrets",
        "docs",
        "dashboard",
        "list",
    }
)


def is_telemetry_enabled(config: ConfigManager) -> bool:
    """Check if telemetry is enabled in config."""
    return config.get("telemetry", False) is True


def is_telemetry_configured(config: ConfigManager) -> bool:
    """Check if user has been asked about telemetry (value is set, not None)."""
    return config.get("telemetry") is not None


def prompt_telemetry_opt_in(config: ConfigManager) -> None:
    """Prompt user to opt in to telemetry on first run.

    Only prompts if telemetry setting has not been configured yet.
    Non-interactive environments (no TTY) default to disabled.
    """
    if is_telemetry_configured(config):
        return

    if not sys.stdin.isatty():
        config.set("telemetry", False)
        return

    try:
        print()
        print("Help improve Huitzo by sharing anonymous usage data?")
        print("This includes: command names, durations, success/failure, Python version, OS.")
        print("No personal data, API keys, or command arguments are collected.")
        print()
        answer = input("Enable anonymous telemetry? (y/n): ").strip().lower()
        enabled = answer in ("y", "yes")
        config.set("telemetry", enabled)
        if enabled:
            print("Telemetry enabled. Disable anytime: huitzo config set telemetry false")
        else:
            print("Telemetry disabled.")
        print()
    except (EOFError, KeyboardInterrupt):
        config.set("telemetry", False)


def send_telemetry(
    config: ConfigManager,
    command: str,
    duration_ms: int,
    success: bool,
) -> None:
    """Send telemetry data to the Huitzo API.

    Validates the command string against a known allowlist to prevent
    accidental leakage of arguments containing secrets or API keys.
    Runs in a background thread to avoid blocking the CLI.
    Silently ignores all errors — telemetry must never break user flows.
    """
    if not is_telemetry_enabled(config):
        return

    # Validate command against allowlist — reject strings with spaces or unknown commands
    if command not in _KNOWN_COMMANDS:
        logger.debug("Telemetry command rejected (not in allowlist): %r", command)
        return

    api_url = config.get("api_url", "https://api.huitzo.ai")

    def _post() -> None:
        try:
            httpx.post(
                f"{api_url}/api/v1/telemetry",
                json={
                    "command": command,
                    "duration_ms": duration_ms,
                    "success": success,
                    "python_version": platform.python_version(),
                    "os": sys.platform,
                    "cli_version": get_version(),
                },
                timeout=5.0,
            )
        except Exception:
            pass  # Never fail on telemetry

    thread = threading.Thread(target=_post, daemon=True)
    thread.start()


class TelemetryTimer:
    """Context manager for timing CLI commands and sending telemetry."""

    def __init__(self, config: ConfigManager, command_name: str) -> None:
        self.config = config
        self.command_name = command_name
        self._start: float = 0
        self.success = True

    def __enter__(self) -> TelemetryTimer:
        self._start = time.perf_counter()
        return self

    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None:
        elapsed_ms = int((time.perf_counter() - self._start) * 1000)
        self.success = exc_type is None
        send_telemetry(self.config, self.command_name, elapsed_ms, self.success)
        return None  # Don't suppress exceptions
