"""Swarm intelligence commands for AITBC CLI"""

import click
import httpx
import json
from typing import Optional, Dict, Any, List
from ..utils import output, error, success, warning


@click.group()
def swarm():
    """Swarm intelligence and collective optimization"""
    pass


@swarm.command()
@click.option("--role", required=True, 
              type=click.Choice(["load-balancer", "resource-optimizer", "task-coordinator", "monitor"]),
              help="Swarm role")
@click.option("--capability", required=True, help="Agent capability")
@click.option("--region", help="Operating region")
@click.option("--priority", default="normal", 
              type=click.Choice(["low", "normal", "high"]),
              help="Swarm priority")
@click.pass_context
def join(ctx, role: str, capability: str, region: Optional[str], priority: str):
    """Join agent swarm for collective optimization"""
    config = ctx.obj['config']
    
    swarm_data = {
        "role": role,
        "capability": capability,
        "priority": priority
    }
    
    if region:
        swarm_data["region"] = region
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/swarm/join",
                headers={"X-Api-Key": config.api_key or ""},
                json=swarm_data
            )
            
            if response.status_code == 201:
                result = response.json()
                success(f"Joined swarm: {result['swarm_id']}")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to join swarm: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@swarm.command()
@click.option("--task", required=True, help="Swarm task type")
@click.option("--collaborators", type=int, default=5, help="Number of collaborators")
@click.option("--strategy", default="consensus", 
              type=click.Choice(["consensus", "leader-election", "distributed"]),
              help="Coordination strategy")
@click.option("--timeout", default=3600, help="Task timeout in seconds")
@click.pass_context
def coordinate(ctx, task: str, collaborators: int, strategy: str, timeout: int):
    """Coordinate swarm task execution"""
    config = ctx.obj['config']
    
    coordination_data = {
        "task": task,
        "collaborators": collaborators,
        "strategy": strategy,
        "timeout_seconds": timeout
    }
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/swarm/coordinate",
                headers={"X-Api-Key": config.api_key or ""},
                json=coordination_data
            )
            
            if response.status_code == 202:
                result = response.json()
                success(f"Swarm coordination started: {result['task_id']}")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to start coordination: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@swarm.command()
@click.option("--swarm-id", help="Filter by swarm ID")
@click.option("--status", help="Filter by status")
@click.option("--limit", default=20, help="Number of swarms to list")
@click.pass_context
def list(ctx, swarm_id: Optional[str], status: Optional[str], limit: int):
    """List active swarms"""
    config = ctx.obj['config']
    
    params = {"limit": limit}
    if swarm_id:
        params["swarm_id"] = swarm_id
    if status:
        params["status"] = status
    
    try:
        with httpx.Client() as client:
            response = client.get(
                f"{config.coordinator_url}/v1/swarm/list",
                headers={"X-Api-Key": config.api_key or ""},
                params=params
            )
            
            if response.status_code == 200:
                swarms = response.json()
                output(swarms, ctx.obj['output_format'])
            else:
                error(f"Failed to list swarms: {response.status_code}")
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@swarm.command()
@click.argument("task_id")
@click.option("--real-time", is_flag=True, help="Show real-time progress")
@click.option("--interval", default=10, help="Update interval for real-time monitoring")
@click.pass_context
def status(ctx, task_id: str, real_time: bool, interval: int):
    """Get swarm task status"""
    config = ctx.obj['config']
    
    def get_status():
        try:
            with httpx.Client() as client:
                response = client.get(
                    f"{config.coordinator_url}/v1/swarm/tasks/{task_id}/status",
                    headers={"X-Api-Key": config.api_key or ""}
                )
                
                if response.status_code == 200:
                    return response.json()
                else:
                    error(f"Failed to get task status: {response.status_code}")
                    return None
        except Exception as e:
            error(f"Network error: {e}")
            return None
    
    if real_time:
        click.echo(f"Monitoring swarm task {task_id} (Ctrl+C to stop)...")
        while True:
            status_data = get_status()
            if status_data:
                click.clear()
                click.echo(f"Task ID: {task_id}")
                click.echo(f"Status: {status_data.get('status', 'Unknown')}")
                click.echo(f"Progress: {status_data.get('progress', 0)}%")
                click.echo(f"Collaborators: {status_data.get('active_collaborators', 0)}/{status_data.get('total_collaborators', 0)}")
                
                if status_data.get('status') in ['completed', 'failed', 'cancelled']:
                    break
            
            time.sleep(interval)
    else:
        status_data = get_status()
        if status_data:
            output(status_data, ctx.obj['output_format'])


@swarm.command()
@click.argument("swarm_id")
@click.pass_context
def leave(ctx, swarm_id: str):
    """Leave swarm"""
    config = ctx.obj['config']
    
    if not click.confirm(f"Leave swarm {swarm_id}?"):
        click.echo("Operation cancelled")
        return
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/swarm/{swarm_id}/leave",
                headers={"X-Api-Key": config.api_key or ""}
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Left swarm {swarm_id}")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to leave swarm: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@swarm.command()
@click.argument("task_id")
@click.option("--consensus-threshold", default=0.7, help="Consensus threshold (0.0-1.0)")
@click.pass_context
def consensus(ctx, task_id: str, consensus_threshold: float):
    """Achieve swarm consensus on task result"""
    config = ctx.obj['config']
    
    consensus_data = {
        "consensus_threshold": consensus_threshold
    }
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/swarm/tasks/{task_id}/consensus",
                headers={"X-Api-Key": config.api_key or ""},
                json=consensus_data
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Consensus achieved: {result.get('consensus_reached', False)}")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to achieve consensus: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)
