"""
Agent Integration and Deployment Framework for Verifiable AI Agent Orchestration
Integrates agent orchestration with existing ML ZK proof system and provides deployment tools
"""

import asyncio
import json
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any
from uuid import uuid4
from enum import Enum

from sqlmodel import Session, select, update, delete, SQLModel, Field, Column, JSON
from sqlalchemy.exc import SQLAlchemyError

from ..domain.agent import (
    AIAgentWorkflow, AgentExecution, AgentStepExecution,
    AgentStatus, VerificationLevel
)
from ..services.agent_service import AIAgentOrchestrator, AgentStateManager
from ..services.agent_security import AgentSecurityManager, AgentAuditor, SecurityLevel, AuditEventType
# Mock ZKProofService for testing
class ZKProofService:
    """Mock ZK proof service for testing"""
    def __init__(self, session):
        self.session = session
    
    async def generate_zk_proof(self, circuit_name: str, inputs: Dict[str, Any]) -> Dict[str, Any]:
        """Mock ZK proof generation"""
        return {
            "proof_id": f"proof_{uuid4().hex[:8]}",
            "circuit_name": circuit_name,
            "inputs": inputs,
            "proof_size": 1024,
            "generation_time": 0.1
        }
    
    async def verify_proof(self, proof_id: str) -> Dict[str, Any]:
        """Mock ZK proof verification"""
        return {
            "verified": True,
            "verification_time": 0.05,
            "details": {"mock": True}
        }

logger = logging.getLogger(__name__)


class DeploymentStatus(str, Enum):
    """Deployment status enumeration"""
    PENDING = "pending"
    DEPLOYING = "deploying"
    DEPLOYED = "deployed"
    FAILED = "failed"
    RETRYING = "retrying"
    TERMINATED = "terminated"


class AgentDeploymentConfig(SQLModel, table=True):
    """Configuration for agent deployment"""
    
    __tablename__ = "agent_deployment_configs"
    
    id: str = Field(default_factory=lambda: f"deploy_{uuid4().hex[:8]}", primary_key=True)
    
    # Deployment metadata
    workflow_id: str = Field(index=True)
    deployment_name: str = Field(max_length=100)
    description: str = Field(default="")
    version: str = Field(default="1.0.0")
    
    # Deployment targets
    target_environments: List[str] = Field(default_factory=list, sa_column=Column(JSON))
    deployment_regions: List[str] = Field(default_factory=list, sa_column=Column(JSON))
    
    # Resource requirements
    min_cpu_cores: float = Field(default=1.0)
    min_memory_mb: int = Field(default=1024)
    min_storage_gb: int = Field(default=10)
    requires_gpu: bool = Field(default=False)
    gpu_memory_mb: Optional[int] = Field(default=None)
    
    # Scaling configuration
    min_instances: int = Field(default=1)
    max_instances: int = Field(default=5)
    auto_scaling: bool = Field(default=True)
    scaling_policy: Dict[str, Any] = Field(default_factory=dict, sa_column=Column(JSON))
    
    # Health checks
    health_check_endpoint: str = Field(default="/health")
    health_check_interval: int = Field(default=30)  # seconds
    health_check_timeout: int = Field(default=10)  # seconds
    max_failures: int = Field(default=3)
    
    # Deployment settings
    rollout_strategy: str = Field(default="rolling")  # rolling, blue-green, canary
    rollback_enabled: bool = Field(default=True)
    deployment_timeout: int = Field(default=1800)  # seconds
    
    # Monitoring
    enable_metrics: bool = Field(default=True)
    enable_logging: bool = Field(default=True)
    enable_tracing: bool = Field(default=False)
    log_level: str = Field(default="INFO")
    
    # Status
    status: DeploymentStatus = Field(default=DeploymentStatus.PENDING)
    deployment_time: Optional[datetime] = Field(default=None)
    last_health_check: Optional[datetime] = Field(default=None)
    
    # Metadata
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)


