"""Inspect completed local CSV files; guess only the delimiter. Python 3.9+."""
import argparse
import csv
import json
from pathlib import Path
import sys

DELIMITERS = {"comma": ",", "semicolon": ";", "tab": "\t", "pipe": "|"}


def inspect_csv(path, mode, columns):
    if len(columns) < 2 or len(set(columns)) != len(columns):
        raise ValueError("expected columns must be unique and number at least two")
    if any(not name.strip() for name in columns):
        raise ValueError("expected column names must not be blank")
    with path.open(encoding="utf-8-sig", newline="") as stream:
        if mode == "auto":
            sample = stream.read(8192)
            try:
                delimiter = csv.Sniffer().sniff(sample, delimiters=",;\t|").delimiter
            except csv.Error as exc:
                raise ValueError("cannot suggest delimiter; specify --delimiter") from exc
            stream.seek(0)
        else:
            delimiter = DELIMITERS[mode]
        reader = csv.reader(stream, delimiter=delimiter, quotechar='"',
                            doublequote=True, skipinitialspace=False, strict=True)
        try:
            header = next(reader, None)
            if header != columns:
                raise ValueError(f"header mismatch: expected {columns!r}, got {header!r}")
            records = 0
            for row in reader:
                if len(row) != len(columns):
                    raise ValueError(
                        f"record {records + 1}, ending line {reader.line_num}: "
                        f"expected {len(columns)} fields, got {len(row)}"
                    )
                records += 1
        except csv.Error as exc:
            raise ValueError(f"CSV error near physical line {reader.line_num}: {exc}") from exc
    return {"delimiter": delimiter, "columns": columns, "records": records,
            "physical_lines": reader.line_num, "selection": mode}


def main():
    parser = argparse.ArgumentParser(description=__doc__, allow_abbrev=False)
    parser.add_argument("file", type=Path)
    parser.add_argument("--delimiter", choices=["auto", *DELIMITERS], default="auto")
    parser.add_argument("--columns", nargs="+", required=True)
    args = parser.parse_args()
    try:
        report = inspect_csv(args.file, args.delimiter, args.columns)
    except (OSError, UnicodeError, ValueError) as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 1
    print(json.dumps(report, ensure_ascii=True))
    return 0


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