"""Convert an array of flat JSON objects into UTF-8 CSV (Python 3.10+)."""

import argparse
import csv
import json
from pathlib import Path


def _reject_constant(value: str):
    raise ValueError(f"Non-standard JSON number: {value}")


def convert(source: Path, destination: Path) -> tuple[int, int]:
    """Create a new CSV. Preserve first-seen column order; never overwrite files."""
    with source.open("r", encoding="utf-8-sig") as handle:
        records = json.load(handle, parse_constant=_reject_constant)
    if not isinstance(records, list):
        raise ValueError("The JSON root must be an array of flat objects")

    columns: dict[str, None] = {}
    for index, record in enumerate(records):
        if not isinstance(record, dict):
            raise ValueError(f"Row {index + 1} must be an object")
        for key, value in record.items():
            if isinstance(value, (dict, list)):
                raise ValueError(f"Row {index + 1}, field {key!r} is nested")
            columns.setdefault(key, None)

    # All input validation completes before creating an output file.
    with destination.open("x", encoding="utf-8", newline="") as handle:
        writer = csv.DictWriter(handle, fieldnames=list(columns), restval="")
        if columns:
            writer.writeheader()
        for record in records:
            normalized = {
                key: "" if value is None else str(value).lower()
                if isinstance(value, bool) else value
                for key, value in record.items()
            }
            writer.writerow(normalized)
    return len(records), len(columns)


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("input", type=Path, help="UTF-8 JSON input file")
    parser.add_argument("output", type=Path, help="New UTF-8 CSV output path")
    args = parser.parse_args()
    try:
        rows, columns = convert(args.input, args.output)
    except (OSError, ValueError) as error:
        parser.exit(1, f"Error: {error}\n")
    print(f"Converted {rows} rows and {columns} columns to {args.output}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