class AgentDeploymentInstance(SQLModel, table=True):
    """Individual deployment instance tracking"""
    
    __tablename__ = "agent_deployment_instances"
    
    id: str = Field(default_factory=lambda: f"instance_{uuid4().hex[:10]}", primary_key=True)
    
    # Instance metadata
    deployment_id: str = Field(index=True)
    instance_id: str = Field(index=True)
    environment: str = Field(index=True)
    region: str = Field(index=True)
    
    # Instance status
    status: DeploymentStatus = Field(default=DeploymentStatus.PENDING)
    health_status: str = Field(default="unknown")  # healthy, unhealthy, unknown
    
    # Instance details
    endpoint_url: Optional[str] = Field(default=None)
    internal_ip: Optional[str] = Field(default=None)
    external_ip: Optional[str] = Field(default=None)
    port: Optional[int] = Field(default=None)
    
    # Resource usage
    cpu_usage: Optional[float] = Field(default=None)
    memory_usage: Optional[int] = Field(default=None)
    disk_usage: Optional[int] = Field(default=None)
    gpu_usage: Optional[float] = Field(default=None)
    
    # Performance metrics
    request_count: int = Field(default=0)
    error_count: int = Field(default=0)
    average_response_time: Optional[float] = Field(default=None)
    uptime_percentage: Optional[float] = Field(default=None)
    
    # Health check history
    last_health_check: Optional[datetime] = Field(default=None)
    consecutive_failures: int = Field(default=0)
    health_check_history: List[Dict[str, Any]] = Field(default_factory=list, sa_column=Column(JSON))
    
    # Timestamps
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)


