#!/usr/bin/env python3
# =============================================================================
#  installer/serial_generator.py — AR Electronics serial number generator
# =============================================================================
#
#  Developer tool.  Generates a batch of unique serial numbers and optionally
#  writes them to a CSV log for the AR Electronics CRM.
#
#  Format: AR-XXXX-XXXX-XXXX  (hex groups, 48 bits of entropy ≈ 281 trillion)
#
#  Usage:
#    python serial_generator.py 10                  # generate 10 serials
#    python serial_generator.py 10 --csv serials.csv
#    python serial_generator.py 1 --vessel "MY YACHT NAME" --csv serials.csv
# =============================================================================

import argparse
import csv
import os
import secrets
from datetime import datetime, timezone


def generate_serial() -> str:
    """Generate a single AR-XXXX-XXXX-XXXX serial number."""
    raw = secrets.token_hex(6).upper()  # 6 bytes = 12 hex chars = 3 × 4
    return f"AR-{raw[0:4]}-{raw[4:8]}-{raw[8:12]}"


def generate_batch(count: int, vessel: str = "") -> list[dict]:
    serials = []
    seen: set[str] = set()

    while len(serials) < count:
        serial = generate_serial()
        if serial in seen:
            continue  # collision (astronomically unlikely)
        seen.add(serial)
        serials.append(
            {
                "serial":     serial,
                "vessel":     vessel,
                "created_at": datetime.now(timezone.utc).isoformat(),
                "status":     "unactivated",
            }
        )

    return serials


def write_key_file(serial: str, output_path: str) -> None:
    """Write a single serial number to a serial.key file."""
    with open(output_path, "w", encoding="utf-8") as f:
        f.write(serial)
    print(f"  → {output_path}")


def write_csv(records: list[dict], csv_path: str) -> None:
    """Append records to a CSV log (creates file if missing)."""
    file_exists = os.path.exists(csv_path)
    with open(csv_path, "a", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=["serial", "vessel", "created_at", "status"])
        if not file_exists:
            writer.writeheader()
        writer.writerows(records)
    print(f"\nAnexado a CSV: {csv_path}")


def main():
    parser = argparse.ArgumentParser(
        description="AR Electronics — Generador de números de serie"
    )
    parser.add_argument("count", type=int, nargs="?", default=1,
                        help="Cantidad de seriales a generar (default: 1)")
    parser.add_argument("--vessel", default="",
                        help="Nombre del buque para asignar al lote")
    parser.add_argument("--csv",
                        help="Ruta al archivo CSV de registro (se crea o se añade)")
    parser.add_argument("--key-dir",
                        help="Directorio donde escribir archivos serial.key individuales")
    args = parser.parse_args()

    records = generate_batch(args.count, vessel=args.vessel)

    print(f"\nSeriales generados ({args.count}):\n")
    for rec in records:
        vessel_info = f"  [{rec['vessel']}]" if rec["vessel"] else ""
        print(f"  {rec['serial']}{vessel_info}")

    if args.csv:
        write_csv(records, args.csv)

    if args.key_dir:
        os.makedirs(args.key_dir, exist_ok=True)
        for i, rec in enumerate(records):
            filename = f"serial_{i+1:03d}.key" if len(records) > 1 else "serial.key"
            write_key_file(rec["serial"], os.path.join(args.key_dir, filename))

    print()


if __name__ == "__main__":
    main()
