#!/usr/bin/env python3
"""Reproduce overall bullying point estimates from archived CDC 2025 national data.

The instrument numbers are Q26/Q27; CDC standardizes released-data variables to
Q23/Q24 and QN23/QN24. This script produces weighted point estimates, not published
CDC table values. Confidence intervals are intentionally not calculated.
"""
from pathlib import Path
from decimal import Decimal
import argparse
import csv
import hashlib
import json
import re

DATA_SHA256 = "7857d9419a43a27a5630baecf7513823c1bc93730fc2bc11989dc0e766a50c33"
SAS_SHA256 = "dbe4283e88139f3afe162258b70361d8dfba4882029c3f2a8cc024f9d07baeaf"


def derive(source_dir: Path):
    data_bytes = (source_dir / "2025_CDC_YRBS_NationalData.dat").read_bytes()
    sas_bytes = (source_dir / "2025_CDC_YRBS_NationalData_SASInput.sas").read_bytes()
    if hashlib.sha256(data_bytes).hexdigest() != DATA_SHA256:
        raise ValueError("National ASCII data differs from the verified CDC release")
    if hashlib.sha256(sas_bytes).hexdigest() != SAS_SHA256:
        raise ValueError("National SAS input differs from the verified CDC release")
    sas = sas_bytes.decode("utf-8")
    for label in ('QN23="Were bullied on school property"', 'QN24="Were electronically bullied"'):
        if label not in sas:
            raise ValueError("CDC variable-label correspondence is not confirmed")
    fields = {name: (int(position) - 1, int(width)) for position, name, width in
              re.findall(r"^@(\d+)\s+([A-Za-z0-9_]+)\s+\$?(\d+)(?:\.\d*)?", sas, re.MULTILINE)}

    def cell(row, variable):
        start, width = fields[variable]
        return row[start:start + width].strip()

    rows = data_bytes.decode("ascii").splitlines()
    if len(rows) != 10710:
        raise ValueError("Data row count does not match the technical report")
    weights = []
    for row in rows:
        value = cell(row, "WEIGHT")
        weight = Decimal(value) if "." in value else Decimal(value) / 10000
        if weight <= 0:
            raise ValueError("A record has a non-positive analysis weight")
        weights.append(weight)
    results = []
    for variable, raw_variable, question in [("QN23", "Q23", "Q26"), ("QN24", "Q24", "Q27")]:
        if any(cell(row, variable) != cell(row, raw_variable) for row in rows):
            raise ValueError("Raw and dichotomous bullying responses disagree")
        valid = [(row, weight) for row, weight in zip(rows, weights) if cell(row, variable) in ("1", "2")]
        yes = [(row, weight) for row, weight in valid if cell(row, variable) == "1"]
        base = sum(weight for row, weight in valid)
        total_yes = sum(weight for row, weight in yes)
        results.append({"variable": variable, "national_instrument_question": question,
                        "valid_unweighted_n": len(valid), "weighted_base": str(base),
                        "unweighted_yes_n": len(yes), "weighted_yes_total": str(total_yes),
                        "weighted_percent": str(total_yes / base * 100),
                        "confidence_interval": "",
                        "source": "Analyst-derived from CDC 2025 national public-use data; not a published YHIF table"})
    return {"records": len(rows), "weight_sum": str(sum(weights)), "measures": results}


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--source-dir", type=Path, default=Path(__file__).resolve().parent)
    parser.add_argument("--output-csv", type=Path)
    args = parser.parse_args()
    result = derive(args.source_dir)
    if args.output_csv:
        with args.output_csv.open("w", newline="") as output:
            writer = csv.DictWriter(output, fieldnames=list(result["measures"][0]))
            writer.writeheader()
            writer.writerows(result["measures"])
    print(json.dumps(result, indent=2))
