#!/usr/bin/env python3
"""
purple_team.py - Red+Blue Orchestration Layer
==============================================

Purple Team role: Orchestrate Red and Blue team activities.
Runs the adversarial/defensive loop for system testing.

Consolidated from:
- receipts/.../re4_lab/purple_team_router__v1.py
- tools/reflex_orchestrator.py concepts

WO#NET_JAZZ_00
"""

from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
from datetime import datetime
from typing import Optional, Dict, Any, Callable
import time

from helix_cdc.reflex.red_team import inject_entropy, entropy_flood
from helix_cdc.reflex.blue_team import monitor_entropy, check_entropy_threshold


@dataclass
class PurpleTeamConfig:
    """Configuration for Purple Team orchestration."""
    log_path: Path = field(default_factory=lambda: Path("/tmp/reflex_purple_test.log"))
    red_inject_count: int = 100
    red_delay: float = 0.005
    blue_threshold: int = 50
    cycles: int = 3
    cycle_delay: float = 0.5


def run_red_blue_cycle(
    config: PurpleTeamConfig,
    on_red_complete: Optional[Callable[[Dict[str, Any]], None]] = None,
    on_blue_alert: Optional[Callable[[Dict[str, Any]], None]] = None,
) -> Dict[str, Any]:
    """
    Run a single Red→Blue cycle.

    1. Red Team injects entropy
    2. Blue Team monitors and fires alert if threshold exceeded

    Args:
        config: Purple team configuration
        on_red_complete: Callback after red team injection
        on_blue_alert: Callback when blue team fires alert

    Returns:
        Dict with cycle results
    """
    cycle_start = time.time()

    # Red Team phase
    red_result = entropy_flood(
        config.log_path,
        count=config.red_inject_count,
        delay=config.red_delay
    )

    if on_red_complete:
        on_red_complete(red_result)

    # Blue Team phase
    blue_result = monitor_entropy(
        config.log_path,
        threshold=config.blue_threshold,
        on_alert=on_blue_alert,
        continuous=False
    )

    cycle_elapsed = time.time() - cycle_start

    return {
        "red": red_result,
        "blue": blue_result,
        "cycle_elapsed_seconds": cycle_elapsed,
        "timestamp": datetime.now().isoformat(),
    }


def dispatch_reflex_loop(
    config: Optional[PurpleTeamConfig] = None,
    on_cycle_complete: Optional[Callable[[int, Dict[str, Any]], None]] = None,
) -> Dict[str, Any]:
    """
    Dispatch full Purple Team reflex loop.

    Runs multiple Red→Blue cycles as configured.

    Args:
        config: Purple team configuration
        on_cycle_complete: Callback with (cycle_num, result) after each cycle

    Returns:
        Dict with full loop results
    """
    if config is None:
        config = PurpleTeamConfig()

    # Clear log for fresh test
    if config.log_path.exists():
        config.log_path.unlink()

    loop_start = time.time()
    cycle_results = []
    alerts_fired = 0

    for i in range(config.cycles):
        def on_alert(result):
            nonlocal alerts_fired
            alerts_fired += 1

        result = run_red_blue_cycle(
            config,
            on_blue_alert=on_alert
        )
        cycle_results.append(result)

        if on_cycle_complete:
            on_cycle_complete(i + 1, result)

        if i < config.cycles - 1:
            time.sleep(config.cycle_delay)

    loop_elapsed = time.time() - loop_start

    return {
        "config": {
            "log_path": str(config.log_path),
            "red_inject_count": config.red_inject_count,
            "blue_threshold": config.blue_threshold,
            "cycles": config.cycles,
        },
        "cycles": cycle_results,
        "total_alerts": alerts_fired,
        "loop_elapsed_seconds": loop_elapsed,
        "timestamp": datetime.now().isoformat(),
        "status": "PASS" if alerts_fired >= config.cycles else "PARTIAL",
    }


# ============================================================================
# CLI
# ============================================================================

def _cli():
    """Purple Team CLI."""
    import argparse
    import json

    parser = argparse.ArgumentParser(description="Purple Team Orchestrator")
    parser.add_argument("--log", type=Path, default=Path("/tmp/reflex_purple_test.log"),
                        help="Log file for testing")
    parser.add_argument("--red-count", type=int, default=100,
                        help="Red team injection count per cycle")
    parser.add_argument("--blue-threshold", type=int, default=50,
                        help="Blue team alert threshold")
    parser.add_argument("--cycles", type=int, default=3,
                        help="Number of Red→Blue cycles")
    parser.add_argument("--json", action="store_true",
                        help="Output JSON result")
    args = parser.parse_args()

    config = PurpleTeamConfig(
        log_path=args.log,
        red_inject_count=args.red_count,
        blue_threshold=args.blue_threshold,
        cycles=args.cycles,
    )

    print("=" * 60)
    print("PURPLE TEAM - Red/Blue Orchestration")
    print("=" * 60)
    print(f"Log: {config.log_path}")
    print(f"Red inject/cycle: {config.red_inject_count}")
    print(f"Blue threshold: {config.blue_threshold}")
    print(f"Cycles: {config.cycles}")
    print()

    def on_cycle(num, result):
        status = "ALERT" if result["blue"]["exceeded"] else "ok"
        print(f"  Cycle {num}: {status} (entropy={result['blue']['count']})")

    result = dispatch_reflex_loop(config, on_cycle_complete=on_cycle)

    print()
    print(f"Result: {result['status']}")
    print(f"Total alerts: {result['total_alerts']}")
    print(f"Elapsed: {result['loop_elapsed_seconds']:.2f}s")

    if args.json:
        print()
        print(json.dumps(result, indent=2))


if __name__ == "__main__":
    _cli()
