"""Aegis CLI entry point."""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

from aegis.runtime.audit import AuditLogger

_INIT_POLICY = """\
# Aegis Policy — generated by `aegis init`
# Docs: https://acacian.github.io/aegis/guides/policies/

version: "1"

defaults:
  risk_level: medium
  approval: approve

rules:
  # Read-only operations: auto-execute
  - name: read_auto
    match:
      type: "read*"
    risk_level: low
    approval: auto

  - name: get_auto
    match:
      type: "get*"
    risk_level: low
    approval: auto

  # Write operations: require human approval
  - name: write_approve
    match:
      type: "write*"
    risk_level: medium
    approval: approve

  - name: update_approve
    match:
      type: "update*"
    risk_level: medium
    approval: approve

  # Bulk operations: high risk
  - name: bulk_high
    match:
      type: "bulk_*"
    risk_level: high
    approval: approve

  # Destructive operations: always blocked
  - name: delete_block
    match:
      type: "delete*"
    risk_level: critical
    approval: block
"""


def main(argv: list[str] | None = None) -> None:
    """CLI entry point for ``aegis`` command."""
    parser = argparse.ArgumentParser(
        prog="aegis",
        description="Aegis: Policy & approval runtime for AI agents",
    )
    parser.add_argument("--version", action="store_true", help="Show version")
    subparsers = parser.add_subparsers(dest="command")

    # aegis audit
    audit_parser = subparsers.add_parser("audit", help="View the audit log")
    audit_parser.add_argument("--db", default="aegis_audit.db", help="Database path")
    audit_parser.add_argument("--session", help="Filter by session ID")
    audit_parser.add_argument("--action-type", help="Filter by action type")
    audit_parser.add_argument("--risk-level", help="Filter by risk level")
    audit_parser.add_argument(
        "--format",
        choices=["table", "json", "jsonl"],
        default="table",
        dest="fmt",
    )
    audit_parser.add_argument("--output", "-o", help="Output file path (for jsonl export)")

    # aegis validate
    validate_parser = subparsers.add_parser("validate", help="Validate a policy file")
    validate_parser.add_argument("policy_file", help="Path to policy YAML file")

    # aegis schema
    subparsers.add_parser("schema", help="Print the policy JSON Schema")

    # aegis init
    init_parser = subparsers.add_parser("init", help="Generate a starter policy file")
    init_parser.add_argument("--output", "-o", default="policy.yaml", help="Output file path")

    # aegis simulate
    sim_parser = subparsers.add_parser(
        "simulate",
        help="Test actions against a policy without executing",
    )
    sim_parser.add_argument("policy_file", help="Path to policy YAML file")
    sim_parser.add_argument(
        "actions",
        nargs="+",
        help="Actions as type:target (e.g. read:crm delete:db)",
    )
    sim_parser.add_argument(
        "--format",
        choices=["table", "json"],
        default="table",
        dest="fmt",
    )

    args = parser.parse_args(argv)

    if args.version:
        from aegis import __version__

        print(f"aegis {__version__}")
        return

    if args.command == "audit":
        _cmd_audit(args)
    elif args.command == "validate":
        _cmd_validate(args)
    elif args.command == "schema":
        _cmd_schema()
    elif args.command == "init":
        _cmd_init(args)
    elif args.command == "simulate":
        _cmd_simulate(args)
    else:
        parser.print_help()


