"""command-line interface for icdlookup.

usage examples::

    # single lookup
    icdlookup A00.1

    # search by keyword
    icdlookup --search cholera

    # annotate a csv file
    icdlookup --file data.csv --column icd_code --output annotated.csv

    # use custom reference
    icdlookup A00.1 --reference /path/to/custom.csv
"""

from __future__ import annotations

import argparse
import csv
import sys
from pathlib import Path


def _build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="icdlookup",
        description="look up icd codes and annotate datasets.",
    )
    parser.add_argument(
        "code",
        nargs="?",
        default=None,
        help="icd code to look up (e.g. A00.1).",
    )
    parser.add_argument(
        "--search", "-s",
        metavar="KEYWORD",
        default=None,
        help="search descriptions by keyword.",
    )
    parser.add_argument(
        "--detail", "-d",
        action="store_true",
        help="show full hierarchy detail for a lookup.",
    )
    parser.add_argument(
        "--file", "-f",
        metavar="CSV",
        default=None,
        help="path to a csv file to annotate.",
    )
    parser.add_argument(
        "--column", "-c",
        metavar="COL",
        default="icd_code",
        help="column name containing icd codes (default: icd_code).",
    )
    parser.add_argument(
        "--output", "-o",
        metavar="CSV",
        default=None,
        help="output path for the annotated csv (default: stdout).",
    )
    parser.add_argument(
        "--reference", "-r",
        metavar="CSV",
        default=None,
        help="path to a custom reference csv.",
    )
    parser.add_argument(
        "--limit", "-l",
        metavar="N",
        type=int,
        default=20,
        help="max number of search results (default: 20).",
    )
    parser.add_argument(
        "--version", "-v",
        action="store_true",
        help="show version and exit.",
    )
    return parser


def main(argv: list[str] | None = None) -> None:
    parser = _build_parser()
    args = parser.parse_args(argv)

    # --version
    if args.version:
        from icdlookup import __version__
        print(f"icdlookup {__version__}")
        return

    ref = args.reference

    # --file: annotate a csv
    if args.file:
        _annotate_csv(args.file, args.column, args.output, ref)
        return

    # --search: keyword search
    if args.search:
        from icdlookup.lookup import search
        results = search(args.search, limit=args.limit, reference=ref)
        if not results:
            print(f"No results for '{args.search}'.", file=sys.stderr)
            sys.exit(1)
        for code, desc in results:
            print(f"{code}\t{desc}")
        return

    # positional code: lookup
    if args.code:
        from icdlookup.lookup import lookup
        result = lookup(args.code, detail=args.detail, reference=ref)
        if result is None:
            print(f"Code '{args.code}' not found.", file=sys.stderr)
            sys.exit(1)
        if isinstance(result, dict):
            for k, v in result.items():
                if v:
                    print(f"{k}: {v}")
        else:
            print(result)
        return

    # no action specified
    parser.print_help()
    sys.exit(1)


def _annotate_csv(
    file_path: str,
    column: str,
    output_path: str | None,
    reference: str | None,
) -> None:
    """read a csv, add an icd_description column, and write out."""
    from icdlookup.loader import build_index, normalise_code

    index = build_index(reference)
    in_path = Path(file_path)

    if not in_path.exists():
        print(f"File not found: {file_path}", file=sys.stderr)
        sys.exit(1)

    with open(in_path, encoding="utf-8", newline="") as fh:
        reader = csv.DictReader(fh)
        if reader.fieldnames is None:
            print("empty csv file.", file=sys.stderr)
            sys.exit(1)
        if column not in reader.fieldnames:
            print(
                f"Column '{column}' not found. Available: {reader.fieldnames}",
                file=sys.stderr,
            )
            sys.exit(1)

        out_fields = list(reader.fieldnames) + ["icd_description"]

        out_fh = (
            open(output_path, "w", encoding="utf-8", newline="")
            if output_path
            else sys.stdout
        )
        try:
            writer = csv.DictWriter(out_fh, fieldnames=out_fields)
            writer.writeheader()
            for row in reader:
                code = row.get(column, "")
                norm = normalise_code(code)
                match = index.get(norm)
                row["icd_description"] = match["description"] if match else ""
                writer.writerow(row)
        finally:
            if output_path:
                out_fh.close()

    if output_path:
        print(f"annotated csv written to {output_path}", file=sys.stderr)


if __name__ == "__main__":
    main()
