"""``penbot purple`` — purple-team defense simulation CLI."""

from __future__ import annotations

import asyncio
import json
from pathlib import Path
from typing import Any

from src.utils.logging import get_logger

logger = get_logger(__name__)


def run_purple(args: Any) -> None:
    """Entry-point for ``penbot purple``."""
    asyncio.run(_run_purple_async(args))


async def _run_purple_async(args: Any) -> None:
    from src.defense.simulator import DefenseSimulator

    session_path = _resolve_session(args)
    if not session_path:
        return

    with open(session_path) as f:
        session = json.load(f)

    findings = session.get("security_findings", [])
    attacks = session.get("attack_attempts", [])

    if not findings:
        print("\nNo findings in session — nothing to simulate defenses against.\n")
        return

    connector = _build_connector(session)
    if connector is None:
        print("\nCould not create target connector. Running in offline mode (no live re-test).\n")
        connector = _OfflineConnector()

    print(f"\n{'='*60}")
    print("  PURPLE-TEAM DEFENSE SIMULATION")
    print(f"{'='*60}")
    print(f"  Session: {session.get('test_session_id', 'unknown')}")
    print(f"  Findings: {len(findings)}")
    print(f"  Attacks: {len(attacks)}")
    print(f"{'='*60}\n")

    simulator = DefenseSimulator(connector=connector)
    report = await simulator.run(findings, attacks)

    _print_report(report)

    if hasattr(args, "output") and args.output:
        out_path = Path(args.output)
        out_path.write_text(report.model_dump_json(indent=2))
        print(f"\nReport saved to {out_path}\n")


def _resolve_session(args: Any) -> Path | None:
    session_id = getattr(args, "session", None)
    use_latest = getattr(args, "latest", False)

    sessions_dir = Path("sessions")
    if not sessions_dir.exists():
        print("No sessions directory found.")
        return None

    if use_latest or not session_id:
        files = sorted(sessions_dir.glob("*.json"), key=lambda p: p.stat().st_mtime, reverse=True)
        if not files:
            print("No sessions found.")
            return None
        return files[0]

    direct = sessions_dir / f"{session_id}.json"
    if direct.exists():
        return direct

    for p in sessions_dir.glob("*.json"):
        if session_id in p.stem:
            return p

    print(f"Session '{session_id}' not found.")
    return None


def _build_connector(session: dict) -> Any | None:
    try:
        config = session.get("target_config", {})
        target_type = session.get("target_type", config.get("type", ""))

        if target_type == "api" or config.get("endpoint"):
            from src.connectors.api_connector import APITargetConnector

            return APITargetConnector(
                endpoint=config.get("endpoint", ""),
                api_key=config.get("api_key"),
            )
    except Exception:
        pass
    return None


class _OfflineConnector:
    """Stand-in connector when the real target is not available."""

    async def send_message(self, message: str, context: dict | None = None) -> dict:
        return {"content": "[OFFLINE — cannot re-test live target]"}


def _print_report(report: Any) -> None:
    print(f"  Findings tested: {report.total_findings}")
    print(f"  Mitigated:       {report.findings_mitigated}")
    print(f"  Unmitigated:     {report.findings_unmitigated}")
    print(f"  Mitigation rate: {report.mitigation_rate:.0%}")
    print()

    if report.recommended_defenses:
        print("  RECOMMENDED DEFENSES:")
        for rec in report.recommended_defenses:
            blocked = rec["attacks_blocked"]
            tested = rec["attacks_tested"]
            eff = rec["effectiveness"]
            print(f"    - {rec['defense']}: {eff} effective ({blocked}/{tested} blocked)")
            print(f"      {rec['description']}")
        print()

    if report.verifications:
        print("  VERIFICATION DETAILS:")
        for v in report.verifications:
            status = "BLOCKED" if v.blocked else "NOT BLOCKED"
            print(f"    [{status}] {v.finding_category} ({v.finding_severity}) → {v.defense_name}")
        print()
