#!/usr/bin/env bash
set -euo pipefail

ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
cd "$ROOT"

python3 - <<'PY'
import os
import pathlib
import re
import subprocess
import sys

failures = []
extra_go_files = {
    pathlib.Path(path)
    for path in os.environ.get("OBSERVABILITY_GUARDRAIL_EXTRA_GO_FILES", "").split(os.pathsep)
    if path and pathlib.Path(path).exists()
}

def fail(message):
    failures.append(message)

def tracked_go_files():
    output = subprocess.check_output(
        ["git", "ls-files", "--cached", "--others", "--exclude-standard", "*.go"],
        text=True,
    )
    paths = [
        pathlib.Path(line)
        for line in output.splitlines()
        if line
        and not line.endswith("_test.go")
        and not line.startswith("x/")
        and pathlib.Path(line).exists()
    ]
    paths.extend(extra_go_files)
    return paths

go_files = tracked_go_files()

def go_code_without_comments_and_literals(source):
    """Keep Go tokens while blanking comments and quoted/raw literals."""
    output = list(source)
    index = 0
    state = "code"
    quote = ""
    while index < len(source):
        current = source[index]
        following = source[index + 1] if index + 1 < len(source) else ""
        if state == "code":
            if current == "/" and following == "/":
                output[index] = output[index + 1] = " "
                index += 2
                state = "line_comment"
                continue
            if current == "/" and following == "*":
                output[index] = output[index + 1] = " "
                index += 2
                state = "block_comment"
                continue
            if current in {'"', "'", "`"}:
                quote = current
                output[index] = " "
                index += 1
                state = "raw_literal" if current == "`" else "quoted_literal"
                continue
        elif state == "line_comment":
            if current == "\n":
                state = "code"
            else:
                output[index] = " "
        elif state == "block_comment":
            if current == "*" and following == "/":
                output[index] = output[index + 1] = " "
                index += 2
                state = "code"
                continue
            if current != "\n":
                output[index] = " "
        elif state == "raw_literal":
            if current == quote:
                state = "code"
            if current != "\n":
                output[index] = " "
        else:
            if current == "\\" and index + 1 < len(source):
                output[index] = output[index + 1] = " "
                index += 2
                continue
            if current == quote:
                state = "code"
            if current != "\n":
                output[index] = " "
        index += 1
    return "".join(output)

raw_go_statement = re.compile(r"\bgo\s+")
managed_go_exemptions = {
    "internal/observability/logging/file_sink.go",  # Pipeline-owned flush ticker.
    "internal/observability/logging/managed.go",    # The single recovery wrapper.
}
for path in go_files:
    path_text = str(path)
    if (
        not (path in extra_go_files or path_text.startswith("internal/") or path_text.startswith("cmd/agentteam-server/") or path_text.startswith("cmd/agentteam-gateway-server/"))
        or
        path_text in managed_go_exemptions
        or "/testkit/" in path_text
        or path_text.startswith("cmd/agentteam-e2e-server/")
    ):
        continue
    if raw_go_statement.search(go_code_without_comments_and_literals(path.read_text())):
        fail(f"{path}: production goroutine roots must use logging.Go for panic logging and flush")

forbidden_metric_names = {
    "agentteam_space_messages_rows",
    "agentteam_space_messages_bytes",
    "agentteam_targeted_delivery_events_rows",
}
for path in go_files:
    text = path.read_text()
    for name in forbidden_metric_names:
        opts_name = r'Name:\s*"' + re.escape(name) + r'"'
        desc_name = r'prometheus\.NewDesc\s*\(\s*"' + re.escape(name) + r'"'
        if re.search(opts_name, text) or re.search(desc_name, text):
            fail(f"{path}: forbidden metric name {name}")

sql_fragment = re.compile(r"\b(SELECT\s+|COUNT\(|SUM\(|AVG\()")
for path in go_files:
    if not str(path).startswith("internal/observability/"):
        continue
    text = path.read_text()
    match = sql_fragment.search(text)
    if match:
        fail(f"{path}: observability package must not contain SQL fragment {match.group(1).strip()}")

otel_import = re.compile(r'"go\.opentelemetry\.io/[^"]+"')
for path in go_files:
    if str(path).startswith("internal/observability/"):
        continue
    text = path.read_text()
    if otel_import.search(text):
        fail(f"{path}: production OpenTelemetry imports must stay under internal/observability")

registry_hits = []
for path in go_files:
    text = path.read_text()
    for line_number, line in enumerate(text.splitlines(), start=1):
        if "prometheus.NewRegistry(" in line:
            registry_hits.append(f"{path}:{line_number}")
allowed_registry_hit = "internal/observability/observability.go"
if len(registry_hits) != 1 or not registry_hits[0].startswith(allowed_registry_hit + ":"):
    fail("prometheus.NewRegistry must appear exactly once in production code at "
         f"{allowed_registry_hit}; found {', '.join(registry_hits) or 'none'}")

metric_label_allowlist = {
    "agentteam_http_requests_total": {"method", "route", "status"},
    "agentteam_http_request_duration_seconds": {"method", "route", "status_class"},
    "agentteam_http_inflight": set(),
    "agentteam_http_panics_total": {"method", "route"},
    "agentteam_daemon_transport_requests_total": {"endpoint", "link_mode", "outcome", "fallback"},
    "agentteam_daemon_transport_request_duration_seconds": {"endpoint", "link_mode", "outcome"},
    "agentteam_daemon_transport_route_decisions_total": {"endpoint", "link_policy", "mode", "reason"},
    "agentteam_daemon_transport_elastic_events_total": {"event", "reason"},
    "agentteam_daemon_transport_elastic_pool": {"state"},
    "agentteam_daemon_transport_warm_events_total": {"origin", "profile", "warm_event", "reason"},
}
vec_pattern = re.compile(
    r"prometheus\.New(?:Histogram|Counter|Gauge)Vec\s*\(\s*"
    r"prometheus\.\w+Opts\s*\{(?P<opts>.*?)\}\s*,\s*"
    r"\[\]string\s*\{(?P<labels>.*?)\}",
    re.DOTALL,
)
name_pattern = re.compile(r'Name:\s*"([^"]+)"')
label_pattern = re.compile(r'"([^"]+)"')
for path in go_files:
    text = path.read_text()
    for match in vec_pattern.finditer(text):
        opts = match.group("opts")
        name_match = name_pattern.search(opts)
        if not name_match:
            fail(f"{path}: metric Vec missing literal Name")
            continue
        metric_name = name_match.group(1)
        if metric_name not in metric_label_allowlist:
            fail(f"{path}: metric Vec {metric_name} is not declared in specs/observability/metrics.md")
            continue
        labels = set(label_pattern.findall(match.group("labels")))
        expected = metric_label_allowlist[metric_name]
        if labels != expected:
            fail(f"{path}: metric Vec {metric_name} labels {sorted(labels)} must equal {sorted(expected)}")

if failures:
    for failure in failures:
        print(f"FAIL: {failure}", file=sys.stderr)
    sys.exit(1)

print("Observability guardrail passed.")
PY