def _cmd_audit(args: argparse.Namespace) -> None:
    """Display audit log entries."""
    logger = AuditLogger(db_path=args.db)

    if args.fmt == "jsonl":
        output = args.output or "aegis_audit.jsonl"
        count = logger.export_jsonl(output, session_id=args.session)
        logger.close()
        print(f"Exported {count} entries to {output}")
        return

    entries = logger.get_log(
        session_id=args.session,
        action_type=getattr(args, "action_type", None),
        risk_level=getattr(args, "risk_level", None),
    )
    logger.close()

    if not entries:
        print("No audit entries found.")
        return

    if args.fmt == "json":
        print(json.dumps(entries, indent=2))
        return

    # Table format
    cols = [
        f"{'ID':>4}",
        f"{'Session':>12}",
        f"{'Action':>15}",
        f"{'Target':>15}",
        f"{'Risk':>8}",
        f"{'Decision':>10}",
        f"{'Result':>10}",
    ]
    header = " ".join(cols)
    print(header)
    print("-" * len(header))
    for e in entries:
        print(
            f"{e['id']:>4} {e['session_id']:>12} {e['action_type']:>15} "
            f"{e['action_target']:>15} {e['risk_level']:>8} "
            f"{(e.get('human_decision') or e['approval']):>10} "
            f"{(e.get('result_status') or '-'):>10}"
        )


def _cmd_validate(args: argparse.Namespace) -> None:
    """Validate a policy YAML file."""
    from aegis.core.policy import Policy

    try:
        policy = Policy.from_yaml(args.policy_file)
        print(f"Policy valid: {len(policy.rules)} rule(s) loaded.")
        for rule in policy.rules:
            print(
                f"  - {rule.name}: {rule.match_type}@{rule.match_target} "
                f"-> {rule.risk_level.name}/{rule.approval.value}"
            )
    except Exception as e:
        print(f"Policy validation failed: {e}", file=sys.stderr)
        sys.exit(1)


def _cmd_schema() -> None:
    """Print the policy JSON Schema."""
    from aegis.core.schema import get_schema_json

    print(get_schema_json())


def _cmd_init(args: argparse.Namespace) -> None:
    """Generate a starter policy file."""
    output = Path(args.output)
    if output.exists():
        print(f"File already exists: {output}", file=sys.stderr)
        sys.exit(1)

    output.write_text(_INIT_POLICY)
    print(f"Created {output}")
    print("Edit the rules to match your agent's actions, then:")
    print(f"  aegis validate {output}")


def _cmd_simulate(args: argparse.Namespace) -> None:
    """Test actions against a policy without executing."""
    from aegis.core.action import Action
    from aegis.core.plan import ExecutionPlan
    from aegis.core.policy import Policy

    try:
        policy = Policy.from_yaml(args.policy_file)
    except Exception as e:
        print(f"Failed to load policy: {e}", file=sys.stderr)
        sys.exit(1)

    actions: list[Action] = []
    for spec in args.actions:
        parts = spec.split(":", 1)
        if len(parts) == 2:
            actions.append(Action(parts[0], parts[1]))
        else:
            actions.append(Action(parts[0], "*"))

    decisions = [policy.evaluate(a) for a in actions]
    plan = ExecutionPlan(decisions=decisions)

    if args.fmt == "json":
        print(json.dumps(plan.to_dict(), indent=2))
        return

    # Table format
    _icons = {"auto": "AUTO", "approve": "APPROVE", "block": "BLOCK"}
    print(f"Policy: {args.policy_file} ({len(policy.rules)} rules)")
    print(f"Actions: {len(actions)}\n")

    blocked = 0
    approval_needed = 0

    for i, d in enumerate(plan.decisions, 1):
        icon = _icons.get(d.approval.value, "?")
        status = "ALLOWED" if d.is_allowed else "BLOCKED"
        if not d.is_allowed:
            blocked += 1
        elif d.approval.value == "approve":
            approval_needed += 1

        print(
            f"  {i}. {d.action.type}:{d.action.target}"
            f"  [{icon}]  risk={d.risk_level.name}"
            f"  rule={d.matched_rule}  -> {status}"
        )

    print()
    total = len(plan.decisions)
    auto = total - blocked - approval_needed
    print(f"Summary: {total} actions")
    print(f"  {auto} auto-execute, {approval_needed} need approval, {blocked} blocked")


if __name__ == "__main__":
    main()
