"""Citadel CLI — self-installation for the Citadel operator.

Usage::

    citadel install   [--namespace NS] [--image IMAGE] [--with-default-policies] [--with-network-policies] [--timeout SECS]
    citadel uninstall [--namespace NS] [--delete-crds]
    citadel status    [--namespace NS]
    citadel manifests [--namespace NS] [--image IMAGE]
"""

from __future__ import annotations

import argparse
import sys

import yaml

# ---------------------------------------------------------------------------
# Defaults
# ---------------------------------------------------------------------------
_DEFAULT_NAMESPACE = "citadel-system"
_DEFAULT_IMAGE = "citadel-operator:latest"
_DEFAULT_TIMEOUT = 120


# ---------------------------------------------------------------------------
# Subcommand handlers
# ---------------------------------------------------------------------------


def _cmd_install(args: argparse.Namespace) -> int:
    from citadel_operator.cli._install import install

    ok = install(
        namespace=args.namespace,
        image=args.image,
        with_default_policies=args.with_default_policies,
        with_network_policies=args.with_network_policies,
        timeout=args.timeout,
    )
    return 0 if ok else 1


def _cmd_uninstall(args: argparse.Namespace) -> int:
    from citadel_operator.cli._uninstall import uninstall

    ok = uninstall(
        namespace=args.namespace,
        delete_crds=args.delete_crds,
    )
    return 0 if ok else 1


def _cmd_status(args: argparse.Namespace) -> int:
    from citadel_operator.cli._status import status

    ok = status(namespace=args.namespace)
    return 0 if ok else 1


def _cmd_manifests(args: argparse.Namespace) -> int:
    from citadel_operator.cli._manifests import (
        all_manifests,
        load_default_policies,
        load_network_policies,
    )

    manifests = all_manifests(namespace=args.namespace, image=args.image)
    manifests.extend(load_default_policies())
    if args.with_network_policies:
        manifests.extend(load_network_policies())

    for i, doc in enumerate(manifests):
        if i > 0:
            print("---")
        print(yaml.dump(doc, default_flow_style=False).rstrip())

    return 0


# ---------------------------------------------------------------------------
# Parser
# ---------------------------------------------------------------------------


def _build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="citadel",
        description="Citadel operator installer — deploy into any Kubernetes cluster",
    )
    sub = parser.add_subparsers(dest="command")

    # install
    p_install = sub.add_parser("install", help="Install Citadel into the cluster")
    p_install.add_argument(
        "--namespace", default=_DEFAULT_NAMESPACE, help=f"Target namespace (default: {_DEFAULT_NAMESPACE})"
    )
    p_install.add_argument(
        "--image", default=_DEFAULT_IMAGE, help=f"Operator container image (default: {_DEFAULT_IMAGE})"
    )
    p_install.add_argument(
        "--with-default-policies",
        action="store_true",
        default=True,
        help="Apply built-in NodeTerminationPolicies (default: True)",
    )
    p_install.add_argument(
        "--no-default-policies",
        dest="with_default_policies",
        action="store_false",
        help="Skip applying built-in NodeTerminationPolicies",
    )
    p_install.add_argument(
        "--with-network-policies",
        action="store_true",
        default=False,
        help="Also apply bundled Cilium network policies (requires Cilium CRDs)",
    )
    p_install.add_argument(
        "--timeout",
        type=int,
        default=_DEFAULT_TIMEOUT,
        help=f"Seconds to wait for Deployment rollout (default: {_DEFAULT_TIMEOUT})",
    )
    p_install.set_defaults(func=_cmd_install)

    # uninstall
    p_uninstall = sub.add_parser("uninstall", help="Remove Citadel from the cluster")
    p_uninstall.add_argument(
        "--namespace", default=_DEFAULT_NAMESPACE, help=f"Target namespace (default: {_DEFAULT_NAMESPACE})"
    )
    p_uninstall.add_argument(
        "--delete-crds",
        action="store_true",
        default=False,
        help="Also delete CRDs (destructive — removes all CRD instances)",
    )
    p_uninstall.set_defaults(func=_cmd_uninstall)

    # status
    p_status = sub.add_parser("status", help="Check Citadel installation health")
    p_status.add_argument(
        "--namespace", default=_DEFAULT_NAMESPACE, help=f"Target namespace (default: {_DEFAULT_NAMESPACE})"
    )
    p_status.set_defaults(func=_cmd_status)

    # manifests
    p_manifests = sub.add_parser(
        "manifests", help="Print all Kubernetes manifests to stdout (for review)"
    )
    p_manifests.add_argument(
        "--namespace", default=_DEFAULT_NAMESPACE, help=f"Target namespace (default: {_DEFAULT_NAMESPACE})"
    )
    p_manifests.add_argument(
        "--image", default=_DEFAULT_IMAGE, help=f"Operator container image (default: {_DEFAULT_IMAGE})"
    )
    p_manifests.add_argument(
        "--with-network-policies",
        action="store_true",
        default=False,
        help="Include bundled Cilium network policies in output",
    )
    p_manifests.set_defaults(func=_cmd_manifests)

    return parser


# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------


def main() -> int:
    """CLI entry point.  Returns exit code."""
    parser = _build_parser()
    args = parser.parse_args()

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

    return args.func(args)


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