"""Build a small standalone HTML table from UTF-8 CSV. Python 3.10+."""
import argparse
import csv
from html import escape
from pathlib import Path
import sys


def positive(value):
    number = int(value)
    if number < 1:
        raise argparse.ArgumentTypeError("must be at least 1")
    return number


def render(source, title, max_rows):
    with source.open(encoding="utf-8-sig", newline="") as file:
        reader = csv.reader(file, strict=True)
        header = next(reader, None)
        if not header or any(not name.strip() for name in header):
            raise ValueError("missing or empty column name")
        if len(set(header)) != len(header):
            raise ValueError("duplicate column name")
        parts = []
        for number, row in enumerate(reader, 1):
            if number > max_rows:
                raise ValueError(f"more than {max_rows} data records")
            if len(row) != len(header):
                raise ValueError(f"record {number}: expected {len(header)} fields, got {len(row)}")
            parts.append("<tr>" + "".join("<td>" + escape(cell) + "</td>" for cell in row) + "</tr>")
    headings = "".join('<th scope="col">' + escape(name) + "</th>" for name in header)
    safe_title = escape(title)
    document = f'''<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{safe_title}</title>
<style>
body {{ font: 16px system-ui, sans-serif; margin: 2rem; color: #172033; }}
.scroll {{ overflow-x: auto; }}
table {{ border-collapse: collapse; }}
th, td {{ border: 1px solid #b8c2d1; padding: .5rem; text-align: left;
           white-space: pre-wrap; overflow-wrap: anywhere; max-width: 36rem; }}
th {{ background: #edf2f8; }}
</style>
</head>
<body>
<h1>{safe_title}</h1>
<p>Records: {len(parts)}</p>
<div class="scroll"><table>
<thead><tr>{headings}</tr></thead>
<tbody>{"".join(parts)}</tbody>
</table></div>
</body>
</html>
'''
    return document, len(parts)


def main():
    parser = argparse.ArgumentParser(description=__doc__, allow_abbrev=False)
    parser.add_argument("source", type=Path)
    parser.add_argument("output", type=Path)
    parser.add_argument("--title", default="CSV report")
    parser.add_argument("--max-rows", type=positive, default=1000)
    args = parser.parse_args()
    try:
        document, count = render(args.source, args.title, args.max_rows)
        payload = document.encode("utf-8")
        with args.output.open("xb") as file:
            file.write(payload)
    except (OSError, UnicodeError, csv.Error, ValueError) as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 1
    print(f"OK: {count} records -> {args.output}")
    return 0


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