class AgentIntegrationManager:
    """Manages integration between agent orchestration and existing systems"""
    
    def __init__(self, session: Session):
        self.session = session
        self.zk_service = ZKProofService(session)
        self.orchestrator = AIAgentOrchestrator(session, None)  # Mock coordinator client
        self.security_manager = AgentSecurityManager(session)
        self.auditor = AgentAuditor(session)
    
    async def integrate_with_zk_system(
        self,
        execution_id: str,
        verification_level: VerificationLevel = VerificationLevel.BASIC
    ) -> Dict[str, Any]:
        """Integrate agent execution with ZK proof system"""
        
        try:
            # Get execution details
            execution = self.session.exec(
                select(AgentExecution).where(AgentExecution.id == execution_id)
            ).first()
            
            if not execution:
                raise ValueError(f"Execution not found: {execution_id}")
            
            # Get step executions
            step_executions = self.session.exec(
                select(AgentStepExecution).where(
                    AgentStepExecution.execution_id == execution_id
                )
            ).all()
            
            integration_result = {
                "execution_id": execution_id,
                "integration_status": "in_progress",
                "zk_proofs_generated": [],
                "verification_results": [],
                "integration_errors": []
            }
            
            # Generate ZK proofs for each step
            for step_execution in step_executions:
                if step_execution.requires_proof:
                    try:
                        # Generate ZK proof for step
                        proof_result = await self._generate_step_zk_proof(
                            step_execution, verification_level
                        )
                        
                        integration_result["zk_proofs_generated"].append({
                            "step_id": step_execution.step_id,
                            "proof_id": proof_result["proof_id"],
                            "verification_level": verification_level,
                            "proof_size": proof_result["proof_size"]
                        })
                        
                        # Verify proof
                        verification_result = await self._verify_zk_proof(
                            proof_result["proof_id"]
                        )
                        
                        integration_result["verification_results"].append({
                            "step_id": step_execution.step_id,
                            "verification_status": verification_result["verified"],
                            "verification_time": verification_result["verification_time"]
                        })
                        
                    except Exception as e:
                        integration_result["integration_errors"].append({
                            "step_id": step_execution.step_id,
                            "error": str(e),
                            "error_type": "zk_proof_generation"
                        })
            
            # Generate workflow-level proof
            try:
                workflow_proof = await self._generate_workflow_zk_proof(
                    execution, step_executions, verification_level
                )
                
                integration_result["workflow_proof"] = {
                    "proof_id": workflow_proof["proof_id"],
                    "verification_level": verification_level,
                    "proof_size": workflow_proof["proof_size"]
                }
                
                # Verify workflow proof
                workflow_verification = await self._verify_zk_proof(
                    workflow_proof["proof_id"]
                )
                
                integration_result["workflow_verification"] = {
                    "verified": workflow_verification["verified"],
                    "verification_time": workflow_verification["verification_time"]
                }
                
            except Exception as e:
                integration_result["integration_errors"].append({
                    "error": str(e),
                    "error_type": "workflow_proof_generation"
                })
            
            # Update integration status
            if integration_result["integration_errors"]:
                integration_result["integration_status"] = "partial_success"
            else:
                integration_result["integration_status"] = "success"
            
            # Log integration event
            await self.auditor.log_event(
                AuditEventType.VERIFICATION_COMPLETED,
                execution_id=execution_id,
                security_level=SecurityLevel.INTERNAL,
                event_data={
                    "integration_result": integration_result,
                    "verification_level": verification_level
                }
            )
            
            return integration_result
            
        except Exception as e:
            logger.error(f"ZK integration failed for execution {execution_id}: {e}")
            await self.auditor.log_event(
                AuditEventType.VERIFICATION_FAILED,
                execution_id=execution_id,
                security_level=SecurityLevel.INTERNAL,
                event_data={"error": str(e)}
            )
            raise
    
    async def _generate_step_zk_proof(
        self,
        step_execution: AgentStepExecution,
        verification_level: VerificationLevel
    ) -> Dict[str, Any]:
        """Generate ZK proof for individual step execution"""
        
        # Prepare proof inputs
        proof_inputs = {
            "step_id": step_execution.step_id,
            "execution_id": step_execution.execution_id,
            "step_type": "inference",  # Would get from step definition
            "input_data": step_execution.input_data,
            "output_data": step_execution.output_data,
            "execution_time": step_execution.execution_time,
            "timestamp": step_execution.completed_at.isoformat() if step_execution.completed_at else None
        }
        
        # Generate proof based on verification level
        if verification_level == VerificationLevel.ZERO_KNOWLEDGE:
            # Generate full ZK proof
            proof_result = await self.zk_service.generate_zk_proof(
                circuit_name="agent_step_verification",
                inputs=proof_inputs
            )
        elif verification_level == VerificationLevel.FULL:
            # Generate comprehensive proof with additional checks
            proof_result = await self.zk_service.generate_zk_proof(
                circuit_name="agent_step_full_verification",
                inputs=proof_inputs
            )
        else:
            # Generate basic proof
            proof_result = await self.zk_service.generate_zk_proof(
                circuit_name="agent_step_basic_verification",
                inputs=proof_inputs
            )
        
        return proof_result
    
    async def _generate_workflow_zk_proof(
        self,
        execution: AgentExecution,
        step_executions: List[AgentStepExecution],
        verification_level: VerificationLevel
    ) -> Dict[str, Any]:
        """Generate ZK proof for entire workflow execution"""
        
        # Prepare workflow proof inputs
        step_proofs = []
        for step_execution in step_executions:
            if step_execution.step_proof:
                step_proofs.append(step_execution.step_proof)
        
        proof_inputs = {
            "execution_id": execution.id,
            "workflow_id": execution.workflow_id,
            "step_proofs": step_proofs,
            "final_result": execution.final_result,
            "total_execution_time": execution.total_execution_time,
            "started_at": execution.started_at.isoformat() if execution.started_at else None,
            "completed_at": execution.completed_at.isoformat() if execution.completed_at else None
        }
        
        # Generate workflow proof
        circuit_name = f"agent_workflow_{verification_level.value}_verification"
        proof_result = await self.zk_service.generate_zk_proof(
            circuit_name=circuit_name,
            inputs=proof_inputs
        )
        
        return proof_result
    
    async def _verify_zk_proof(self, proof_id: str) -> Dict[str, Any]:
        """Verify ZK proof"""
        
        verification_result = await self.zk_service.verify_proof(proof_id)
        
        return {
            "verified": verification_result["verified"],
            "verification_time": verification_result["verification_time"],
            "verification_details": verification_result.get("details", {})
        }


