"""CLI for pyfortis: pyfortis api|schema|validate|gate."""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path


def _cmd_api(args: argparse.Namespace) -> None:
    """Print public API summary."""
    import pyfortis

    print("pyfortis public API")
    print("=" * 40)
    for name in sorted(pyfortis.__all__):
        obj = getattr(pyfortis, name)
        kind = type(obj).__name__
        if isinstance(obj, type):
            kind = "class"
        print(f"  {name} ({kind})")


def _cmd_schema(args: argparse.Namespace) -> None:
    """Print config schema reference."""
    schema = {
        "meta": {
            "version": "str",
            "engine_name": "str",
            "strict_mode": "bool (default: true)",
        },
        "limits": [
            {
                "name": "str (required)",
                "type": "position|concentration|price_tolerance|order_rate|notional|self_trade|custom",
                "scope": "order|instrument|strategy|sector|portfolio",
                "params": "dict",
                "severity": "INFO|WARNING|CRITICAL|KILL",
                "enabled": "bool (default: true)",
            }
        ],
        "metrics": [
            {
                "name": "str (required)",
                "type": "var|cvar|drawdown|volatility|beta|sharpe|sortino",
                "params": "dict",
                "severity": "INFO|WARNING|CRITICAL|KILL (optional)",
                "enabled": "bool (default: true)",
            }
        ],
        "circuit_breakers": [
            {
                "name": "str (required)",
                "type": "daily_pnl|drawdown|volatility",
                "params": "dict",
                "action": "log|notify|block_order|flatten_positions|halt_trading",
                "cooldown": "str (e.g. '1h')",
            }
        ],
        "breach_policy": {
            "default_action": "log|notify|block_order|flatten_positions|halt_trading",
            "escalation": {
                "WARNING": ["log", "notify"],
                "CRITICAL": ["log", "notify", "block_order"],
                "KILL": ["log", "notify", "block_order", "flatten_positions"],
            },
        },
    }
    print(json.dumps(schema, indent=2))


def _cmd_validate(args: argparse.Namespace) -> None:
    """Validate and lint a config file."""
    from pyfortis.config.loader import ConfigLoader
    from pyfortis.lint import lint_config

    path = Path(args.config)
    try:
        config = ConfigLoader.load(path)
    except Exception as exc:
        print(f"ERROR: Failed to load config: {exc}", file=sys.stderr)
        sys.exit(1)

    issues = lint_config(config)

    if not issues:
        print(f"OK: {path} is valid with no issues")
        return

    errors = [i for i in issues if i.level == "error"]
    warnings = [i for i in issues if i.level == "warning"]
    infos = [i for i in issues if i.level == "info"]

    for issue in issues:
        prefix = {"error": "ERROR", "warning": "WARN", "info": "INFO"}[issue.level]
        loc = f" [{issue.path}]" if issue.path else ""
        print(f"  {prefix}{loc}: {issue.message}")

    print(f"\n{len(errors)} error(s), {len(warnings)} warning(s), {len(infos)} info(s)")
    if errors:
        sys.exit(1)


def _cmd_gate(args: argparse.Namespace) -> None:
    """Run a quick gate check from CLI."""
    from pyfortis import Order, RiskEngine, Side

    engine = RiskEngine.from_yaml(args.config)

    order = Order(
        order_id=args.order_id or "cli-001",
        instrument=args.instrument,
        side=Side(args.side),
        quantity=float(args.quantity),
        price=float(args.price),
        portfolio=args.portfolio or "default",
    )

    result = engine.validate_order(order)
    print(f"Verdict: {result.verdict.value}")
    print(f"Message: {result.message}")
    if result.breaches:
        print(f"Breaches ({len(result.breaches)}):")
        for b in result.breaches:
            print(f"  [{b.severity.value}] {b.limit_name}: {b.message}")

    if result.is_rejected:
        sys.exit(1)


def main(argv: list[str] | None = None) -> None:
    parser = argparse.ArgumentParser(
        prog="pyfortis",
        description="PyFortis risk engine CLI",
    )
    sub = parser.add_subparsers(dest="command")

    # api
    sub.add_parser("api", help="Print public API")

    # schema
    sub.add_parser("schema", help="Print config schema")

    # validate
    p_val = sub.add_parser("validate", help="Validate a config file")
    p_val.add_argument("config", help="Path to YAML/JSON config")

    # gate
    p_gate = sub.add_parser("gate", help="Run a gate check")
    p_gate.add_argument("config", help="Path to YAML/JSON config")
    p_gate.add_argument("--instrument", required=True)
    p_gate.add_argument("--side", required=True, choices=["buy", "sell"])
    p_gate.add_argument("--quantity", required=True, type=float)
    p_gate.add_argument("--price", required=True, type=float)
    p_gate.add_argument("--order-id", default=None)
    p_gate.add_argument("--portfolio", default="default")

    args = parser.parse_args(argv)

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

    handlers = {
        "api": _cmd_api,
        "schema": _cmd_schema,
        "validate": _cmd_validate,
        "gate": _cmd_gate,
    }
    handlers[args.command](args)


if __name__ == "__main__":
    main()
