import argparse
import json
import sys
import logging

from .core import (
    load_config,
    save_config,
    get_config_value,
    set_config_value,
    list_tools,
    validate_config,
    format_output,
    build_cli_parser,
    cli_main,
)

__version__ = "1.0.0"

logger = logging.getLogger("agent-config")


def _setup_logging(verbose: bool) -> None:
    level = logging.DEBUG if verbose else logging.WARNING
    logging.basicConfig(
        level=level,
        format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
    )


def _output(data, as_json: bool = False) -> None:
    if as_json:
        if isinstance(data, str):
            print(json.dumps({"result": data}, indent=2))
        else:
            print(json.dumps(data, indent=2, default=str))
    else:
        if isinstance(data, dict):
            print(format_output(data))
        elif isinstance(data, list):
            for item in data:
                print(format_output(item) if isinstance(item, dict) else str(item))
        else:
            print(data)


def cmd_load(args: argparse.Namespace) -> int:
    logger.debug("Loading config from: %s", args.file)
    try:
        config = load_config(args.file)
        _output(config, as_json=args.json)
        return 0
    except Exception as e:
        logger.error("Failed to load config: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


def cmd_save(args: argparse.Namespace) -> int:
    logger.debug("Saving config to: %s", args.file)
    try:
        config = load_config(args.source) if args.source else {}
        save_config(config, args.file)
        _output({"status": "saved", "file": args.file}, as_json=args.json)
        return 0
    except Exception as e:
        logger.error("Failed to save config: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


def cmd_get(args: argparse.Namespace) -> int:
    logger.debug("Getting config value for key: %s", args.key)
    try:
        config = load_config(args.file)
        value = get_config_value(config, args.key)
        if value is None and not args.json:
            print(f"Key '{args.key}' not found.", file=sys.stderr)
            return 1
        _output({"key": args.key, "value": value}, as_json=args.json)
        return 0
    except Exception as e:
        logger.error("Failed to get config value: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


def cmd_set(args: argparse.Namespace) -> int:
    logger.debug("Setting config value: %s = %s", args.key, args.value)
    try:
        config = load_config(args.file)
        value = args.value
        # Try to parse value as JSON for non-string types
        try:
            value = json.loads(value)
        except (json.JSONDecodeError, TypeError):
            pass
        config = set_config_value(config, args.key, value)
        save_config(config, args.file)
        _output({"status": "updated", "key": args.key, "value": value}, as_json=args.json)
        return 0
    except Exception as e:
        logger.error("Failed to set config value: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


def cmd_list_tools(args: argparse.Namespace) -> int:
    logger.debug("Listing tools")
    try:
        config = load_config(args.file) if args.file else None
        tools = list_tools(config) if config is not None else list_tools()
        _output({"tools": tools}, as_json=args.json)
        return 0
    except Exception as e:
        logger.error("Failed to list tools: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


def cmd_validate(args: argparse.Namespace) -> int:
    logger.debug("Validating config: %s", args.file)
    try:
        config = load_config(args.file)
        result = validate_config(config)
        if isinstance(result, bool):
            status = "valid" if result else "invalid"
            output_data = {"status": status, "file": args.file}
        else:
            output_data = {"status": "complete", "result": result, "file": args.file}
        _output(output_data, as_json=args.json)
        if isinstance(result, bool) and not result:
            return 1
        return 0
    except Exception as e:
        logger.error("Validation failed: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


def cmd_format(args: argparse.Namespace) -> int:
    logger.debug("Formatting config output: %s", args.file)
    try:
        config = load_config(args.file)
        formatted = format_output(config)
        if args.json:
            print(json.dumps({"formatted": formatted}, indent=2))
        else:
            print(formatted)
        return 0
    except Exception as e:
        logger.error("Failed to format output: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


def create_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="agent-config",
        description="CLI for managing agent configuration files.",
    )
    parser.add_argument(
        "--version",
        action="version",
        version=f"%(prog)s {__version__}",
    )
    parser.add_argument(
        "--json",
        action="store_true",
        default=False,
        help="Output results in JSON format.",
    )
    parser.add_argument(
        "--verbose",
        action="store_true",
        default=False,
        help="Enable verbose/debug output.",
    )

    subparsers = parser.add_subparsers(
        title="subcommands",
        dest="command",
        help="Available subcommands",
    )

    # load subcommand
    load_parser = subparsers.add_parser("load", help="Load and display a configuration file.")
    load_parser.add_argument("file", help="Path to the configuration file.")
    load_parser.set_defaults(func=cmd_load)

    # save subcommand
    save_parser = subparsers.add_parser("save", help="Save a configuration file.")
    save_parser.add_argument("file", help="Path to the destination configuration file.")
    save_parser.add_argument(
        "--source",
        default=None,
        help="Path to a source configuration file to copy from.",
    )
    save_parser.set_defaults(func=cmd_save)

    # get subcommand
    get_parser = subparsers.add_parser("get", help="Get a specific configuration value.")
    get_parser.add_argument("file", help="Path to the configuration file.")
    get_parser.add_argument("key", help="Configuration key to retrieve.")
    get_parser.set_defaults(func=cmd_get)

    # set subcommand
    set_parser = subparsers.add_parser("set", help="Set a specific configuration value.")
    set_parser.add_argument("file", help="Path to the configuration file.")
    set_parser.add_argument("key", help="Configuration key to set.")
    set_parser.add_argument("value", help="Value to set for the key.")
    set_parser.set_defaults(func=cmd_set)

    # list-tools subcommand
    tools_parser = subparsers.add_parser("list-tools", help="List available tools.")
    tools_parser.add_argument(
        "--file",
        default=None,
        help="Optional path to a configuration file.",
    )
    tools_parser.set_defaults(func=cmd_list_tools)

    # validate subcommand
    validate_parser = subparsers.add_parser("validate", help="Validate a configuration file.")
    validate_parser.add_argument("file", help="Path to the configuration file to validate.")
    validate_parser.set_defaults(func=cmd_validate)

    # format subcommand
    format_parser = subparsers.add_parser("format", help="Format and display configuration output.")
    format_parser.add_argument("file", help="Path to the configuration file.")
    format_parser.set_defaults(func=cmd_format)

    return parser


def main(argv: list[str] | None = None) -> int:
    # Allow core module to build/extend the parser if needed
    parser = create_parser()

    # Optionally let core module extend the parser
    try:
        extended_parser = build_cli_parser(parser)
        if extended_parser is not None:
            parser = extended_parser
    except Exception:
        logger.debug("build_cli_parser from core did not extend parser.")

    args = parser.parse_args(argv)

    _setup_logging(args.verbose)
    logger.debug("Parsed arguments: %s", args)

    if args.command is None:
        parser.print_help()
        return 0

    if hasattr(args, "func"):
        return args.func(args)

    # Fallback to cli_main from core if no func is set
    try:
        return cli_main(args)
    except Exception as e:
        logger.error("cli_main failed: %s", e)
        print(f"Error: {e}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    sys.exit(main())