"""OpenClaw integration commands for AITBC CLI"""

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


@click.group()
def openclaw():
    """OpenClaw integration with edge computing deployment"""
    pass


@click.group()
def deploy():
    """Agent deployment operations"""
    pass


openclaw.add_command(deploy)


@deploy.command()
@click.argument("agent_id")
@click.option("--region", required=True, help="Deployment region")
@click.option("--instances", default=1, help="Number of instances to deploy")
@click.option("--instance-type", default="standard", help="Instance type")
@click.option("--edge-locations", help="Comma-separated edge locations")
@click.option("--auto-scale", is_flag=True, help="Enable auto-scaling")
@click.pass_context
def deploy(ctx, agent_id: str, region: str, instances: int, instance_type: str, 
           edge_locations: Optional[str], auto_scale: bool):
    """Deploy agent to OpenClaw network"""
    config = ctx.obj['config']
    
    deployment_data = {
        "agent_id": agent_id,
        "region": region,
        "instances": instances,
        "instance_type": instance_type,
        "auto_scale": auto_scale
    }
    
    if edge_locations:
        deployment_data["edge_locations"] = [loc.strip() for loc in edge_locations.split(',')]
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/deploy",
                headers={"X-Api-Key": config.api_key or ""},
                json=deployment_data
            )
            
            if response.status_code == 202:
                deployment = response.json()
                success(f"Agent deployment started: {deployment['id']}")
                output(deployment, ctx.obj['output_format'])
            else:
                error(f"Failed to start deployment: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@deploy.command()
@click.argument("deployment_id")
@click.option("--instances", required=True, type=int, help="New number of instances")
@click.option("--auto-scale", is_flag=True, help="Enable auto-scaling")
@click.option("--min-instances", default=1, help="Minimum instances for auto-scaling")
@click.option("--max-instances", default=10, help="Maximum instances for auto-scaling")
@click.pass_context
def scale(ctx, deployment_id: str, instances: int, auto_scale: bool, min_instances: int, max_instances: int):
    """Scale agent deployment"""
    config = ctx.obj['config']
    
    scale_data = {
        "instances": instances,
        "auto_scale": auto_scale,
        "min_instances": min_instances,
        "max_instances": max_instances
    }
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/deployments/{deployment_id}/scale",
                headers={"X-Api-Key": config.api_key or ""},
                json=scale_data
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Deployment scaled successfully")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to scale deployment: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@deploy.command()
@click.argument("deployment_id")
@click.option("--objective", default="cost", 
              type=click.Choice(["cost", "performance", "latency", "efficiency"]),
              help="Optimization objective")
@click.pass_context
def optimize(ctx, deployment_id: str, objective: str):
    """Optimize agent deployment"""
    config = ctx.obj['config']
    
    optimization_data = {"objective": objective}
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/deployments/{deployment_id}/optimize",
                headers={"X-Api-Key": config.api_key or ""},
                json=optimization_data
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Deployment optimization completed")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to optimize deployment: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@click.group()
def monitor():
    """OpenClaw monitoring operations"""
    pass


openclaw.add_command(monitor)


@monitor.command()
@click.argument("deployment_id")
@click.option("--metrics", default="latency,cost", help="Comma-separated metrics to monitor")
@click.option("--real-time", is_flag=True, help="Show real-time metrics")
@click.option("--interval", default=10, help="Update interval for real-time monitoring")
@click.pass_context
def monitor(ctx, deployment_id: str, metrics: str, real_time: bool, interval: int):
    """Monitor OpenClaw agent performance"""
    config = ctx.obj['config']
    
    params = {"metrics": [m.strip() for m in metrics.split(',')]}
    
    def get_metrics():
        try:
            with httpx.Client() as client:
                response = client.get(
                    f"{config.coordinator_url}/v1/openclaw/deployments/{deployment_id}/metrics",
                    headers={"X-Api-Key": config.api_key or ""},
                    params=params
                )
                
                if response.status_code == 200:
                    return response.json()
                else:
                    error(f"Failed to get metrics: {response.status_code}")
                    return None
        except Exception as e:
            error(f"Network error: {e}")
            return None
    
    if real_time:
        click.echo(f"Monitoring deployment {deployment_id} (Ctrl+C to stop)...")
        while True:
            metrics_data = get_metrics()
            if metrics_data:
                click.clear()
                click.echo(f"Deployment ID: {deployment_id}")
                click.echo(f"Status: {metrics_data.get('status', 'Unknown')}")
                click.echo(f"Instances: {metrics_data.get('instances', 'N/A')}")
                
                metrics_list = metrics_data.get('metrics', {})
                for metric in [m.strip() for m in metrics.split(',')]:
                    if metric in metrics_list:
                        value = metrics_list[metric]
                        click.echo(f"{metric.title()}: {value}")
                
                if metrics_data.get('status') in ['terminated', 'failed']:
                    break
            
            time.sleep(interval)
    else:
        metrics_data = get_metrics()
        if metrics_data:
            output(metrics_data, ctx.obj['output_format'])


@monitor.command()
@click.argument("deployment_id")
@click.pass_context
def status(ctx, deployment_id: str):
    """Get deployment status"""
    config = ctx.obj['config']
    
    try:
        with httpx.Client() as client:
            response = client.get(
                f"{config.coordinator_url}/v1/openclaw/deployments/{deployment_id}/status",
                headers={"X-Api-Key": config.api_key or ""}
            )
            
            if response.status_code == 200:
                status_data = response.json()
                output(status_data, ctx.obj['output_format'])
            else:
                error(f"Failed to get deployment status: {response.status_code}")
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@click.group()
def edge():
    """Edge computing operations"""
    pass


openclaw.add_command(edge)


@edge.command()
@click.argument("agent_id")
@click.option("--locations", required=True, help="Comma-separated edge locations")
@click.option("--strategy", default="latency", 
              type=click.Choice(["latency", "cost", "availability", "hybrid"]),
              help="Edge deployment strategy")
@click.option("--replicas", default=1, help="Number of replicas per location")
@click.pass_context
def deploy(ctx, agent_id: str, locations: str, strategy: str, replicas: int):
    """Deploy agent to edge locations"""
    config = ctx.obj['config']
    
    edge_data = {
        "agent_id": agent_id,
        "locations": [loc.strip() for loc in locations.split(',')],
        "strategy": strategy,
        "replicas": replicas
    }
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/edge/deploy",
                headers={"X-Api-Key": config.api_key or ""},
                json=edge_data
            )
            
            if response.status_code == 202:
                deployment = response.json()
                success(f"Edge deployment started: {deployment['id']}")
                output(deployment, ctx.obj['output_format'])
            else:
                error(f"Failed to start edge deployment: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@edge.command()
@click.option("--location", help="Filter by location")
@click.pass_context
def resources(ctx, location: Optional[str]):
    """Manage edge resources"""
    config = ctx.obj['config']
    
    params = {}
    if location:
        params["location"] = location
    
    try:
        with httpx.Client() as client:
            response = client.get(
                f"{config.coordinator_url}/v1/openclaw/edge/resources",
                headers={"X-Api-Key": config.api_key or ""},
                params=params
            )
            
            if response.status_code == 200:
                resources = response.json()
                output(resources, ctx.obj['output_format'])
            else:
                error(f"Failed to get edge resources: {response.status_code}")
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@edge.command()
@click.argument("deployment_id")
@click.option("--latency-target", type=int, help="Target latency in milliseconds")
@click.option("--cost-budget", type=float, help="Cost budget")
@click.option("--availability", type=float, help="Target availability (0.0-1.0)")
@click.pass_context
def optimize(ctx, deployment_id: str, latency_target: Optional[int], 
           cost_budget: Optional[float], availability: Optional[float]):
    """Optimize edge deployment performance"""
    config = ctx.obj['config']
    
    optimization_data = {}
    if latency_target:
        optimization_data["latency_target_ms"] = latency_target
    if cost_budget:
        optimization_data["cost_budget"] = cost_budget
    if availability:
        optimization_data["availability_target"] = availability
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/edge/deployments/{deployment_id}/optimize",
                headers={"X-Api-Key": config.api_key or ""},
                json=optimization_data
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Edge optimization completed")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to optimize edge deployment: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@edge.command()
@click.argument("deployment_id")
@click.option("--standards", help="Comma-separated compliance standards")
@click.pass_context
def compliance(ctx, deployment_id: str, standards: Optional[str]):
    """Check edge security compliance"""
    config = ctx.obj['config']
    
    params = {}
    if standards:
        params["standards"] = [s.strip() for s in standards.split(',')]
    
    try:
        with httpx.Client() as client:
            response = client.get(
                f"{config.coordinator_url}/v1/openclaw/edge/deployments/{deployment_id}/compliance",
                headers={"X-Api-Key": config.api_key or ""},
                params=params
            )
            
            if response.status_code == 200:
                compliance_data = response.json()
                output(compliance_data, ctx.obj['output_format'])
            else:
                error(f"Failed to check compliance: {response.status_code}")
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@click.group()
def routing():
    """Agent skill routing and job offloading"""
    pass


openclaw.add_command(routing)


@routing.command()
@click.argument("deployment_id")
@click.option("--algorithm", default="load-balanced", 
              type=click.Choice(["load-balanced", "skill-based", "cost-based", "latency-based"]),
              help="Routing algorithm")
@click.option("--weights", help="Comma-separated weights for routing factors")
@click.pass_context
def optimize(ctx, deployment_id: str, algorithm: str, weights: Optional[str]):
    """Optimize agent skill routing"""
    config = ctx.obj['config']
    
    routing_data = {"algorithm": algorithm}
    if weights:
        routing_data["weights"] = [w.strip() for w in weights.split(',')]
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/routing/deployments/{deployment_id}/optimize",
                headers={"X-Api-Key": config.api_key or ""},
                json=routing_data
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Routing optimization completed")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to optimize routing: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@routing.command()
@click.argument("deployment_id")
@click.pass_context
def status(ctx, deployment_id: str):
    """Get routing status and statistics"""
    config = ctx.obj['config']
    
    try:
        with httpx.Client() as client:
            response = client.get(
                f"{config.coordinator_url}/v1/openclaw/routing/deployments/{deployment_id}/status",
                headers={"X-Api-Key": config.api_key or ""}
            )
            
            if response.status_code == 200:
                status_data = response.json()
                output(status_data, ctx.obj['output_format'])
            else:
                error(f"Failed to get routing status: {response.status_code}")
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@click.group()
def ecosystem():
    """OpenClaw ecosystem development"""
    pass


openclaw.add_command(ecosystem)


@ecosystem.command()
@click.option("--name", required=True, help="Solution name")
@click.option("--type", required=True, 
              type=click.Choice(["agent", "workflow", "integration", "tool"]),
              help="Solution type")
@click.option("--description", default="", help="Solution description")
@click.option("--package", type=click.File('rb'), help="Solution package file")
@click.pass_context
def create(ctx, name: str, type: str, description: str, package):
    """Create OpenClaw ecosystem solution"""
    config = ctx.obj['config']
    
    solution_data = {
        "name": name,
        "type": type,
        "description": description
    }
    
    files = {}
    if package:
        files["package"] = package.read()
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/ecosystem/solutions",
                headers={"X-Api-Key": config.api_key or ""},
                data=solution_data,
                files=files
            )
            
            if response.status_code == 201:
                solution = response.json()
                success(f"OpenClaw solution created: {solution['id']}")
                output(solution, ctx.obj['output_format'])
            else:
                error(f"Failed to create solution: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


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


@ecosystem.command()
@click.argument("solution_id")
@click.pass_context
def install(ctx, solution_id: str):
    """Install OpenClaw ecosystem solution"""
    config = ctx.obj['config']
    
    try:
        with httpx.Client() as client:
            response = client.post(
                f"{config.coordinator_url}/v1/openclaw/ecosystem/solutions/{solution_id}/install",
                headers={"X-Api-Key": config.api_key or ""}
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Solution installed successfully")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to install solution: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)


@openclaw.command()
@click.argument("deployment_id")
@click.pass_context
def terminate(ctx, deployment_id: str):
    """Terminate OpenClaw deployment"""
    config = ctx.obj['config']
    
    if not click.confirm(f"Terminate deployment {deployment_id}? This action cannot be undone."):
        click.echo("Operation cancelled")
        return
    
    try:
        with httpx.Client() as client:
            response = client.delete(
                f"{config.coordinator_url}/v1/openclaw/deployments/{deployment_id}",
                headers={"X-Api-Key": config.api_key or ""}
            )
            
            if response.status_code == 200:
                result = response.json()
                success(f"Deployment {deployment_id} terminated")
                output(result, ctx.obj['output_format'])
            else:
                error(f"Failed to terminate deployment: {response.status_code}")
                if response.text:
                    error(response.text)
                ctx.exit(1)
    except Exception as e:
        error(f"Network error: {e}")
        ctx.exit(1)
