# /// script
# requires-python = ">=3.10"
# ///
# Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT
# https://thedataengineering.com/lab-code/LICENSE.txt
"""Positional against named CSV.

A headerless CSV (shipment_id, volume_kg, price_cents) read by position, then
the same reader after a weight_kg column is inserted in the middle, then the
new file with a header, read by name. Counts the rows read wrong.
"""
import argparse, csv, io, json, random

p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
p.add_argument("--rows", type=int, default=1000, help="Shipments.")
p.add_argument("--seed", type=int, default=0, help="Random seed.")
p.add_argument("--json", help="Also write the results to this JSON file.")
args = p.parse_args()
random.seed(args.seed)

truth = [{"shipment_id": f"S{i}", "weight_kg": round(random.uniform(0.5, 20), 1), "volume_kg": round(random.uniform(1, 50), 1),
          "price_cents": random.randrange(500, 50000)} for i in range(args.rows)]
old = "".join(f"{r['shipment_id']},{r['volume_kg']},{r['price_cents']}\n" for r in truth)
new = "".join(f"{r['shipment_id']},{r['weight_kg']},{r['volume_kg']},{r['price_cents']}\n" for r in truth)   # weight_kg inserted at position 2
def read_by_position(text):
    return [{"shipment_id": r[0], "volume_kg": float(r[1]), "price_cents": float(r[2])} for r in csv.reader(io.StringIO(text))]
def read_by_name(text):
    return [{"shipment_id": r["shipment_id"], "volume_kg": float(r["volume_kg"]), "price_cents": float(r["price_cents"])}
            for r in csv.DictReader(io.StringIO(text))]
def wrong(rows): return sum(1 for r, t in zip(rows, truth) if r["volume_kg"] != t["volume_kg"] or r["price_cents"] != t["price_cents"])
results = []
for label, fn, text in (("old file, by position", read_by_position, old), ("new file, by position", read_by_position, new),
                        ("new file with a header, by name", read_by_name, "shipment_id,weight_kg,volume_kg,price_cents\n" + new)):
    try: rows = fn(text); results.append({"read": label, "error": "none", "rows": len(rows), "wrong": wrong(rows), "first": f"volume {rows[0]['volume_kg']}, price {rows[0]['price_cents']:.0f}"})
    except Exception as e: results.append({"read": label, "error": type(e).__name__, "rows": 0, "wrong": None, "first": ""})
summary = {"truth_first": f"volume {truth[0]['volume_kg']}, price {truth[0]['price_cents']}"}
for r in results: print(f"{r['read']:<34} exception: {r['error']:<5} rows {r['rows']:>5}  wrong {r['wrong']:>5}  first row: {r['first']}")
print(f"true first row: {summary['truth_first']}")

if args.json:
    with open(args.json, "w") as f:
        json.dump({"summary": summary, "tables": {"reads": results}}, f)