class AgentDeploymentManager:
    """Manages deployment of agent workflows to production environments"""
    
    def __init__(self, session: Session):
        self.session = session
        self.integration_manager = AgentIntegrationManager(session)
        self.auditor = AgentAuditor(session)
    
    async def create_deployment_config(
        self,
        workflow_id: str,
        deployment_name: str,
        deployment_config: Dict[str, Any]
    ) -> AgentDeploymentConfig:
        """Create deployment configuration for agent workflow"""
        
        config = AgentDeploymentConfig(
            workflow_id=workflow_id,
            deployment_name=deployment_name,
            **deployment_config
        )
        
        self.session.add(config)
        self.session.commit()
        self.session.refresh(config)
        
        # Log deployment configuration creation
        await self.auditor.log_event(
            AuditEventType.WORKFLOW_CREATED,
            workflow_id=workflow_id,
            security_level=SecurityLevel.INTERNAL,
            event_data={
                "deployment_config_id": config.id,
                "deployment_name": deployment_name
            }
        )
        
        logger.info(f"Created deployment config: {config.id} for workflow {workflow_id}")
        return config
    
    async def deploy_agent_workflow(
        self,
        deployment_config_id: str,
        target_environment: str = "production"
    ) -> Dict[str, Any]:
        """Deploy agent workflow to target environment"""
        
        try:
            # Get deployment configuration
            config = self.session.get(AgentDeploymentConfig, deployment_config_id)
            if not config:
                raise ValueError(f"Deployment config not found: {deployment_config_id}")
            
            # Update deployment status
            config.status = DeploymentStatus.DEPLOYING
            config.deployment_time = datetime.utcnow()
            self.session.commit()
            
            deployment_result = {
                "deployment_id": deployment_config_id,
                "environment": target_environment,
                "status": "deploying",
                "instances": [],
                "deployment_errors": []
            }
            
            # Create deployment instances
            for i in range(config.min_instances):
                instance = await self._create_deployment_instance(
                    config, target_environment, i
                )
                deployment_result["instances"].append(instance)
            
            # Update deployment status
            if deployment_result["deployment_errors"]:
                config.status = DeploymentStatus.FAILED
            else:
                config.status = DeploymentStatus.DEPLOYED
            
            self.session.commit()
            
            # Log deployment event
            await self.auditor.log_event(
                AuditEventType.EXECUTION_STARTED,
                workflow_id=config.workflow_id,
                security_level=SecurityLevel.INTERNAL,
                event_data={
                    "deployment_id": deployment_config_id,
                    "environment": target_environment,
                    "deployment_result": deployment_result
                }
            )
            
            logger.info(f"Deployed agent workflow: {deployment_config_id} to {target_environment}")
            return deployment_result
            
        except Exception as e:
            logger.error(f"Deployment failed for {deployment_config_id}: {e}")
            
            # Update deployment status to failed
            config = self.session.get(AgentDeploymentConfig, deployment_config_id)
            if config:
                config.status = DeploymentStatus.FAILED
                self.session.commit()
            
            await self.auditor.log_event(
                AuditEventType.EXECUTION_FAILED,
                workflow_id=config.workflow_id if config else None,
                security_level=SecurityLevel.INTERNAL,
                event_data={"error": str(e)}
            )
            
            raise
    
    async def _create_deployment_instance(
        self,
        config: AgentDeploymentConfig,
        environment: str,
        instance_number: int
    ) -> Dict[str, Any]:
        """Create individual deployment instance"""
        
        try:
            instance_id = f"{config.deployment_name}-{environment}-{instance_number}"
            
            instance = AgentDeploymentInstance(
                deployment_id=config.id,
                instance_id=instance_id,
                environment=environment,
                region=config.deployment_regions[0] if config.deployment_regions else "default",
                status=DeploymentStatus.DEPLOYING,
                port=8000 + instance_number  # Assign unique port
            )
            
            self.session.add(instance)
            self.session.commit()
            self.session.refresh(instance)
            
            # TODO: Actually deploy the instance
            # This would involve:
            # 1. Setting up the runtime environment
            # 2. Deploying the agent orchestration service
            # 3. Configuring health checks
            # 4. Setting up monitoring
            
            # For now, simulate successful deployment
            instance.status = DeploymentStatus.DEPLOYED
            instance.health_status = "healthy"
            instance.endpoint_url = f"http://localhost:{instance.port}"
            instance.last_health_check = datetime.utcnow()
            
            self.session.commit()
            
            return {
                "instance_id": instance_id,
                "status": "deployed",
                "endpoint_url": instance.endpoint_url,
                "port": instance.port
            }
            
        except Exception as e:
            logger.error(f"Failed to create instance {instance_number}: {e}")
            return {
                "instance_id": f"{config.deployment_name}-{environment}-{instance_number}",
                "status": "failed",
                "error": str(e)
            }
    
    async def monitor_deployment_health(
        self,
        deployment_config_id: str
    ) -> Dict[str, Any]:
        """Monitor health of deployment instances"""
        
        try:
            # Get deployment configuration
            config = self.session.get(AgentDeploymentConfig, deployment_config_id)
            if not config:
                raise ValueError(f"Deployment config not found: {deployment_config_id}")
            
            # Get deployment instances
            instances = self.session.exec(
                select(AgentDeploymentInstance).where(
                    AgentDeploymentInstance.deployment_id == deployment_config_id
                )
            ).all()
            
            health_result = {
                "deployment_id": deployment_config_id,
                "total_instances": len(instances),
                "healthy_instances": 0,
                "unhealthy_instances": 0,
                "unknown_instances": 0,
                "instance_health": []
            }
            
            # Check health of each instance
            for instance in instances:
                instance_health = await self._check_instance_health(instance)
                health_result["instance_health"].append(instance_health)
                
                if instance_health["status"] == "healthy":
                    health_result["healthy_instances"] += 1
                elif instance_health["status"] == "unhealthy":
                    health_result["unhealthy_instances"] += 1
                else:
                    health_result["unknown_instances"] += 1
            
            # Update overall deployment health
            overall_health = "healthy"
            if health_result["unhealthy_instances"] > 0:
                overall_health = "unhealthy"
            elif health_result["unknown_instances"] > 0:
                overall_health = "degraded"
            
            health_result["overall_health"] = overall_health
            
            return health_result
            
        except Exception as e:
            logger.error(f"Health monitoring failed for {deployment_config_id}: {e}")
            raise
    
    async def _check_instance_health(
        self,
        instance: AgentDeploymentInstance
    ) -> Dict[str, Any]:
        """Check health of individual instance"""
        
        try:
            # TODO: Implement actual health check
            # This would involve:
            # 1. HTTP health check endpoint
            # 2. Resource usage monitoring
            # 3. Performance metrics collection
            
            # For now, simulate health check
            health_status = "healthy"
            response_time = 0.1
            
            # Update instance health status
            instance.health_status = health_status
            instance.last_health_check = datetime.utcnow()
            
            # Add to health check history
            health_check_record = {
                "timestamp": datetime.utcnow().isoformat(),
                "status": health_status,
                "response_time": response_time
            }
            instance.health_check_history.append(health_check_record)
            
            # Keep only last 100 health checks
            if len(instance.health_check_history) > 100:
                instance.health_check_history = instance.health_check_history[-100:]
            
            self.session.commit()
            
            return {
                "instance_id": instance.instance_id,
                "status": health_status,
                "response_time": response_time,
                "last_check": instance.last_health_check.isoformat()
            }
            
        except Exception as e:
            logger.error(f"Health check failed for instance {instance.id}: {e}")
            
            # Mark as unhealthy
            instance.health_status = "unhealthy"
            instance.last_health_check = datetime.utcnow()
            instance.consecutive_failures += 1
            self.session.commit()
            
            return {
                "instance_id": instance.instance_id,
                "status": "unhealthy",
                "error": str(e),
                "consecutive_failures": instance.consecutive_failures
            }
    
    async def scale_deployment(
        self,
        deployment_config_id: str,
        target_instances: int
    ) -> Dict[str, Any]:
        """Scale deployment to target number of instances"""
        
        try:
            # Get deployment configuration
            config = self.session.get(AgentDeploymentConfig, deployment_config_id)
            if not config:
                raise ValueError(f"Deployment config not found: {deployment_config_id}")
            
            # Get current instances
            current_instances = self.session.exec(
                select(AgentDeploymentInstance).where(
                    AgentDeploymentInstance.deployment_id == deployment_config_id
                )
            ).all()
            
            current_count = len(current_instances)
            
            scaling_result = {
                "deployment_id": deployment_config_id,
                "current_instances": current_count,
                "target_instances": target_instances,
                "scaling_action": None,
                "scaled_instances": [],
                "scaling_errors": []
            }
            
            if target_instances > current_count:
                # Scale up
                scaling_result["scaling_action"] = "scale_up"
                instances_to_add = target_instances - current_count
                
                for i in range(instances_to_add):
                    instance = await self._create_deployment_instance(
                        config, "production", current_count + i
                    )
                    scaling_result["scaled_instances"].append(instance)
                    
            elif target_instances < current_count:
                # Scale down
                scaling_result["scaling_action"] = "scale_down"
                instances_to_remove = current_count - target_instances
                if instances_to_remove > 0:
                    # Remove excess instances (remove last ones)
                    instances_to_remove_list = current_instances[-instances_to_remove:]
                    for instance in instances_to_remove_list:
                        await self._remove_deployment_instance(instance.id)
                        scaling_result["scaled_instances"].append({
                            "instance_id": instance.instance_id,
                            "status": "removed"
                        })
            
            else:
                scaling_result["scaling_action"] = "no_change"
            
            return scaling_result
            
        except Exception as e:
            logger.error(f"Scaling failed for {deployment_config_id}: {e}")
            raise
    
    async def _remove_deployment_instance(self, instance_id: str):
        """Remove deployment instance"""
        
        try:
            instance = self.session.get(AgentDeploymentInstance, instance_id)
            if instance:
                # TODO: Actually remove the instance
                # This would involve:
                # 1. Stopping the service
                # 2. Cleaning up resources
                # 3. Removing from load balancer
                
                # For now, just mark as terminated
                instance.status = DeploymentStatus.TERMINATED
                self.session.commit()
                
                logger.info(f"Removed deployment instance: {instance_id}")
            
        except Exception as e:
            logger.error(f"Failed to remove instance {instance_id}: {e}")
            raise
    
    async def rollback_deployment(
        self,
        deployment_config_id: str
    ) -> Dict[str, Any]:
        """Rollback deployment to previous version"""
        
        try:
            # Get deployment configuration
            config = self.session.get(AgentDeploymentConfig, deployment_config_id)
            if not config:
                raise ValueError(f"Deployment config not found: {deployment_config_id}")
            
            if not config.rollback_enabled:
                raise ValueError("Rollback not enabled for this deployment")
            
            rollback_result = {
                "deployment_id": deployment_config_id,
                "rollback_status": "in_progress",
                "rolled_back_instances": [],
                "rollback_errors": []
            }
            
            # Get current instances
            current_instances = self.session.exec(
                select(AgentDeploymentInstance).where(
                    AgentDeploymentInstance.deployment_id == deployment_config_id
                )
            ).all()
            
            # Rollback each instance
            for instance in current_instances:
                try:
                    # TODO: Implement actual rollback
                    # This would involve:
                    # 1. Deploying previous version
                    # 2. Verifying rollback success
                    # 3. Updating load balancer
                    
                    # For now, just mark as rolled back
                    instance.status = DeploymentStatus.FAILED
                    self.session.commit()
                    
                    rollback_result["rolled_back_instances"].append({
                        "instance_id": instance.instance_id,
                        "status": "rolled_back"
                    })
                    
                except Exception as e:
                    rollback_result["rollback_errors"].append({
                        "instance_id": instance.instance_id,
                        "error": str(e)
                    })
            
            # Update deployment status
            if rollback_result["rollback_errors"]:
                config.status = DeploymentStatus.FAILED
            else:
                config.status = DeploymentStatus.TERMINATED
            
            self.session.commit()
            
            # Log rollback event
            await self.auditor.log_event(
                AuditEventType.EXECUTION_CANCELLED,
                workflow_id=config.workflow_id,
                security_level=SecurityLevel.INTERNAL,
                event_data={
                    "deployment_id": deployment_config_id,
                    "rollback_result": rollback_result
                }
            )
            
            logger.info(f"Rolled back deployment: {deployment_config_id}")
            return rollback_result
            
        except Exception as e:
            logger.error(f"Rollback failed for {deployment_config_id}: {e}")
            raise


