#!/usr/bin/env python3
"""Export JSON with mixed integer and float field values to CSV with an explicit
numeric-type column policy. Run locally with Python 3.12+.

Usage:
    python integer-float-to-csv.py fixture.json output.csv naive.csv evidence.json
"""
import json, csv, os, sys, hashlib
from pathlib import Path

SCHEMA = ["id", "quantity_kind", "quantity_json_type", "quantity_value", "quantity_json"]

def classify_number(val):
    """Classify a JSON number as integer or float based on its source token."""
    # In Python, json.loads produces int for integer literals and float for
    # floating-point literals. bool is a subclass of int, so check bool first.
    if isinstance(val, bool):
        kind = "boolean"
        json_type = "boolean"
    elif isinstance(val, int):
        kind = "integer"
        json_type = "number"
    elif isinstance(val, float):
        # float with integral value: 1.0 in source JSON
        if val.is_integer():
            kind = "float_integral"
        else:
            kind = "float_fractional"
        json_type = "number"
    elif isinstance(val, str):
        kind = "string"
        json_type = "string"
    elif val is None:
        kind = "null"
        json_type = "null"
    else:
        kind = type(val).__name__
        json_type = type(val).__name__
    return kind, json_type

def json_serialization(val):
    """Produce the exact JSON token for the value."""
    return json.dumps(val, ensure_ascii=False)

def export_explicit(source_path, csv_path, naive_path, evidence_path):
    # Read source
    with open(source_path, "r", encoding="utf-8") as f:
        raw_text = f.read()
    source_sha = hashlib.sha256(raw_text.encode("utf-8")).hexdigest()
    records = json.loads(raw_text)

    # Build explicit rows
    rows = []
    for rec in records:
        row = {col: "" for col in SCHEMA}
        row["id"] = rec["id"]
        val = rec["quantity"]
        kind, json_type = classify_number(val)
        row["quantity_kind"] = kind
        row["quantity_json_type"] = json_type
        row["quantity_value"] = json.dumps(val, ensure_ascii=False)
        row["quantity_json"] = json_serialization(val)
        rows.append(row)

    # Write explicit CSV (exclusive creation)
    with open(csv_path, "x", encoding="utf-8", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=SCHEMA)
        writer.writeheader()
        writer.writerows(rows)

    # Write naive CSV (single quantity column)
    naive_schema = ["id", "quantity"]
    naive_rows = []
    for rec in records:
        val = rec["quantity"]
        naive_rows.append({"id": rec["id"], "quantity": json.dumps(val, ensure_ascii=False)})
    with open(naive_path, "x", encoding="utf-8", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=naive_schema)
        writer.writeheader()
        writer.writerows(naive_rows)

    # Read-back verification
    with open(csv_path, "r", encoding="utf-8", newline="") as f:
        reader = csv.DictReader(f)
        csv_rows = list(reader)

    checks_passed = 0
    checks_total = 0
    for csv_row, src_rec in zip(csv_rows, records):
        val = src_rec["quantity"]
        exp_kind, exp_type = classify_number(val)
        exp_json = json_serialization(val)
        checks_total += 5
        assert csv_row["id"] == src_rec["id"], f"id mismatch in {src_rec['id']}"
        checks_passed += 1
        assert csv_row["quantity_kind"] == exp_kind, f"kind mismatch in {src_rec['id']}"
        checks_passed += 1
        assert csv_row["quantity_json_type"] == exp_type, f"type mismatch in {src_rec['id']}"
        checks_passed += 1
        assert csv_row["quantity_value"] == exp_json, f"value mismatch in {src_rec['id']}"
        checks_passed += 1
        assert csv_row["quantity_json"] == exp_json, f"json mismatch in {src_rec['id']}"
        checks_passed += 1

    # Evidence
    with open(csv_path, "rb") as f:
        csv_bytes = f.read()
    csv_sha = hashlib.sha256(csv_bytes).hexdigest()

    evidence = {
        "date": "2026-11-05",
        "python_version": sys.version,
        "source_sha256": source_sha,
        "source_bytes": len(raw_text.encode("utf-8")),
        "csv_sha256": csv_sha,
        "csv_bytes": len(csv_bytes),
        "csv_rows": len(csv_rows),
        "csv_columns": len(SCHEMA),
        "naive_bytes": os.path.getsize(naive_path),
        "checks_passed": checks_passed,
        "checks_total": checks_total,
        "records": [
            {
                "id": r["id"],
                "source_value": json_serialization(r["quantity"]),
                "source_python_type": type(r["quantity"]).__name__,
                "kind": classify_number(r["quantity"])[0],
                "json_type": classify_number(r["quantity"])[1],
            }
            for r in records
        ],
    }
    with open(evidence_path, "x", encoding="utf-8") as f:
        json.dump(evidence, f, indent=2)

    print(f"Export complete: {len(rows)} rows, {len(SCHEMA)} columns")
    print(f"CSV: {len(csv_bytes)} bytes, SHA-256: {csv_sha[:16]}...")
    print(f"Checks: {checks_passed}/{checks_total} passed")

if __name__ == "__main__":
    if len(sys.argv) != 5:
        print("Usage: python integer-float-to-csv.py fixture.json output.csv naive.csv evidence.json")
        sys.exit(1)
    export_explicit(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
