#!/usr/bin/env python3
"""
pyKwet — command-line wrapper for the installed pykwet package.

This script deliberately contains no rule-engine code.  It imports the
installed package and delegates generation to pykwet.KwetEngine.

Typical use:

    pyKwet examples/Russian.kwet
    pyKwet -n 10 -s BOYNAME examples/Russian.kwet
    pyKwet -n 10 -S 12345 -Z examples/Russian.kwet

The old hidden -b option is still accepted as an alias for -s for
compatibility with earlier Kwet usage.
"""

from __future__ import annotations

import argparse
import json
import os
import sys
from typing import Iterable, List, Optional

try:
    from pykwet import KwetEngine
except ImportError as exc:  # pragma: no cover - helpful command-line failure
    raise SystemExit(
        "Could not import the installed 'pykwet' package.\n\n"
        "Install it first with:\n\n"
        "    cd /path/to/pykwet\n"
        "    python3 -m pip install -e .\n"
    ) from exc


def build_arg_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog=os.path.basename(sys.argv[0]),
        description="Generate random text from Kwet rule files using the installed pykwet package.",
    )

    parser.add_argument(
        "rulefiles",
        nargs="+",
        help="One or more .kwet rule files to load.",
    )
    parser.add_argument(
        "-n",
        "--count",
        type=int,
        default=1,
        help="Number of outputs to generate. Default: 1.",
    )
    parser.add_argument(
        "-s",
        "--start",
        "--variable",
        dest="variable",
        help="Rule/variable to generate from. If omitted, the rule file default is used.",
    )
    parser.add_argument(
        "-b",
        dest="variable_b",
        help=argparse.SUPPRESS,
    )
    parser.add_argument(
        "-S",
        "--seed",
        type=int,
        help="Random seed as a decimal integer, for repeatable output.",
    )
    parser.add_argument(
        "-Z",
        "--sort",
        dest="sort_after",
        action="store_true",
        help="Sort generated output alphabetically after generation.",
    )
    parser.add_argument(
        "--sort-by",
        help="When sorting, generate a parallel sort key from this rule/variable.",
    )
    parser.add_argument(
        "--records",
        nargs="+",
        metavar="VARIABLE",
        help="Generate structured records containing the listed variables.",
    )
    parser.add_argument(
        "--json",
        action="store_true",
        help="Output JSON rather than plain text.",
    )
    parser.add_argument(
        "--info",
        action="store_true",
        help="Show rule-set metadata and exit.",
    )
    parser.add_argument(
        "-d",
        "--debug",
        action="count",
        default=0,
        help="Accepted for compatibility. Debug output depends on the installed package.",
    )

    return parser


def metadata_to_dict(info: object) -> dict:
    """Convert the package metadata object into a plain dictionary."""
    return {
        "name": getattr(info, "name", ""),
        "description": getattr(info, "description", ""),
        "theme": getattr(info, "theme", ""),
        "allowed": list(getattr(info, "allowed", []) or []),
        "default_variable": getattr(info, "default_variable", None),
    }


def print_info(engine: KwetEngine, as_json: bool = False) -> None:
    info = metadata_to_dict(engine.info())

    if as_json:
        print(json.dumps(info, indent=2, ensure_ascii=False))
        return

    print(f"Name: {info['name']}")
    print(f"Description: {info['description']}")
    print(f"Theme: {info['theme']}")
    print(f"Default variable: {info['default_variable']}")
    print("Allowed variables:")
    for item in info["allowed"]:
        print(f"  {item}")


def normalise_result(item: object) -> object:
    """Make result objects JSON-friendly while leaving strings untouched."""
    if isinstance(item, str):
        return item

    if hasattr(item, "__dict__"):
        return dict(item.__dict__)

    return str(item)


def main(argv: Optional[List[str]] = None) -> int:
    parser = build_arg_parser()
    args = parser.parse_args(argv)

    variable = args.variable or args.variable_b

    if args.count < 0:
        parser.error("--count must be zero or greater")

    engine = KwetEngine(args.rulefiles, seed=args.seed)

    if args.info:
        print_info(engine, as_json=args.json)
        return 0

    if args.records:
        records = engine.generate_records(
            args.records,
            count=args.count,
            sort_by=args.sort_by,
        )

        if args.json:
            print(json.dumps(records, indent=2, ensure_ascii=False))
        else:
            for record in records:
                print("\t".join(str(record.get(key, "")) for key in args.records))
        return 0

    # If --sort-by is supplied, ask for result objects so the sort key can be
    # represented in JSON output.  Plain text output still prints only the text.
    as_results = bool(args.sort_by and args.json)

    results = engine.generate(
        variable=variable,
        count=args.count,
        sort=args.sort_after or bool(args.sort_by),
        sort_by=args.sort_by,
        as_results=as_results,
    )

    if args.json:
        print(json.dumps([normalise_result(item) for item in results], indent=2, ensure_ascii=False))
    else:
        for item in results:
            print(getattr(item, "text", item))

    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))