class AgentMonitoringManager:
    """Manages monitoring and metrics for deployed agents"""
    
    def __init__(self, session: Session):
        self.session = session
        self.deployment_manager = AgentDeploymentManager(session)
        self.auditor = AgentAuditor(session)
    
    async def get_deployment_metrics(
        self,
        deployment_config_id: str,
        time_range: str = "1h"
    ) -> Dict[str, Any]:
        """Get metrics for deployment over time range"""
        
        try:
            # Get deployment configuration
            config = self.session.get(AgentDeploymentConfig, deployment_config_id)
            if not config:
                raise ValueError(f"Deployment config not found: {deployment_config_id}")
            
            # Get deployment instances
            instances = self.session.exec(
                select(AgentDeploymentInstance).where(
                    AgentDeploymentInstance.deployment_id == deployment_config_id
                )
            ).all()
            
            metrics = {
                "deployment_id": deployment_config_id,
                "time_range": time_range,
                "total_instances": len(instances),
                "instance_metrics": [],
                "aggregated_metrics": {
                    "total_requests": 0,
                    "total_errors": 0,
                    "average_response_time": 0,
                    "average_cpu_usage": 0,
                    "average_memory_usage": 0,
                    "uptime_percentage": 0
                }
            }
            
            # Collect metrics from each instance
            total_requests = 0
            total_errors = 0
            total_response_time = 0
            total_cpu = 0
            total_memory = 0
            total_uptime = 0
            
            for instance in instances:
                instance_metrics = await self._collect_instance_metrics(instance)
                metrics["instance_metrics"].append(instance_metrics)
                
            # Aggregate metrics
            for instance_metrics in metrics["instance_metrics"]:
                total_requests += instance_metrics.get("request_count", 0)
                total_errors += instance_metrics.get("error_count", 0)
                avg_response_time = instance_metrics.get("average_response_time", 0)
                request_count = instance_metrics.get("request_count", 1)
                if avg_response_time is not None:
                    total_response_time += avg_response_time * request_count
                cpu_usage = instance_metrics.get("cpu_usage", 0)
                if cpu_usage is not None:
                    total_cpu += cpu_usage
                memory_usage = instance_metrics.get("memory_usage", 0)
                if memory_usage is not None:
                    total_memory += memory_usage
                uptime_percentage = instance_metrics.get("uptime_percentage", 0)
                if uptime_percentage is not None:
                    total_uptime += uptime_percentage
            
            # Calculate aggregated metrics
            if len(instances) > 0:
                metrics["aggregated_metrics"]["total_requests"] = total_requests
                metrics["aggregated_metrics"]["total_errors"] = total_errors
                metrics["aggregated_metrics"]["average_response_time"] = (
                    total_response_time / total_requests if total_requests > 0 else 0
                )
                metrics["aggregated_metrics"]["average_cpu_usage"] = total_cpu / len(instances)
                metrics["aggregated_metrics"]["average_memory_usage"] = total_memory / len(instances)
                metrics["aggregated_metrics"]["uptime_percentage"] = total_uptime / len(instances)
            
            return metrics
            
        except Exception as e:
            logger.error(f"Metrics collection failed for {deployment_config_id}: {e}")
            raise
    
    async def _collect_instance_metrics(
        self,
        instance: AgentDeploymentInstance
    ) -> Dict[str, Any]:
        """Collect metrics from individual instance"""
        
        try:
            # TODO: Implement actual metrics collection
            # This would involve:
            # 1. Querying metrics endpoints
            # 2. Collecting performance data
            # 3. Aggregating time series data
            
            # For now, return current instance data
            return {
                "instance_id": instance.instance_id,
                "status": instance.status,
                "health_status": instance.health_status,
                "request_count": instance.request_count,
                "error_count": instance.error_count,
                "average_response_time": instance.average_response_time,
                "cpu_usage": instance.cpu_usage,
                "memory_usage": instance.memory_usage,
                "uptime_percentage": instance.uptime_percentage,
                "last_health_check": instance.last_health_check.isoformat() if instance.last_health_check else None
            }
            
        except Exception as e:
            logger.error(f"Metrics collection failed for instance {instance.id}: {e}")
            return {
                "instance_id": instance.instance_id,
                "error": str(e)
            }
    
    async def create_alerting_rules(
        self,
        deployment_config_id: str,
        alerting_rules: Dict[str, Any]
    ) -> Dict[str, Any]:
        """Create alerting rules for deployment monitoring"""
        
        try:
            # TODO: Implement alerting rules
            # This would involve:
            # 1. Setting up monitoring thresholds
            # 2. Configuring alert channels
            # 3. Creating alert escalation policies
            
            alerting_result = {
                "deployment_id": deployment_config_id,
                "alerting_rules": alerting_rules,
                "rules_created": len(alerting_rules.get("rules", [])),
                "status": "created"
            }
            
            # Log alerting configuration
            await self.auditor.log_event(
                AuditEventType.WORKFLOW_CREATED,
                workflow_id=None,
                security_level=SecurityLevel.INTERNAL,
                event_data={
                    "alerting_config": alerting_result
                }
            )
            
            return alerting_result
            
        except Exception as e:
            logger.error(f"Alerting rules creation failed for {deployment_config_id}: {e}")
            raise


