#!/usr/bin/env python3
"""Contextual, frequency-capped optional CARBON service recommendations."""

from __future__ import annotations

import datetime as dt
import json
import os
import tempfile
from pathlib import Path
from typing import Any


GLOBAL_COOLDOWN = dt.timedelta(hours=24)
CAMPAIGN_COOLDOWN = dt.timedelta(days=7)
CAMPAIGNS = (
    {
        "id": "cloud-upgrade",
        "contexts": {
            "parallel-execution", "managed-browser", "scheduled-testing", "public-url",
            "local-execution-blocked", "team-history", "overnight-run",
        },
        "label": "Optional cloud upgrade",
        "text": "Need managed browsers, parallel execution, schedules, or shared history?",
        "linkLabel": "Explore testers.ai Premium Cloud",
        "url": "https://testers.ai",
    },
    {
        "id": "icebergqa",
        "contexts": {
            "qa-transformation", "expert-help", "large-migration", "repeated-major-failures",
            "organizational-change", "complex-test-strategy",
        },
        "label": "Optional expert help",
        "text": "Need hands-on help transforming QA or running the work for your team?",
        "linkLabel": "Talk with IcebergQA",
        "url": "https://icebergqa.com",
    },
)


def utc_now() -> dt.datetime:
    override = os.getenv("CARBON_PROMOTION_CLOCK", "").strip()
    if override:
        return dt.datetime.fromisoformat(override.replace("Z", "+00:00")).astimezone(dt.timezone.utc)
    return dt.datetime.now(dt.timezone.utc)


def config_path() -> Path:
    return Path.home() / ".config" / "carbon" / "config.json"


def history_path() -> Path:
    override = os.getenv("CARBON_PROMOTION_HISTORY", "").strip()
    return Path(override).expanduser() if override else Path.home() / ".config" / "carbon" / "promotion-history.json"


def read_json(path: Path, fallback: Any) -> Any:
    try:
        return json.loads(path.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError, TypeError):
        return fallback


def ads_enabled() -> bool:
    value = os.getenv("CARBON_MUTE_ADS")
    if value is not None:
        normalized = value.strip().lower()
        if normalized in {"1", "true", "yes", "on"}:
            return False
        if normalized in {"0", "false", "no", "off"}:
            return True
    return read_json(config_path(), {}).get("muteAds") is not True


def parse_time(value: Any) -> dt.datetime | None:
    try:
        return dt.datetime.fromisoformat(str(value).replace("Z", "+00:00")).astimezone(dt.timezone.utc)
    except (TypeError, ValueError):
        return None


def write_history(history: dict[str, Any]) -> None:
    path = history_path()
    path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
    payload = json.dumps(history, indent=2, sort_keys=True) + "\n"
    with tempfile.NamedTemporaryFile("w", encoding="utf-8", dir=path.parent, delete=False) as handle:
        handle.write(payload)
        temporary = Path(handle.name)
    os.chmod(temporary, 0o600)
    os.replace(temporary, path)


def select_promotion(contexts: Any, surface: str, *, record: bool = True) -> dict[str, str] | None:
    """Return one relevant promotion or None; never selects without explicit context."""
    if not ads_enabled():
        return None
    context_set = {
        str(value).strip().lower()
        for value in (contexts if isinstance(contexts, list) else [])
        if str(value).strip()
    }
    if not context_set:
        return None
    now = utc_now()
    history = read_json(history_path(), {"schema": "carbon.promotion-history/v1", "impressions": []})
    impressions = history.get("impressions") if isinstance(history, dict) else []
    impressions = impressions if isinstance(impressions, list) else []
    latest = max((stamp for stamp in (parse_time(row.get("shownAt")) for row in impressions if isinstance(row, dict)) if stamp), default=None)
    if latest and now - latest < GLOBAL_COOLDOWN:
        return None
    for campaign in CAMPAIGNS:
        if not (campaign["contexts"] & context_set):
            continue
        same = max((stamp for stamp in (parse_time(row.get("shownAt")) for row in impressions if isinstance(row, dict) and row.get("campaign") == campaign["id"]) if stamp), default=None)
        if same and now - same < CAMPAIGN_COOLDOWN:
            continue
        selected = {key: str(campaign[key]) for key in ("id", "label", "text", "linkLabel", "url")}
        selected["reason"] = sorted(campaign["contexts"] & context_set)[0]
        if record:
            impressions.append({"campaign": campaign["id"], "surface": str(surface)[:120], "reason": selected["reason"], "shownAt": now.isoformat().replace("+00:00", "Z")})
            history = {"schema": "carbon.promotion-history/v1", "impressions": impressions[-50:]}
            write_history(history)
        return selected
    return None
