from ai_testing_swarm.agents.test_planner_agent import TestPlannerAgent
from ai_testing_swarm.agents.execution_agent import ExecutionAgent
from ai_testing_swarm.agents.llm_reasoning_agent import LLMReasoningAgent
from ai_testing_swarm.agents.learning_agent import LearningAgent
from ai_testing_swarm.agents.release_gate_agent import ReleaseGateAgent
from ai_testing_swarm.reporting.report_writer import write_report

import logging

logger = logging.getLogger(__name__)
EXPECTED_FAILURES = {
    "success",
    "missing_param",
    "invalid_param",
    "security",
}

class SwarmOrchestrator:
    """
    Central brain of the AI Testing Swarm.
    """

    def __init__(self):
        self.planner = TestPlannerAgent()
        self.executor = ExecutionAgent()
        self.reasoner = LLMReasoningAgent()
        self.learner = LearningAgent()
        self.release_gate = ReleaseGateAgent()

    def run(self, request: dict):
        """
        Runs the full AI testing swarm and returns:
        - release decision
        - full test results
        """

        # --------------------------------------------------------
        # 1️⃣ PLAN TESTS
        # --------------------------------------------------------
        tests = self.planner.plan(request)
        results = []

        logger.info("🧠 Planned %d tests", len(tests))

        # --------------------------------------------------------
        # 2️⃣ EXECUTE + CLASSIFY
        # --------------------------------------------------------
        for test in tests:
            test_name = test.get("name")

            # Execute request with mutation (or baseline)
            execution_result = self.executor.execute(request, test)

            # 🔒 GUARANTEE name is always present
            execution_result["name"] = test_name

            # Classify result (LLM / rules)
            classification = self.reasoner.reason(execution_result)

            # Merge classification into execution result
            execution_result.update({
                "reason": classification.get("type"),
                "confidence": classification.get("confidence", 1.0),
                "failure_type": classification.get("type"),
                "status": (
                    "PASSED"
                    # if classification.get("type") == "success"
                    if classification["type"] in EXPECTED_FAILURES
                    else "FAILED"
                ),
            })

            results.append(execution_result)

            # Optional learning step
            try:
                self.learner.learn(test_name, classification)
            except Exception as e:
                logger.warning("⚠️ Learning skipped for %s: %s", test_name, e)

        # --------------------------------------------------------
        # 3️⃣ WRITE JSON REPORT (ONCE, ONLY ONCE)
        # --------------------------------------------------------
        report_path = write_report(request, results)
        logger.info("📄 Swarm JSON report written to: %s", report_path)
        print(f"📄 Swarm JSON report written to: {report_path}")

        # --------------------------------------------------------
        # 4️⃣ RELEASE DECISION
        # --------------------------------------------------------
        decision = self.release_gate.decide(results)

        return decision, results
