#!/usr/bin/env python3
"""Privacy-safe, evidence-qualified CARBON activity statistics."""

from __future__ import annotations

import argparse
import datetime as dt
import json
import math
import os
import re
import tempfile
from collections import Counter, defaultdict
from pathlib import Path
from typing import Any


SCHEMA = "carbon.stats/v1"
EVENT_SCHEMA = "carbon.stats-event/v1"
ACTIVITIES = {
    "planning", "discovery", "test-creation", "execution", "evidence-analysis",
    "issue-triage", "fix", "re-test", "reporting", "other",
}
SEVERITY_ORDER = {"critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4, "unknown": 5}
TERMINAL_TEST_STATUSES = {"passed", "failed", "blocked", "skipped", "canceled", "cancelled"}
FIXED_STATUSES = {"fixed", "resolved", "verified", "closed", "remediated"}
REPORT_PATTERN = re.compile(r"^(\d{8}T\d{6}Z)-(.+)-[0-9a-f]{4}\.html$")
SUPPORT_REPORTS = ("wcag-2-2", "accessibility-conformance-report")
TOKEN_FIELDS = ("inputTokens", "outputTokens", "cachedInputTokens", "reasoningTokens", "totalTokens")
MAX_JSON_BYTES = 25_000_000
MAX_EVENT_ROWS = 100_000
LOAD_GAPS: Counter[str] = Counter()


def utc_now() -> str:
    return dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")


def safe_number(value: Any, *, minimum: float = 0.0) -> float:
    if isinstance(value, bool):
        return 0.0
    try:
        number = float(value)
    except (TypeError, ValueError):
        return 0.0
    return number if math.isfinite(number) and number >= minimum else 0.0


def safe_int(value: Any) -> int:
    return int(safe_number(value))


def load_json(path: Path, fallback: Any) -> Any:
    try:
        if path.stat().st_size > MAX_JSON_BYTES:
            LOAD_GAPS["oversized-json-artifact"] += 1
            return fallback
        return json.loads(path.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError):
        return fallback


def load_jsonl(path: Path) -> list[dict[str, Any]]:
    rows: list[dict[str, Any]] = []
    try:
        handle = path.open("r", encoding="utf-8")
    except OSError:
        return rows
    with handle:
        for index, line in enumerate(handle):
            if index >= MAX_EVENT_ROWS:
                LOAD_GAPS["event-row-limit"] += 1
                break
            try:
                value = json.loads(line)
            except json.JSONDecodeError:
                continue
            if isinstance(value, dict):
                rows.append(value)
    return rows


def append_event(root: Path, event: dict[str, Any]) -> Path:
    path = root / ".carbon" / "stats" / "events.jsonl"
    path.parent.mkdir(parents=True, exist_ok=True)
    payload = {"schema": EVENT_SCHEMA, "at": utc_now(), **event}
    with path.open("a", encoding="utf-8") as handle:
        handle.write(json.dumps(payload, ensure_ascii=False, separators=(",", ":")) + "\n")
    os.chmod(path, 0o600)
    return path


def parse_time(value: Any) -> dt.datetime | None:
    if not isinstance(value, str) or not value.strip():
        return None
    try:
        return dt.datetime.fromisoformat(value.strip().replace("Z", "+00:00"))
    except ValueError:
        return None


def elapsed_seconds(start: Any, finish: Any) -> float:
    left, right = parse_time(start), parse_time(finish)
    if left is None or right is None or right < left:
        return 0.0
    return (right - left).total_seconds()


def compact_number(value: int | float | None) -> str:
    if value is None:
        return "NOT MEASURED"
    number = float(value)
    if number >= 1_000_000:
        return f"{number / 1_000_000:.2f}M"
    if number >= 1_000:
        return f"{number / 1_000:.1f}K"
    if number.is_integer():
        return f"{int(number):,}"
    return f"{number:,.2f}"


def dollars(value: float | None) -> str:
    return "NOT MEASURED" if value is None else f"${value:,.2f}"


def normalize_command(value: Any) -> str:
    command = str(value or "").strip().lstrip("$/")
    if not command:
        return ""
    command = command.split()[0].replace("_", "-")
    return command[:120]


def report_commands(carbon: Path) -> tuple[Counter[str], list[str]]:
    counts: Counter[str] = Counter()
    times: list[str] = []
    directory = carbon / "reports" / "commands"
    if not directory.is_dir():
        return counts, times
    for path in directory.glob("*.html"):
        match = REPORT_PATTERN.match(path.name)
        if not match:
            continue
        command = match.group(2)
        if command.startswith(SUPPORT_REPORTS):
            continue
        counts[command] += 1
        times.append(match.group(1))
    return counts, times


def command_stats(carbon: Path, events: list[dict[str, Any]]) -> dict[str, Any]:
    reports, timestamps = report_commands(carbon)
    journey = load_json(carbon / "workspace" / "journey.json", {})
    journey_counts = Counter()
    if isinstance(journey, dict) and isinstance(journey.get("commands"), dict):
        for raw, detail in journey["commands"].items():
            command = normalize_command(raw)
            if command and isinstance(detail, dict):
                journey_counts[command] = safe_int(detail.get("count"))
                if detail.get("firstRunAt"):
                    timestamps.append(str(detail["firstRunAt"]))
                if detail.get("lastRunAt"):
                    timestamps.append(str(detail["lastRunAt"]))
    ledger_counts: Counter[str] = Counter()
    for event in events:
        if event.get("kind") == "command":
            command = normalize_command(event.get("command"))
            if command:
                ledger_counts[command] += 1
                timestamps.append(str(event.get("at") or ""))
    commands = set(reports) | set(journey_counts) | set(ledger_counts)
    # Old report files and new content-free events often describe the same command.
    # The largest source count avoids double-counting while retaining older history.
    combined = Counter({command: max(reports[command], journey_counts[command], ledger_counts[command]) for command in commands})
    frequency = [{"command": command, "count": count} for command, count in combined.most_common()]
    active_days = sorted({parsed.date().isoformat() for value in timestamps if (parsed := parse_time(value))})
    longest_streak = 0
    current_streak = 0
    if active_days:
        days = {dt.date.fromisoformat(value) for value in active_days}
        previous: dt.date | None = None
        running = 0
        for day in sorted(days):
            running = running + 1 if previous and day == previous + dt.timedelta(days=1) else 1
            longest_streak = max(longest_streak, running)
            previous = day
        cursor = dt.datetime.now(dt.timezone.utc).date()
        while cursor in days:
            current_streak += 1
            cursor -= dt.timedelta(days=1)
    return {
        "total": sum(combined.values()),
        "unique": len(combined),
        "frequency": frequency,
        "top": frequency[0] if frequency else None,
        "activeDays": len(active_days),
        "longestObservedStreakDays": longest_streak,
        "currentStreakDays": current_streak,
        "sources": {"commandReports": sum(reports.values()), "workspaceJourney": sum(journey_counts.values()), "statsLedger": sum(ledger_counts.values())},
    }


def run_stats(carbon: Path) -> tuple[dict[str, Any], list[dict[str, Any],], list[dict[str, Any]]]:
    counts = Counter()
    findings: list[dict[str, Any]] = []
    signals: list[dict[str, Any]] = []
    durations = 0.0
    run_count = 0
    for path in sorted((carbon / "runs").glob("*/run.json")) if (carbon / "runs").is_dir() else []:
        state = load_json(path, {})
        if not isinstance(state, dict):
            continue
        run_count += 1
        durations += elapsed_seconds(state.get("startedAt"), state.get("finishedAt"))
        tests = state.get("tests") if isinstance(state.get("tests"), list) else []
        for test in tests:
            if not isinstance(test, dict):
                continue
            status = str(test.get("status") or "planned").lower()
            counts[status] += 1
            if status in TERMINAL_TEST_STATUSES or safe_int(test.get("attempts")) > 0:
                counts["executed"] += 1
            durations += elapsed_seconds(test.get("startedAt"), test.get("finishedAt")) if not state.get("finishedAt") else 0
        raw_findings = state.get("findings") if isinstance(state.get("findings"), list) else []
        for item in raw_findings:
            if not isinstance(item, dict):
                continue
            finding = dict(item)
            finding["runId"] = str(state.get("runId") or path.parent.name)
            finding["severity"] = str(finding.get("severity") or "unknown").lower()
            finding["status"] = str(finding.get("status") or finding.get("resolution") or "open").lower()
            findings.append(finding)
        manifest = load_json(path.parent / "evidence" / "manifest.json", {})
        manifest_findings = manifest.get("issues") if isinstance(manifest, dict) and isinstance(manifest.get("issues"), list) else []
        for item in manifest_findings:
            if not isinstance(item, dict):
                continue
            finding = dict(item)
            finding["runId"] = str(state.get("runId") or path.parent.name)
            finding["severity"] = str(finding.get("severity") or "unknown").lower()
            finding["status"] = str(finding.get("status") or finding.get("resolution") or "open").lower()
            # Evidence manifests may include positive capture/redaction signals.
            # Those make the evidence trail stronger, but they are not product
            # issues and must not inflate severity or failure-yield totals.
            if str(finding.get("confidence") or "").lower() == "observed" or str(finding.get("id") or "").upper().startswith("SIG-"):
                signals.append(finding)
            else:
                findings.append(finding)
    return {
        "runs": run_count,
        "tests": dict(counts),
        "observedDurationSeconds": round(durations, 2),
        "signals": len(signals),
    }, findings, signals


def created_test_stats(carbon: Path) -> dict[str, int]:
    ids: set[str] = set()
    intent = load_json(carbon / "tests" / "intent-tests.json", {})
    intent_tests = intent.get("tests") if isinstance(intent, dict) and isinstance(intent.get("tests"), list) else []
    for index, test in enumerate(intent_tests):
        if isinstance(test, dict):
            ids.add(str(test.get("id") or f"intent-{index}"))
    regression = load_json(carbon / "framework" / "regression-suite.json", {})
    regression_tests = regression.get("tests") if isinstance(regression, dict) and isinstance(regression.get("tests"), list) else []
    for index, test in enumerate(regression_tests):
        if isinstance(test, dict):
            ids.add(str(test.get("id") or f"regression-{index}"))
    return {"total": len(ids), "intent": len(intent_tests), "regression": len(regression_tests)}


def evidence_stats(carbon: Path) -> dict[str, int]:
    totals = Counter()
    runs = carbon / "runs"
    if not runs.is_dir():
        return dict(totals)
    for manifest_path in runs.glob("*/evidence/manifest.json"):
        manifest = load_json(manifest_path, {})
        if not isinstance(manifest, dict):
            continue
        pages = manifest.get("pages") if isinstance(manifest.get("pages"), list) else []
        issues = manifest.get("issues") if isinstance(manifest.get("issues"), list) else []
        totals["pages"] += len(pages)
        totals["issues"] += len(issues)
        for page in pages:
            if not isinstance(page, dict):
                continue
            artifacts = page.get("artifacts") if isinstance(page.get("artifacts"), list) else []
            totals["artifacts"] += len(artifacts)
            totals["screenshots"] += sum(1 for item in artifacts if isinstance(item, dict) and str(item.get("channel") or item.get("kind") or "").lower() == "screenshot")
    return dict(totals)


def usage_stats(events: list[dict[str, Any]], rates: list[dict[str, Any]]) -> dict[str, Any]:
    activity: dict[str, Counter[str]] = defaultdict(Counter)
    models: dict[tuple[str, str, str], Counter[str]] = defaultdict(Counter)
    measured_records = 0
    token_records = 0
    explicit_cost = 0.0
    cost_records = 0
    rate_map = {str(row.get("model")): row for row in rates if isinstance(row, dict) and row.get("model")}
    calculated_cost = 0.0
    calculated_records = 0
    for event in events:
        if event.get("kind") != "usage":
            continue
        measured_records += 1
        has_token_counter = any(field in event for field in TOKEN_FIELDS)
        if has_token_counter:
            token_records += 1
        name = str(event.get("activity") or "other")
        if name not in ACTIVITIES:
            name = "other"
        bucket = activity[name]
        for field in TOKEN_FIELDS:
            bucket[field] += safe_int(event.get(field))
        if has_token_counter:
            bucket["tokenRecords"] += 1
        bucket["durationSeconds"] += safe_number(event.get("durationSeconds"))
        bucket["testsCreated"] += safe_int(event.get("testsCreated"))
        bucket["testsExecuted"] += safe_int(event.get("testsExecuted"))
        bucket["issuesFound"] += safe_int(event.get("issuesFound"))
        bucket["issuesFixed"] += safe_int(event.get("issuesFixed"))
        cost = event.get("costUsd")
        if cost is not None:
            value = safe_number(cost)
            bucket["costMicros"] += round(value * 1_000_000)
            bucket["costRecords"] += 1
            explicit_cost += value
            cost_records += 1
        provider = str(event.get("provider") or "not supplied")[:80]
        model = str(event.get("model") or "not supplied")[:120]
        level = str(event.get("modelLevel") or "not supplied")[:80]
        model_bucket = models[(provider, model, level)]
        model_bucket["records"] += 1
        for field in TOKEN_FIELDS:
            model_bucket[field] += safe_int(event.get(field))
        if has_token_counter:
            model_bucket["tokenRecords"] += 1
        rate = rate_map.get(model)
        if cost is None and rate and any(field in event for field in ("inputTokens", "outputTokens", "cachedInputTokens")):
            input_cost = safe_int(event.get("inputTokens")) * safe_number(rate.get("inputPerMillionUsd")) / 1_000_000
            output_cost = safe_int(event.get("outputTokens")) * safe_number(rate.get("outputPerMillionUsd")) / 1_000_000
            cached_cost = safe_int(event.get("cachedInputTokens")) * safe_number(rate.get("cachedInputPerMillionUsd")) / 1_000_000
            value = input_cost + output_cost + cached_cost
            bucket["costMicros"] += round(value * 1_000_000)
            bucket["costRecords"] += 1
            calculated_cost += value
            calculated_records += 1
    activity_rows = []
    totals = Counter()
    for name, values in sorted(activity.items(), key=lambda row: row[1]["totalTokens"], reverse=True):
        row = {"activity": name, **dict(values), "costUsd": round(values["costMicros"] / 1_000_000, 6) if values["costRecords"] else None}
        row.pop("costMicros", None)
        activity_rows.append(row)
        totals.update(values)
    model_rows = [{"provider": key[0], "model": key[1], "modelLevel": key[2], **dict(value)} for key, value in sorted(models.items(), key=lambda row: row[1]["totalTokens"], reverse=True)]
    total_cost = explicit_cost + calculated_cost if cost_records or calculated_records else None
    return {
        "measured": measured_records > 0,
        "tokensMeasured": token_records > 0,
        "records": measured_records,
        "tokens": {field: totals[field] for field in TOKEN_FIELDS},
        "totalCostUsd": round(total_cost, 6) if total_cost is not None else None,
        "costBasis": "explicit usage cost" if cost_records and not calculated_records else "configured model rates" if calculated_records and not cost_records else "explicit usage cost plus configured rates" if cost_records and calculated_records else "not measured",
        "activities": activity_rows,
        "models": model_rows,
    }


def normalized_baseline(raw: Any) -> dict[str, Any]:
    value = raw if isinstance(raw, dict) else {}
    rates = value.get("modelRates") if isinstance(value.get("modelRates"), list) else []
    return {
        "manualTestCreationMinutes": safe_number(value.get("manualTestCreationMinutes")),
        "manualTestExecutionMinutes": safe_number(value.get("manualTestExecutionMinutes")),
        "manualIssueTriageMinutes": safe_number(value.get("manualIssueTriageMinutes")),
        "manualFixVerificationMinutes": safe_number(value.get("manualFixVerificationMinutes")),
        "loadedHourlyRateUsd": safe_number(value.get("loadedHourlyRateUsd")),
        "modelRates": rates,
    }


def savings_estimate(baseline: dict[str, Any], created: int, executed: int, issues: int, fixed: int, usage: dict[str, Any], run_duration: float) -> dict[str, Any]:
    required = ("manualTestCreationMinutes", "manualTestExecutionMinutes", "manualIssueTriageMinutes", "manualFixVerificationMinutes", "loadedHourlyRateUsd")
    missing = [field for field in required if baseline[field] <= 0]
    if missing:
        return {"available": False, "label": "NOT ESTIMATED", "missing": missing, "basis": "No traditional-testing baseline was supplied. CARBON does not invent labor rates or productivity assumptions."}
    traditional_minutes = (
        created * baseline["manualTestCreationMinutes"]
        + executed * baseline["manualTestExecutionMinutes"]
        + issues * baseline["manualIssueTriageMinutes"]
        + fixed * baseline["manualFixVerificationMinutes"]
    )
    usage_duration = sum(safe_number(row.get("durationSeconds")) for row in usage["activities"])
    carbon_minutes = max(usage_duration, run_duration) / 60
    saved_minutes = max(0.0, traditional_minutes - carbon_minutes)
    labor_value = saved_minutes / 60 * baseline["loadedHourlyRateUsd"]
    net_value = labor_value - safe_number(usage.get("totalCostUsd"))
    return {
        "available": True,
        "label": "SCENARIO ESTIMATE",
        "traditionalMinutes": round(traditional_minutes, 2),
        "carbonObservedMinutes": round(carbon_minutes, 2),
        "timeSavedMinutes": round(saved_minutes, 2),
        "laborValueUsd": round(labor_value, 2),
        "netValueUsd": round(net_value, 2),
        "assumptions": {field: baseline[field] for field in required},
        "basis": "Illustrative comparison using user-supplied minutes per activity and loaded hourly rate; it is not audited ROI.",
    }


def fixed_keys(events: list[dict[str, Any]], findings: list[dict[str, Any]]) -> set[str]:
    keys = set()
    for event in events:
        if event.get("kind") == "issue-fixed" and event.get("verified") is True:
            keys.add(f"{event.get('runId') or ''}:{event.get('findingId') or ''}")
    for finding in findings:
        if str(finding.get("status") or "").lower() in FIXED_STATUSES:
            keys.add(f"{finding.get('runId') or ''}:{finding.get('id') or ''}")
    return keys


def report_payload(stats: dict[str, Any]) -> dict[str, Any]:
    commands, runs, created, usage = stats["commands"], stats["runs"], stats["testsCreated"], stats["usage"]
    executed = safe_int(runs["tests"].get("executed"))
    issues = stats["issues"]
    savings = stats["savings"]
    top = commands.get("top") or {}
    metrics = [
        {"label": "Commands", "value": compact_number(commands["total"]), "detail": f"{commands['unique']} distinct workflows", "tone": "neutral", "icon": "cycle"},
        {"label": "Tests created", "value": compact_number(created["total"]), "detail": f"{created['intent']} intent · {created['regression']} regression", "tone": "good", "icon": "tests"},
        {"label": "Tests executed", "value": compact_number(executed), "detail": f"{runs['runs']} durable runs", "tone": "good", "icon": "execution"},
        {"label": "Issues found", "value": compact_number(issues["found"]), "detail": f"{issues['critical']} critical · {issues['high']} high", "tone": "risk" if issues["critical"] or issues["high"] else "neutral", "icon": "findings"},
        {"label": "Evidence signals", "value": compact_number(runs.get("signals")), "detail": "Observed capture or safety signals; not product issues", "tone": "neutral", "icon": "evidence"},
        {"label": "Fixes verified", "value": compact_number(issues["fixed"]), "detail": "Only explicit, verified fix records count", "tone": "good", "icon": "confidence"},
    ]
    if usage["tokensMeasured"]:
        metrics.append({"label": "Total tokens", "value": compact_number(usage["tokens"]["totalTokens"]), "detail": "Exact host-supplied counters only", "tone": "neutral", "icon": "budget"})
    if usage["totalCostUsd"] is not None:
        metrics.append({"label": "Observed AI cost", "value": dollars(usage["totalCostUsd"]), "detail": usage["costBasis"], "tone": "neutral", "icon": "budget"})
    if savings.get("available"):
        metrics.append({"label": "Time saved", "value": compact_number(savings.get("timeSavedMinutes")) + " min", "detail": savings["label"], "tone": "good", "icon": "quick"})
    activity_items = [{"title": row["activity"].replace("-", " ").title(), "detail": f"{compact_number(row.get('totalTokens'))} tokens · {dollars(row.get('costUsd'))} · {row.get('testsCreated', 0)} created · {row.get('testsExecuted', 0)} executed", "status": "completed"} for row in usage["activities"] if row.get("tokenRecords")]
    model_items = [{"title": f"{row['model']} · {row['modelLevel']}", "detail": f"{row['provider']} · {compact_number(row.get('totalTokens'))} tokens across {row.get('records', 0)} records", "status": "completed"} for row in usage["models"] if row.get("tokenRecords")]
    command_items = [{"title": f"/{row['command']}", "detail": f"{row['count']} execution{'s' if row['count'] != 1 else ''}", "status": "completed"} for row in commands["frequency"][:12]] or [{"title": "No command history found", "detail": "Command reporting will build a content-free frequency ledger going forward.", "status": "blocked"}]
    fixed_items = [{"title": item["title"], "detail": f"{item['severity'].upper()} · verified fixed · {item.get('id') or 'finding'}", "status": "completed"} for item in issues["biggestFixed"]]
    if not fixed_items:
        fixed_items = [{"title": "No verified saved issues yet", "detail": "CARBON found issues only when supported by run evidence and counts an issue as saved only after an explicit fix-verification record.", "status": "partial"}]
    cost_creation = stats["unitEconomics"]["costPerTestCreatedUsd"]
    cost_execution = stats["unitEconomics"]["costPerTestExecutedUsd"]
    sections = []
    if usage["tokensMeasured"]:
        sections.extend([
            {"title": "Where the tokens went", "intro": "Exact token and spend attribution by activity.", "icon": "budget", "items": activity_items},
            {"title": "Models and levels", "intro": "Exact provider, model, and level labels supplied by the host or agent.", "icon": "context", "items": model_items},
        ])
    fun_items = []
    for title, key in (("Failure yield", "failureYield"), ("Evidence density", "evidenceDensity"), ("Fix verification rate", "fixVerificationRate")):
        value = stats["funStats"][key]
        if value != "NOT MEASURED":
            fun_items.append({"title": title, "detail": value, "status": "completed"})
    if top:
        fun_items.append({"title": "Most productive command", "detail": f"/{top['command']}", "status": "completed"})

    sections.extend([
        {"title": "Command leaderboard", "intro": f"Top workflow: /{top.get('command', 'not measured')} · {commands['activeDays']} active day(s) · {commands['currentStreakDays']}-day current streak · {commands['longestObservedStreakDays']}-day longest streak.", "icon": "cycle", "items": command_items},
        {"title": "Biggest issues saved", "intro": "Only issues connected to an explicit verified fix are called saved.", "icon": "risk", "tone": "risk", "items": fixed_items},
    ])
    if fun_items:
        sections.append({"title": "Fun but useful signals", "intro": "Leverage, evidence density, and failure yield expose whether activity is producing decision-grade evidence.", "icon": "quick", "items": fun_items})
    unit_economics_items = []
    if cost_creation is not None:
        unit_economics_items.append({"title": "Cost per test created", "detail": dollars(cost_creation), "status": "completed"})
    if cost_execution is not None:
        unit_economics_items.append({"title": "Cost per test executed", "detail": dollars(cost_execution), "status": "completed"})
    if savings.get("available"):
        unit_economics_items.append({"title": "Estimated net value", "detail": dollars(savings.get("netValueUsd")), "status": "completed"})
    if unit_economics_items:
        sections.insert(len(sections) - 1, {"title": "Unit economics", "intro": "Observed attributable AI spend divided by matching recorded work; no blended guesses.", "icon": "budget", "items": unit_economics_items})
    report_gaps = []
    if not usage["tokensMeasured"]:
        report_gaps.append("Connect exact host usage counters to add token, model, level, and cost views.")
    if not savings.get("available"):
        report_gaps.append("Add a complete traditional-testing baseline to unlock a clearly labeled time-and-value scenario.")
    if issues["found"] and not issues["fixed"]:
        report_gaps.append("Verify a remediation against its original finding before it is counted as an issue saved.")
    if stats["issues"]["unmatchedFixRecords"]:
        report_gaps.append(f"Reconcile {stats['issues']['unmatchedFixRecords']} fix-verification record(s) with an available finding before they count toward verified fixes.")
    if report_gaps:
        sections.append({"title": "Unlock richer analytics", "intro": "These additions expand the dashboard; their absence is never treated as a zero.", "icon": "evidence", "tone": "risk", "bullets": report_gaps})
    activity_visuals = [
        {
            "label": row["activity"].replace("-", " ").title(),
            "value": row.get("totalTokens") if row.get("tokenRecords") else 0,
            "display": compact_number(row.get("totalTokens")) if row.get("tokenRecords") else "NOT MEASURED",
        }
        for row in usage["activities"]
        if row.get("tokenRecords")
    ]
    command_visuals = [
        {"label": f"/{row['command']}", "value": row["count"], "display": str(row["count"])}
        for row in commands["frequency"][:12]
    ]
    issue_visuals = []
    if runs["runs"] or issues["found"] or issues["fixed"]:
        issue_visuals = [
            {"label": "Found", "value": issues["found"], "display": str(issues["found"]), "tone": "risk" if issues["critical"] or issues["high"] else "neutral"},
            {"label": "Critical", "value": issues["critical"], "display": str(issues["critical"]), "tone": "risk"},
            {"label": "High", "value": issues["high"], "display": str(issues["high"]), "tone": "risk"},
            {"label": "Fixes verified", "value": issues["fixed"], "display": str(issues["fixed"])},
        ]
    economics_visuals: list[dict[str, Any]] = []
    if savings.get("available"):
        economics_visuals = [
            {"label": "Traditional minutes", "value": savings.get("traditionalMinutes", 0), "display": f"{savings.get('traditionalMinutes', 0):g} min"},
            {"label": "CARBON observed", "value": savings.get("carbonObservedMinutes", 0), "display": f"{savings.get('carbonObservedMinutes', 0):g} min"},
            {"label": "Scenario time saved", "value": savings.get("timeSavedMinutes", 0), "display": f"{savings.get('timeSavedMinutes', 0):g} min"},
        ]
    return {
        "command": "carbon-stats",
        "title": "What CARBON has actually accomplished",
        "summary": f"{commands['total']} commands, {created['total']} tests created, {executed} tests executed, {issues['found']} confirmed findings, {runs.get('signals', 0)} evidence signals, and {issues['fixed']} fixes explicitly verified.",
        "status": "completed",
        "scope": "Project-local CARBON activity and evidence",
        "metrics": metrics,
        "decision": {
            "label": "ACTIVITY",
            "headline": "Productivity is visible; shipping confidence is separate.",
            "summary": f"CARBON observed {commands['total']} commands, {executed} test executions, {issues['found']} confirmed findings, {runs.get('signals', 0)} evidence signals, and {issues['fixed']} explicitly verified fixes.",
            "basis": "This dashboard describes observed CARBON activity. It does not convert activity volume into a release decision.",
            "tone": "risk" if issues["critical"] or issues["high"] else "neutral",
        },
        "narrative": [
            {"value": "Understand CARBON effort and outcomes"},
            {"value": f"{issues['critical']} critical · {issues['high']} high", "tone": "risk" if issues["critical"] or issues["high"] else "neutral"},
            {"value": f"{executed} executions · {issues['fixed']} fixes verified"},
            {"value": "Activity measured; release confidence separate"},
            {"value": "Run /carbon-confidence with current evidence"},
        ],
        "statsVisuals": {
            "activity": activity_visuals,
            "commands": command_visuals,
            "issues": issue_visuals,
            "economics": economics_visuals,
        },
        "sections": sections,
        "findings": [],
        "evidenceBoundary": "Observed values come only from project-local .carbon command reports, journey state, durable runs, test libraries, evidence manifests, and content-free stats events. Seeded benchmark defects are excluded. Token, model, and cost values appear only when explicit host-supplied counters are available. Savings are labeled scenario estimates and appear only with a complete user-supplied baseline.",
        "confidenceMeter": {"basis": "This command measures CARBON activity; it does not assess whether the product is ready to ship.", "missingItems": []},
        "recommendedCommands": [
            {"command": "carbon-confidence", "prompt": "assess shipping confidence using the latest project evidence", "reason": "Activity volume is not product confidence; this examines the strength and gaps in the evidence."},
            {"command": "carbon-test", "prompt": "verify the highest-severity unresolved issue and its fix", "reason": "Turns an issue count into reproducible fix-verification evidence."},
            {"command": "carbon-auto", "prompt": "run a bounded test-fix-retest loop on the most failure-prone area", "reason": "Builds verified-fix and re-test evidence for the next stats snapshot."},
        ],
    }


def snapshot(root: Path, baseline_input: Any, record_current: bool) -> dict[str, Any]:
    LOAD_GAPS.clear()
    carbon = root / ".carbon"
    carbon.mkdir(parents=True, exist_ok=True)
    if record_current:
        append_event(root, {"kind": "command", "command": "carbon-stats", "status": "running"})
    events = load_jsonl(carbon / "stats" / "events.jsonl")
    baseline_file = load_json(carbon / "stats" / "baseline.json", {})
    baseline = normalized_baseline(baseline_input if isinstance(baseline_input, dict) and baseline_input else baseline_file)
    commands = command_stats(carbon, events)
    runs, findings, signals = run_stats(carbon)
    created = created_test_stats(carbon)
    evidence = evidence_stats(carbon)
    usage = usage_stats(events, baseline["modelRates"])
    fixes = fixed_keys(events, findings)
    unique_findings: dict[str, dict[str, Any]] = {}
    for finding in findings:
        key = f"{finding.get('runId') or ''}:{finding.get('id') or finding.get('title') or len(unique_findings)}"
        unique_findings[key] = finding
    severity = Counter(str(item.get("severity") or "unknown") for item in unique_findings.values())
    matched_fixes = fixes.intersection(unique_findings)
    biggest_fixed = sorted([item for key, item in unique_findings.items() if key in matched_fixes], key=lambda item: (SEVERITY_ORDER.get(str(item.get("severity")), 5), str(item.get("title") or "")))[:8]
    issue_stats = {"found": len(unique_findings), "fixed": len(matched_fixes), "unmatchedFixRecords": len(fixes - matched_fixes), "critical": severity["critical"], "high": severity["high"], "bySeverity": dict(severity), "biggestFixed": biggest_fixed}
    executed = safe_int(runs["tests"].get("executed"))
    savings = savings_estimate(baseline, created["total"], executed, issue_stats["found"], issue_stats["fixed"], usage, safe_number(runs["observedDurationSeconds"]))
    creation_rows = [row for row in usage["activities"] if row["activity"] == "test-creation"]
    execution_rows = [row for row in usage["activities"] if row["activity"] in {"execution", "re-test"}]
    creation_cost = sum(safe_number(row.get("costUsd")) for row in creation_rows)
    creation_count = sum(safe_int(row.get("testsCreated")) for row in creation_rows)
    execution_cost = sum(safe_number(row.get("costUsd")) for row in execution_rows)
    execution_count = sum(safe_int(row.get("testsExecuted")) for row in execution_rows)
    unit = {
        "costPerTestCreatedUsd": round(creation_cost / creation_count, 6) if creation_count and any(row.get("costUsd") is not None for row in creation_rows) else None,
        "costPerTestExecutedUsd": round(execution_cost / execution_count, 6) if execution_count and any(row.get("costUsd") is not None for row in execution_rows) else None,
    }
    artifacts = safe_int(evidence.get("artifacts"))
    fun = {
        "failureYield": f"{issue_stats['found'] / executed * 100:.1f} issues per 100 executed tests" if executed else "NOT MEASURED",
        "evidenceDensity": f"{artifacts / executed:.1f} artifacts per executed test" if executed else "NOT MEASURED",
        "fixVerificationRate": f"{issue_stats['fixed'] / issue_stats['found'] * 100:.1f}%" if issue_stats["found"] else "NOT MEASURED",
    }
    gaps = []
    if not usage["tokensMeasured"]:
        gaps.append("No exact host usage records: total tokens, activity attribution, models, levels, and AI cost are NOT MEASURED.")
    if not savings["available"]:
        gaps.append("No complete traditional-testing baseline: time and dollar savings are NOT ESTIMATED.")
    if issue_stats["found"] and not issue_stats["fixed"]:
        gaps.append("Issues exist, but no explicit verified-fix records connect remediation to the original findings.")
    if issue_stats["unmatchedFixRecords"]:
        gaps.append(f"{issue_stats['unmatchedFixRecords']} fix-verification record(s) do not match a currently available finding and are excluded from fixed totals.")
    if not executed:
        gaps.append("No executed tests were found in durable CARBON run state; planned tests do not count as execution.")
    if LOAD_GAPS:
        gaps.append("Some local statistics inputs exceeded safe processing limits and were excluded: " + ", ".join(f"{name}={count}" for name, count in sorted(LOAD_GAPS.items())) + ".")
    if not gaps:
        gaps.append("No major measurement gaps detected in the currently available CARBON artifacts; retain the assumptions and evidence boundary with any exported figure.")
    result = {
        "schema": SCHEMA,
        "generatedAt": utc_now(),
        "root": str(root),
        "commands": commands,
        "runs": runs,
        "testsCreated": created,
        "issues": issue_stats,
        "evidence": evidence,
        "usage": usage,
        "unitEconomics": unit,
        "savings": savings,
        "funStats": fun,
        "measurementGaps": gaps,
        "privacy": "Project-local and content-minimized. Stats events contain command names, counters, model metadata, durations, and finding references only; never prompts, responses, URLs, credentials, user identity, or source content.",
    }
    result["reportPayload"] = report_payload(result)
    return result


def record_usage(root: Path, args: argparse.Namespace) -> dict[str, Any]:
    activity = args.activity or "other"
    if activity not in ACTIVITIES:
        raise ValueError(f"activity must be one of: {', '.join(sorted(ACTIVITIES))}")
    raw_numeric = {field: getattr(args, re.sub(r"([A-Z])", lambda match: "_" + match.group(1).lower(), field)) for field in TOKEN_FIELDS}
    for field, value in raw_numeric.items():
        if value is not None and value < 0:
            raise ValueError(f"{field} cannot be negative")
    numeric = {field: safe_int(value) for field, value in raw_numeric.items() if value is not None}
    if "totalTokens" not in numeric and ("inputTokens" in numeric or "outputTokens" in numeric):
        numeric["totalTokens"] = numeric.get("inputTokens", 0) + numeric.get("outputTokens", 0)
    for label, value in (("durationSeconds", args.duration_seconds), ("costUsd", args.cost_usd), ("testsCreated", args.tests_created), ("testsExecuted", args.tests_executed), ("issuesFound", args.issues_found), ("issuesFixed", args.issues_fixed)):
        if value is not None and (not math.isfinite(float(value)) or value < 0):
            raise ValueError(f"{label} must be a finite non-negative number")
    payload = {
        "kind": "usage", "activity": activity, "command": normalize_command(args.command),
        "provider": str(args.provider or "")[:80], "model": str(args.model or "")[:120], "modelLevel": str(args.model_level or "")[:80],
        **numeric,
        "source": str(args.source or "host-supplied")[:80],
    }
    for field, value in (("durationSeconds", args.duration_seconds), ("costUsd", args.cost_usd), ("testsCreated", args.tests_created), ("testsExecuted", args.tests_executed), ("issuesFound", args.issues_found), ("issuesFixed", args.issues_fixed)):
        if value is not None:
            payload[field] = safe_number(value) if field in {"durationSeconds", "costUsd"} else safe_int(value)
    path = append_event(root, payload)
    return {"schema": SCHEMA, "recorded": True, "kind": "usage", "path": str(path), "contentFree": True, "usage": payload}


def record_fix(root: Path, args: argparse.Namespace) -> dict[str, Any]:
    if not args.finding_id:
        raise ValueError("finding-id is required")
    if not args.verified:
        raise ValueError("A fix counts only after explicit verification; pass --verified after re-testing the exact finding.")
    matches = []
    runs = root / ".carbon" / "runs"
    candidates = [runs / args.run_id / "run.json"] if args.run_id else sorted(runs.glob("*/run.json")) if runs.is_dir() else []
    for path in candidates:
        state = load_json(path, {})
        run_id = str(state.get("runId") or path.parent.name) if isinstance(state, dict) else path.parent.name
        findings = state.get("findings") if isinstance(state, dict) and isinstance(state.get("findings"), list) else []
        manifest = load_json(path.parent / "evidence" / "manifest.json", {})
        if isinstance(manifest, dict) and isinstance(manifest.get("issues"), list):
            findings = [*findings, *manifest["issues"]]
        if any(isinstance(item, dict) and str(item.get("id") or "") == str(args.finding_id) for item in findings):
            matches.append(run_id)
    if len(matches) != 1:
        raise ValueError("finding-id must resolve to exactly one available durable CARBON finding; supply run-id when IDs repeat")
    resolved_run_id = matches[0]
    payload = {"kind": "issue-fixed", "findingId": str(args.finding_id)[:200], "runId": resolved_run_id[:200], "verified": True, "verification": str(args.verification or "re-tested")[:120]}
    path = append_event(root, payload)
    return {"schema": SCHEMA, "recorded": True, "kind": "issue-fixed", "path": str(path), "contentFree": True, "fix": payload}


def configure(root: Path, raw: Any, confirm: bool) -> dict[str, Any]:
    if not confirm:
        raise ValueError("Saving a project statistics baseline requires explicit confirm=true after reviewing the assumptions.")
    baseline = normalized_baseline(raw)
    if any(baseline[field] <= 0 for field in ("manualTestCreationMinutes", "manualTestExecutionMinutes", "manualIssueTriageMinutes", "manualFixVerificationMinutes", "loadedHourlyRateUsd")):
        raise ValueError("Every labor baseline and the loaded hourly rate must be greater than zero.")
    path = root / ".carbon" / "stats" / "baseline.json"
    path.parent.mkdir(parents=True, exist_ok=True)
    with tempfile.NamedTemporaryFile("w", encoding="utf-8", dir=path.parent, delete=False) as handle:
        json.dump({"schema": "carbon.stats-baseline/v1", "updatedAt": utc_now(), **baseline}, handle, indent=2)
        handle.write("\n")
        temporary = Path(handle.name)
    os.replace(temporary, path)
    os.chmod(path, 0o600)
    return {"schema": SCHEMA, "configured": True, "path": str(path), "baseline": baseline, "warning": "Savings are scenario estimates, not audited ROI."}


def parser() -> argparse.ArgumentParser:
    root = argparse.ArgumentParser(description=__doc__)
    sub = root.add_subparsers(dest="action", required=True)
    summary = sub.add_parser("summary")
    summary.add_argument("--root", default=".")
    summary.add_argument("--baseline-json")
    summary.add_argument("--record-current-command", action=argparse.BooleanOptionalAction, default=True)
    usage = sub.add_parser("record-usage")
    usage.add_argument("--root", default=".")
    usage.add_argument("--activity", choices=sorted(ACTIVITIES), default="other")
    usage.add_argument("--command"); usage.add_argument("--provider"); usage.add_argument("--model"); usage.add_argument("--model-level")
    for field in ("input-tokens", "output-tokens", "cached-input-tokens", "reasoning-tokens", "total-tokens", "tests-created", "tests-executed", "issues-found", "issues-fixed"):
        usage.add_argument(f"--{field}", type=int)
    usage.add_argument("--duration-seconds", type=float); usage.add_argument("--cost-usd", type=float); usage.add_argument("--source")
    fixed = sub.add_parser("record-fix")
    fixed.add_argument("--root", default="."); fixed.add_argument("--finding-id", required=True); fixed.add_argument("--run-id"); fixed.add_argument("--verified", action="store_true"); fixed.add_argument("--verification")
    config = sub.add_parser("configure")
    config.add_argument("--root", default="."); config.add_argument("--baseline-json", required=True); config.add_argument("--confirm", action="store_true")
    return root


def main() -> int:
    args = parser().parse_args()
    root = Path(args.root).expanduser().resolve()
    if not root.is_dir():
        raise ValueError("root must be an existing project directory")
    if args.action == "summary":
        baseline = json.loads(args.baseline_json) if args.baseline_json else None
        result = snapshot(root, baseline, args.record_current_command)
    elif args.action == "record-usage":
        result = record_usage(root, args)
    elif args.action == "record-fix":
        result = record_fix(root, args)
    else:
        result = configure(root, json.loads(args.baseline_json), args.confirm)
    print(json.dumps(result, indent=2, ensure_ascii=False))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
