import argparse
import json
from ai_testing_swarm.orchestrator import SwarmOrchestrator
from ai_testing_swarm.core.curl_parser import parse_curl


def normalize_request(payload: dict) -> dict:
    """Normalize input into execution-ready request.

    Supported formats:
    1) { "curl": "curl ..." }
    2) { "method": "...", "url": "...", "headers": {...}, "body": {...} }
    3) OpenAPI-driven (optional):
       {
         "openapi": "./openapi.json" | "https://.../openapi.json",
         "path": "/pets",
         "method": "GET",
         "headers": {...},
         "path_params": {...},
         "query_params": {...},
         "body": {...}
       }
    """

    # Case 1: raw curl input
    if "curl" in payload:
        return parse_curl(payload["curl"])

    # Case 3: OpenAPI
    if "openapi" in payload:
        from ai_testing_swarm.core.openapi_loader import load_openapi, build_request_from_openapi

        spec = load_openapi(payload["openapi"])
        req = build_request_from_openapi(
            spec,
            path=payload["path"],
            method=payload["method"],
            headers=payload.get("headers") or {},
            path_params=payload.get("path_params") or {},
            query_params=payload.get("query_params") or {},
            body=payload.get("body"),
        )
        # Attach OpenAPI context for optional response validation/reporting.
        req["_openapi"] = {
            "source": payload["openapi"],
            "path": payload["path"],
            "method": str(payload["method"]).upper(),
            "spec": spec,
        }
        return req

    # Case 2: already normalized
    required_keys = {"method", "url"}
    if required_keys.issubset(payload.keys()):
        return payload

    raise ValueError(
        "Invalid input format.\n"
        "Expected either:\n"
        "1) { \"curl\": \"curl ...\" }\n"
        "2) { \"method\": \"POST\", \"url\": \"...\", \"headers\": {}, \"body\": {} }\n"
        "3) { \"openapi\": \"...\", \"path\": \"/x\", \"method\": \"GET\" }"
    )


def main():
    parser = argparse.ArgumentParser(
        description="AI Testing Swarm CLI (advanced API mutation testing)",
        epilog=(
            "Environment toggles (optional):\n"
            "  AI_SWARM_WORKERS=5            Parallel workers\n"
            "  AI_SWARM_MAX_TESTS=80         Max tests per run\n"
            "  AI_SWARM_RETRY_COUNT=1        Retries on transient failures\n"
            "  AI_SWARM_RETRY_BACKOFF_MS=250 Backoff base\n"
            "  AI_SWARM_RPS=0                Throttle (requests/sec), 0=off\n"
            "  AI_SWARM_SLA_MS=2000          Slow-test threshold\n"
            "  AI_SWARM_USE_OPENAI=1         Enable OpenAI augmentation\n"
            "  AI_SWARM_MAX_AI_TESTS=20      Extra AI-generated tests\n"
            "  AI_SWARM_AI_SUMMARY=1         Add AI summary to report\n"
            "  AI_SWARM_OPENAI_MODEL=...     Model name\n"
            "  OPENAI_API_KEY=...            Required if OpenAI enabled\n"
            "  AI_SWARM_OPENAPI_BASE_URL=... Override OpenAPI servers[]\n"
        ),
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    from ai_testing_swarm import __version__

    parser.add_argument("--version", action="version", version=f"ai-testing-swarm {__version__}")

    parser.add_argument(
        "--input",
        required=True,
        help="Path to request.json"
    )

    parser.add_argument(
        "--public-only",
        action="store_true",
        help="Safety: allow only public test hosts (httpbin/postman-echo/reqres) for this run",
    )

    parser.add_argument(
        "--report-format",
        default="json",
        choices=["json", "md", "html"],
        help="Report format to write (default: json)",
    )

    # Batch1: risk gate thresholds (backward compatible defaults)
    parser.add_argument(
        "--gate-warn",
        type=int,
        default=30,
        help="Gate WARN threshold for endpoint risk score (default: 30)",
    )
    parser.add_argument(
        "--gate-block",
        type=int,
        default=80,
        help="Gate BLOCK threshold for endpoint risk score (default: 80)",
    )

    args = parser.parse_args()

    # ------------------------------------------------------------
    # Load input JSON
    # ------------------------------------------------------------
    with open(args.input) as f:
        payload = json.load(f)

    # ------------------------------------------------------------
    # 🔴 NORMALIZE INPUT (THIS FIXES YOUR ERROR)
    # ------------------------------------------------------------
    request = normalize_request(payload)

    # ------------------------------------------------------------
    # Run swarm
    # ------------------------------------------------------------
    if args.public_only:
        import os
        os.environ["AI_SWARM_PUBLIC_ONLY"] = "1"

    decision, results = SwarmOrchestrator().run(
        request,
        report_format=args.report_format,
        gate_warn=args.gate_warn,
        gate_block=args.gate_block,
    )

    # ------------------------------------------------------------
    # Console output
    # ------------------------------------------------------------
    print("\n=== RELEASE DECISION ===")
    print(decision)

    print("\n=== TEST RESULTS ===")
    for r in results:
        response = r.get("response", {})
        status_code = response.get("status_code")

        print(
            f"{r.get('name'):25} "
            f"{str(status_code):5} "
            f"{r.get('reason')}"
        )


if __name__ == "__main__":
    main()