class AgentProductionManager:
    """Main production management interface for agent orchestration"""
    
    def __init__(self, session: Session):
        self.session = session
        self.integration_manager = AgentIntegrationManager(session)
        self.deployment_manager = AgentDeploymentManager(session)
        self.monitoring_manager = AgentMonitoringManager(session)
        self.auditor = AgentAuditor(session)
    
    async def deploy_to_production(
        self,
        workflow_id: str,
        deployment_config: Dict[str, Any],
        integration_config: Optional[Dict[str, Any]] = None
    ) -> Dict[str, Any]:
        """Deploy agent workflow to production with full integration"""
        
        try:
            production_result = {
                "workflow_id": workflow_id,
                "deployment_status": "in_progress",
                "integration_status": "pending",
                "monitoring_status": "pending",
                "deployment_id": None,
                "errors": []
            }
            
            # Step 1: Create deployment configuration
            deployment = await self.deployment_manager.create_deployment_config(
                workflow_id=workflow_id,
                deployment_name=deployment_config.get("name", f"production-{workflow_id}"),
                deployment_config=deployment_config
            )
            
            production_result["deployment_id"] = deployment.id
            
            # Step 2: Deploy to production
            deployment_result = await self.deployment_manager.deploy_agent_workflow(
                deployment_config_id=deployment.id,
                target_environment="production"
            )
            
            production_result["deployment_status"] = deployment_result["status"]
            production_result["deployment_errors"] = deployment_result.get("deployment_errors", [])
            
            # Step 3: Set up integration with ZK system
            if integration_config:
                # Simulate integration setup
                production_result["integration_status"] = "configured"
            else:
                production_result["integration_status"] = "skipped"
            
            # Step 4: Set up monitoring
            try:
                monitoring_setup = await self.monitoring_manager.create_alerting_rules(
                    deployment_config_id=deployment.id,
                    alerting_rules=deployment_config.get("alerting_rules", {})
                )
                production_result["monitoring_status"] = monitoring_setup["status"]
            except Exception as e:
                production_result["monitoring_status"] = "failed"
                production_result["errors"].append(f"Monitoring setup failed: {e}")
            
            # Determine overall status
            if production_result["errors"]:
                production_result["overall_status"] = "partial_success"
            else:
                production_result["overall_status"] = "success"
            
            # Log production deployment
            await self.auditor.log_event(
                AuditEventType.EXECUTION_COMPLETED,
                workflow_id=workflow_id,
                security_level=SecurityLevel.INTERNAL,
                event_data={
                    "production_deployment": production_result
                }
            )
            
            logger.info(f"Production deployment completed for workflow {workflow_id}")
            return production_result
            
        except Exception as e:
            logger.error(f"Production deployment failed for workflow {workflow_id}: {e}")
            
            await self.auditor.log_event(
                AuditEventType.EXECUTION_FAILED,
                workflow_id=workflow_id,
                security_level=SecurityLevel.INTERNAL,
                event_data={"error": str(e)}
            )
            
            raise
