"""Meridian EUID command-line interface."""

from __future__ import annotations

import argparse
import json
import sys
from typing import Optional, Sequence

from . import __version__
from .euid import validate, compute_check_character, encode, parse, Environment
from .exceptions import EUIDError


def main(argv: Optional[Sequence[str]] = None) -> int:
    """Main CLI entry point. Returns exit code."""
    parser = argparse.ArgumentParser(
        prog="meridian-euid",
        description="Meridian EUID validator, encoder, and parser.",
    )
    parser.add_argument(
        "--version", action="version", version=f"%(prog)s {__version__}"
    )
    subparsers = parser.add_subparsers(dest="command", required=True)

    # validate command
    validate_parser = subparsers.add_parser(
        "validate",
        help="Validate an EUID",
    )
    validate_parser.add_argument("euid", help="The EUID to validate")
    validate_parser.add_argument(
        "--env",
        choices=["production", "sandbox"],
        required=True,
        help="Environment context",
    )
    validate_parser.add_argument(
        "--allowed-prefixes",
        help="Comma-separated list of allowed sandbox prefixes (sandbox only)",
    )

    # compute-check command
    check_parser = subparsers.add_parser(
        "compute-check",
        help="Compute check character for a payload",
    )
    check_parser.add_argument(
        "payload",
        help=(
            "Checksum payload (no delimiters). "
            "Production: CATEGORY+BODY. Sandbox: SANDBOX+CATEGORY+BODY."
        ),
    )

    # encode command
    encode_parser = subparsers.add_parser(
        "encode",
        help="Encode an integer as a Meridian EUID",
    )
    encode_parser.add_argument("integer", type=int, help="Positive integer to encode")
    encode_parser.add_argument(
        "category", help="Category prefix (2-3 uppercase Crockford letters)"
    )
    encode_parser.add_argument(
        "--sandbox",
        default=None,
        help="Sandbox prefix (single letter, H-Z excluding reserved A-G and I/L/O/U)",
    )

    # parse command
    parse_parser = subparsers.add_parser(
        "parse",
        help="Parse an EUID into its components",
    )
    parse_parser.add_argument("euid", help="The EUID to parse")

    args = parser.parse_args(argv)

    commands = {
        "validate": cmd_validate,
        "compute-check": cmd_compute_check,
        "encode": cmd_encode,
        "parse": cmd_parse,
    }
    return commands[args.command](args)


def cmd_validate(args: argparse.Namespace) -> int:
    """Handle validate command."""
    env: Environment = args.env
    allowed_prefixes = None
    if args.allowed_prefixes:
        allowed_prefixes = set(args.allowed_prefixes.split(","))

    try:
        canonical = validate(
            args.euid, environment=env, allowed_sandbox_prefixes=allowed_prefixes
        )
        print(f"VALID: {canonical}")
        return 0
    except EUIDError as e:
        print(f"INVALID: {e}", file=sys.stderr)
        return 1


def cmd_compute_check(args: argparse.Namespace) -> int:
    """Handle compute-check command."""
    try:
        check_char = compute_check_character(args.payload)
        print(check_char)
        return 0
    except (EUIDError, ValueError) as e:
        print(f"ERROR: {e}", file=sys.stderr)
        return 1


def cmd_encode(args: argparse.Namespace) -> int:
    """Handle encode command."""
    try:
        euid = encode(args.integer, args.category, sandbox=args.sandbox)
        print(euid)
        return 0
    except (EUIDError, ValueError) as e:
        print(f"ERROR: {e}", file=sys.stderr)
        return 1


def cmd_parse(args: argparse.Namespace) -> int:
    """Handle parse command."""
    try:
        result = parse(args.euid)
        print(json.dumps(result, indent=2))
        return 0
    except (EUIDError, ValueError) as e:
        print(f"ERROR: {e}", file=sys.stderr)
        return 1


if __name__ == "__main__":  # pragma: no cover
    sys.exit(main())
