"""
Phase 103: Dynamic Swarm Roster & Agent Injector

This module allows the Orchestrator to break out of the hardcoded `company_roster.py`.
When a task requires a skill not found in the local roster, the COO can query the 
Brynq Marketplace (via Federation) to discover, download, and dynamically inject 
a specialized Agent Profile (and its tools) into the active Swarm.
"""

import json
import logging
from typing import Optional, Dict, Any
from pathlib import Path
from datetime import datetime, timezone

logger = logging.getLogger("brynq.agent_injector")

# Attempt imports gracefully
try:
    from brynq.company_roster import get_roster as get_local_roster
except ImportError:
    get_local_roster = lambda: {}

try:
    from brynq.federation import list_peers
except ImportError:
    try:
        from brynq._future.federation import list_peers
    except ImportError:
        list_peers = lambda: []


def get_dynamic_roster() -> Dict[str, Any]:
    """
    Get the full roster. This merges the hardcoded company_roster
    with any dynamically downloaded agents currently installed.
    """
    roster = get_local_roster()
    
    # Check for dynamically installed agents
    installed_dir = Path("state/broker/installed_agents")
    if installed_dir.exists():
        for f in installed_dir.glob("*.json"):
            try:
                agent_data = json.loads(f.read_text("utf-8"))
                agent_key = agent_data.get("id", f.stem)
                # Overwrite or append to local roster
                roster[agent_key] = agent_data
            except Exception as e:
                logger.error(f"Failed to load dynamic agent {f}: {e}")
                
    return roster


def discover_and_inject_agent(missing_skill: str, max_cost: float = 0.0) -> Optional[str]:
    """
    The core dynamic injection routine.
    1. The COO realizes it lacks `missing_skill`.
    2. Queries the Federation/Marketplace for an agent with this skill.
    3. Downloads the agent profile.
    4. Saves it locally so the Orchestrator can spawn it.
    
    Returns the dynamic agent_key if successful, None otherwise.
    """
    logger.info(f"Dynamic Roster: Searching marketplace for skill '{missing_skill}'...")
    
    # In a real environment, this would do an HTTP GET to a central registry
    # or federated peers to find the agent profile.
    # We will simulate a federated discovery for the purpose of the prototype:
    
    simulated_marketplace = {
        "unreal_engine_5_graphics_expert": {
            "title": "Unreal Engine 5 Graphics Expert",
            "division": "External Consultants",
            "description": "A dynamically downloaded expert in UE5 blueprints and C++.",
            "skills": ["unreal_engine", "cpp", "graphics", missing_skill],
            "tools": ["read_file", "write_file", "run_shell_command"],
            "prompt": "You are a senior Unreal Engine 5 technical artist. Write highly optimized C++ and dictate blueprint structures."
        },
        "senior_django_security_auditor": {
            "title": "Senior Django Security Auditor",
            "division": "External Consultants",
            "description": "Specializes in tearing apart Django ORM queries to find SQLi.",
            "skills": ["django", "python", "security", missing_skill],
            "tools": ["read_file", "grep_search", "run_shell_command"],
            "prompt": "You are a Django security expert. Audit the code specifically looking for ORM leaks and CSRF vulnerabilities."
        }
    }
    
    # Simple search
    best_match = None
    best_key = None
    for key, profile in simulated_marketplace.items():
        if missing_skill.lower() in [s.lower() for s in profile.get("skills", [])]:
            best_match = profile
            best_key = key
            break
            
    if not best_match:
        logger.warning(f"Dynamic Roster: No agent found in marketplace for skill '{missing_skill}'.")
        return None
        
    # Install the agent locally
    logger.info(f"Dynamic Roster: Found '{best_match['title']}'. Installing...")
    
    installed_dir = Path("state/broker/installed_agents")
    installed_dir.mkdir(parents=True, exist_ok=True)
    
    best_match["installed_at"] = datetime.now(timezone.utc).isoformat()
    best_match["source"] = "brynq_marketplace"
    
    file_path = installed_dir / f"{best_key}.json"
    file_path.write_text(json.dumps(best_match, indent=2))
    
    logger.info(f"Dynamic Roster: Successfully injected '{best_key}' into the local roster.")
    return best_key
