import pytest
import httpx
import os
import time
import json
from conftest import BASE_URL

def _headers():
    uid = os.getenv("SYNC_TEST_USER_ID", "9a333ccd-9c3f-432f-a030-7b1e1284a436")
    return {"X-User-ID": uid}

@pytest.mark.slow
def test_coworker_full_journey():
    """
    CO-WORKER FULL JOURNEY INTEGRATION TEST:
    1. Deploy agent with High Threshold (95%) to force rework.
    2. Trigger via webhook.
    3. Monitor 'evaluation_status' for real-time indicators.
    4. Verify 'latest_quality_score' changes across attempts.
    5. Audit .cortex/history.log for:
       - 'duration' fields for every step.
       - 'type': 'attempt' entries for rework tracking.
       - 'type': 'event' entries for Rubric/Agent execution.
    6. Ensure final result is delivered successfully.
    """
    node_id = os.getenv("SYNC_TEST_NODE1", "test-node-1")
    admin_id = os.getenv("SYNC_TEST_USER_ID", "9a333ccd-9c3f-432f-a030-7b1e1284a436")
    instance_id = None
    
    # We use a prompt that is simple but specific to ensure we can verify correctness
    test_prompt = "Create a file named 'secret.txt' containing the word 'PHOENIX'. Then verify it exists."
    
    with httpx.Client(timeout=60.0) as client:
        try:
            # 1. Register Node (noop if exists, but ensures it's in DB for this user)
            client.post(f"{BASE_URL}/nodes/admin", params={"admin_id": admin_id}, json={
                "node_id": node_id, "is_active": True, "skill_config": {"shell": {"enabled": True}, "sync": {"enabled": True}}
            })

            # 2. Deploy Agent with High Threshold
            deploy_payload = {
                "name": "Full Journey Agent",
                "system_prompt": "You are an infrastructure specialist.",
                "max_loop_iterations": 5,
                "mesh_node_id": node_id,
                "provider_name": "gemini",
                "model_name": "gemini-3-flash-preview",
                "trigger_type": "webhook",
                "co_worker_quality_gate": True,
                "max_rework_attempts": 2,
                "rework_threshold": 101, # Impossible to pass to force multiple rework rounds
                "default_prompt": test_prompt,
            }
            r_deploy = client.post(f"{BASE_URL}/agents/deploy", json=deploy_payload, headers=_headers())
            assert r_deploy.status_code == 200, f"Deploy failed: {r_deploy.text}"
            res = r_deploy.json()
            instance_id = res["instance_id"]
            sync_workspace_id = res["sync_workspace_id"]

            # 3. Trigger it
            r_trig = client.get(f"{BASE_URL}/agents/{instance_id}/triggers", headers=_headers())
            secret = next(t for t in r_trig.json() if t["trigger_type"] == "webhook")["webhook_secret"]
            client.post(f"{BASE_URL}/agents/{instance_id}/webhook", params={"token": secret}, json={"prompt": test_prompt})

            # 4. Monitor & Track Journey
            print(f"\n[Journey] Starting tracking for Agent {instance_id}")
            seen_statuses = set()
            scores_log = []
            max_wait = 300 # 5 minutes total for a slow rework journey
            start_time = time.time()
            
            while time.time() - start_time < max_wait:
                r_agents = client.get(f"{BASE_URL}/agents", headers=_headers())
                agent = next((a for a in r_agents.json() if a["id"] == instance_id), None)
                if not agent: break
                
                status = agent.get("status")
                eval_status = agent.get("evaluation_status")
                score = agent.get("latest_quality_score")
                
                if eval_status: seen_statuses.add(eval_status)
                if score and (not scores_log or scores_log[-1] != score):
                    scores_log.append(score)
                    print(f"  [Metric] Quality Score updated: {score}%")

                if eval_status:
                    print(f"  [Status] {eval_status}")

                # Terminal conditions:
                if status == "idle" and eval_status in ["passed", "failed_limit"]:
                    print(f"  [Journey] Terminal state reached: {eval_status}")
                    break
                
                if status == "error_suspended":
                    pytest.fail(f"Agent failed with error: {agent.get('last_error')}")
                
                time.sleep(3)

            # 5. Assertions on the Journey
            # We expect to see various statuses throughout the loop
            print(f"Seen statuses: {seen_statuses}")
            # Minimum expected statuses to prove the loop happened
            assert any("Auditing" in s for s in seen_statuses) or any("Analyzing" in s for s in seen_statuses), "Should have seen an Auditing/Analysis phase"
            
            # Check if rework happened (should have if score < 98)
            if any("Rework" in s for s in seen_statuses):
                print("  [Verified] Rework loop was triggered.")
            
            # 6. Content Audit (The history.log on the node)
            print(f"[test] Polling .cortex/history.log on node {node_id}...")
            history = []
            for _ in range(30): # 60s timeout
                r_hist = client.get(f"{BASE_URL}/nodes/{node_id}/fs/cat", params={"path": ".cortex/history.log", "session_id": sync_workspace_id}, headers=_headers())
                if r_hist.status_code == 200:
                    history = json.loads(r_hist.json().get("stdout", "[]"))
                    if len(history) > 0:
                        break
                time.sleep(2)
                
            assert len(history) > 0, "history.log should not be empty"
            
            # Verify Duration Tracking (Timespan Capture)
            for entry in history:
                name = entry.get("name") or entry.get("type")
                duration = entry.get("duration", 0)
                print(f"  [Audit] Step '{name}' took {duration}s")
                assert duration >= 0, f"Step {name} has invalid duration: {duration}"
                
            # Verify specific entries
            has_rubric = any(e.get("name") == "Rubric Generation" for e in history)
            has_agent_run = any(e.get("name") == "Agent execution" for e in history)
            has_audit = any(e.get("name") == "Co-Worker review" for e in history)
            
            assert has_rubric, "Rubric generation not logged"
            assert has_agent_run, "Agent execution not logged"
            assert has_audit, "Audit pass not logged"

            # 7. Final Sanity Check for the generated file
            r_ls = client.get(f"{BASE_URL}/nodes/{node_id}/fs/ls", params={"path": ".", "session_id": sync_workspace_id}, headers=_headers())
            files = [f["name"] for f in r_ls.json().get("files", [])]
            assert "secret.txt" in files, "The agent failed to create the requested file."

        finally:
            if instance_id:
                client.delete(f"{BASE_URL}/agents/{instance_id}", headers=_headers())
