#!/usr/bin/env python3
import csv
import sys
from pathlib import Path

BASE = Path(__file__).resolve().parent
BACKLOG = BASE / "next_batch_backlog.csv"
PROTOCOL = BASE / "next_batch_test_protocol.md"
PLAN = BASE / "next_batch_plan.md"

REQUIRED_COLUMNS = [
    "priority",
    "company",
    "ticker",
    "period_coverage_target",
    "source_family",
    "primary_source_url",
    "metric_family",
    "expected_artifact",
    "validation_gate",
    "why_this_metric",
]

SELECTED = {"EQIX", "APLD", "CRWV"}
ALLOWED_METRICS = {
    "capex_actuals",
    "future_capacity_pipeline",
    "revenue_conversion",
    "secured_power",
    "lease_commitments",
    "rpo_backlog",
    "cloud_capacity_commitments",
}


def main():
    errors = []
    for path in (BACKLOG, PROTOCOL, PLAN):
        if not path.exists():
            errors.append(f"missing {path.name}")
    if errors:
        return report(errors)

    rows = list(csv.DictReader(BACKLOG.open(newline="", encoding="utf-8")))
    if not rows:
        errors.append("backlog has no rows")
        return report(errors)
    missing_cols = set(REQUIRED_COLUMNS) - set(rows[0])
    if missing_cols:
        errors.append(f"missing columns: {sorted(missing_cols)}")

    tickers = {row.get("ticker") for row in rows}
    if tickers != SELECTED:
        errors.append(f"expected selected tickers {sorted(SELECTED)}, got {sorted(tickers)}")

    metrics_by_ticker = {ticker: set() for ticker in SELECTED}
    for i, row in enumerate(rows, start=2):
        for col in REQUIRED_COLUMNS:
            if not row.get(col, "").strip():
                errors.append(f"row {i}: missing {col}")
        if not row.get("primary_source_url", "").startswith("https://"):
            errors.append(f"row {i}: primary_source_url must be https")
        if row.get("metric_family") not in ALLOWED_METRICS:
            errors.append(f"row {i}: unexpected metric_family {row.get('metric_family')}")
        if not row.get("expected_artifact", "").endswith(".csv"):
            errors.append(f"row {i}: expected_artifact must be a CSV")
        if not row.get("validation_gate", "").startswith("validate_"):
            errors.append(f"row {i}: validation_gate must name a validator")
        if row.get("ticker") in metrics_by_ticker:
            metrics_by_ticker[row["ticker"]].add(row.get("metric_family"))

    for ticker, metrics in metrics_by_ticker.items():
        if len(metrics) < 3:
            errors.append(f"{ticker}: expected at least 3 metric families, got {sorted(metrics)}")

    protocol = PROTOCOL.read_text(encoding="utf-8")
    plan = PLAN.read_text(encoding="utf-8")
    for ticker in SELECTED:
        if ticker not in protocol and ticker not in plan:
            errors.append(f"{ticker}: missing from protocol/plan")
    if "single task should run next" not in plan.lower():
        errors.append("plan must explicitly identify the single task to run next")

    return report(errors, rows=len(rows), companies=len(tickers))


def report(errors, rows=0, companies=0):
    if errors:
        print("Next batch backlog validation failed")
        for error in errors:
            print(f"- {error}")
        return 1
    print("Next batch backlog validation passed")
    print(f"- rows checked: {rows}")
    print(f"- companies selected: {companies}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
