"""Lightweight opt-in CLI telemetry."""

import logging
import os
import platform
import sys
import threading
import uuid

import httpx
from rich.prompt import Confirm

from . import __version__
from .config.settings import Settings, load_config, save_config

logger = logging.getLogger(__name__)

SENTRY_DSN = "https://8f0e573049ed813ca0879c0f5eda3a43@o4509726139219968.ingest.us.sentry.io/4509727575179264"


def _get_install_id() -> str:
    """Read or create a persistent anonymous install ID."""
    config = load_config()
    install_id = config.get("install_id", "")
    if install_id:
        return install_id
    install_id = str(uuid.uuid4())
    save_config({"install_id": install_id})
    return install_id


def _is_enabled() -> bool:
    """Check whether telemetry is enabled (env var then config)."""
    env = os.environ.get("GJALLA_TELEMETRY")
    if env is not None:
        return env not in ("0", "false", "no", "off")
    config = load_config()
    return config.get("telemetry") is True


def check_consent() -> None:
    """Prompt once for telemetry opt-in if the user hasn't decided yet."""
    env = os.environ.get("GJALLA_TELEMETRY")
    if env is not None:
        return  # env var takes precedence, skip prompt

    config = load_config()
    if "telemetry" in config:
        return  # already decided

    if not sys.stdin.isatty():
        return  # non-interactive — don't prompt, don't persist

    from .display.output import info
    info("The gjalla CLI does not use an LLM or process your code remotely.")

    try:
        enabled = Confirm.ask(
            "[bold]Help improve gjalla?[/bold] Send anonymous usage stats (command name, version, OS). No code or project data.",
            default=False,
        )
    except (EOFError, KeyboardInterrupt):
        enabled = False

    save_config({"telemetry": enabled})


def init_sentry() -> None:
    """Initialize Sentry error tracking if telemetry is opted-in.

    Gated behind the same telemetry consent as usage stats.
    No-op if disabled, no DSN configured, or sentry-sdk unavailable.
    """
    if not _is_enabled():
        return

    try:
        import sentry_sdk

        sentry_sdk.init(
            dsn=SENTRY_DSN,
            environment=os.environ.get("SENTRY_ENVIRONMENT", "production"),
            release=f"gjalla-cli@{__version__}",
            traces_sample_rate=0.1,
            send_default_pii=False,
            include_local_variables=False,
            attach_stacktrace=True,
            before_send=_sentry_before_send,
            max_breadcrumbs=20,
        )
        sentry_sdk.set_tag("service", "gjalla-cli")
        sentry_sdk.set_tag("os", platform.system())
        sentry_sdk.set_tag("python_version", platform.python_version())
    except Exception:
        pass  # silent degradation


def _sentry_before_send(event, hint):
    """Strip sensitive data from Sentry events."""
    sensitive_keys = ["password", "token", "key", "secret", "api_key", "authorization", "dsn"]

    def _scrub(data):
        if isinstance(data, dict):
            return {
                k: "[Filtered]" if any(s in k.lower() for s in sensitive_keys) else _scrub(v)
                for k, v in data.items()
            }
        if isinstance(data, list):
            return [_scrub(item) for item in data]
        return data

    return _scrub(event)


def track(command: str) -> None:
    """Fire-and-forget telemetry event. Silent on any failure."""
    if not _is_enabled():
        return

    settings = Settings.load()
    has_project = bool(settings.projects)

    event = {
        "install_id": _get_install_id(),
        "command": command or "unknown",
        "cli_version": __version__,
        "os": f"{platform.system()} {platform.release()}",
        "python_version": platform.python_version(),
        "has_project": has_project,
    }

    def _send() -> None:
        try:
            httpx.post(
                f"{settings.api_url}/api/cli/telemetry",
                json=event,
                timeout=2.0,
            )
        except Exception:
            pass

    t = threading.Thread(target=_send, daemon=True)
    t.start()
