#!/bin/bash
# MCP-ZERO Terraform Configuration Generator
# Creates Terraform files for infrastructure deployment with offline-first resilience
# Implements contract burning integration for healthcare agents

# Color definitions
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Print colored message
print_message() {
  local color=$1
  local message=$2
  echo -e "${color}${message}${NC}"
}

# Generate main.tf
generate_main_tf() {
  local tf_dir="$1"
  local agent_type="$2"
  local offline_mode="$3"
  
  echo "Generating main.tf..."
  
  cat > "${tf_dir}/main.tf" << EOF
# MCP-ZERO Terraform Configuration
# Generated by burn folder script

terraform {
  required_providers {
    null = {
      source  = "hashicorp/null"
      version = "~> 3.0"
    }
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
  
  # Enable offline-first resilience with local state
  backend "local" {
    path = "terraform.tfstate"
  }
}

provider "null" {}
provider "local" {}

# Record deployment timestamp for audit trail
resource "local_file" "deployment_timestamp" {
  filename = "\${path.module}/deployment.lock"
  content  = jsonencode({
    timestamp  = timestamp()
    agent_type = "${agent_type}"
    offline_mode = ${offline_mode}
  })
  file_permission = "0444" # Read-only for immutability
}

# Import variables from tfvars if present
locals {
  agent_vars = fileexists("\${path.module}/agent.tfvars.json") ? jsondecode(file("\${path.module}/agent.tfvars.json")) : {
    agent_type = "${agent_type}"
    offline_mode = ${offline_mode}
    fallback = true
  }
}
EOF

  echo "main.tf generated successfully"
}

# Generate vpods.tf for agent deployment
generate_vpods_tf() {
  local tf_dir="$1"
  local agent_type="$2"
  
  echo "Generating vpods.tf for agent deployment..."
  
  cat > "${tf_dir}/vpods.tf" << EOF
# MCP-ZERO Agent Deployment Configuration
# Defines virtual pods (vpods) for agent deployment

# Agent resource allocation
resource "null_resource" "agent_vpod" {
  triggers = {
    agent_id = "${agent_type}-\${formatdate("YYYYMMDDhhmmss", timestamp())}"
  }
  
  provisioner "local-exec" {
    # Use offline-first resilience pattern with single connection attempt
    command = "SINGLE_CONNECTION_ATTEMPT=1 OFFLINE_FIRST=1 python3 \${path.module}/scripts/deploy_agent.py --agent-id=\${self.triggers.agent_id} --type=${agent_type} || echo 'Falling back to offline mode'"
  }
}

# Agent communication graph
resource "local_file" "agent_graph" {
  filename = "\${path.module}/agent_graph.json"
  content = jsonencode({
    agent_id = null_resource.agent_vpod.triggers.agent_id
    agent_type = "${agent_type}"
    connections = [
      {
        type = "internal",
        target = "memory",
        direction = "bidirectional"
      },
      {
        type = "external",
        target = "api",
        direction = "outbound",
        fallback = "local"
      }
    ]
  })
}

# Output the agent ID for reference
output "agent_id" {
  value = null_resource.agent_vpod.triggers.agent_id
}
EOF

  echo "vpods.tf generated successfully"
}

# Generate contracts.tf
generate_contracts_tf() {
  local tf_dir="$1"
  local contracts_dir="$2"
  local burned_dir="$3"
  
  echo "Generating contracts.tf..."
  
  cat > "${tf_dir}/contracts.tf" << EOF
# MCP-ZERO Contract Integration
# Contracts are burned during deployment for immutability

# Scan contracts directory and create list of contracts
locals {
  contract_files = fileset("\${path.module}/${contracts_dir}", "*.{yml,yaml}")
  burned_contracts_dir = "\${path.module}/${burned_dir}"
}

# Create contract burn resource to ensure contracts are burned
resource "null_resource" "burn_contracts" {
  triggers = {
    contract_files = join(",", local.contract_files)
    timestamp = timestamp()
  }
  
  provisioner "local-exec" {
    command = "OFFLINE_FIRST=1 python3 \${path.module}/scripts/burn_contracts.py --contracts-dir=\${path.module}/${contracts_dir} --burn-dir=\${local.burned_contracts_dir} --terraform-dir=\${path.module}"
  }
}

# Output contract validation data
output "contract_validation" {
  value = {
    contract_count = length(local.contract_files)
    burn_time = timestamp()
  }
  depends_on = [null_resource.burn_contracts]
}
EOF

  echo "contracts.tf generated successfully"
}

# Generate variables.tf
generate_variables_tf() {
  local tf_dir="$1"
  
  echo "Generating variables.tf..."
  
  cat > "${tf_dir}/variables.tf" << EOF
# MCP-ZERO Terraform Variables

variable "agent_type" {
  description = "Type of agent to deploy"
  type        = string
  default     = "healthcare"
}

variable "offline_mode" {
  description = "Whether to operate in offline mode"
  type        = bool
  default     = true
}

variable "environment" {
  description = "Deployment environment"
  type        = string
  default     = "development"
}

variable "resources" {
  description = "Resource allocation for agent"
  type = object({
    memory = string
    cpu    = string
  })
  default = {
    memory = "512Mi"
    cpu    = "0.5"
  }
}
EOF

  echo "variables.tf generated successfully"
}

# Generate deploy_agent.py script
generate_deploy_script() {
  local tf_dir="$1"
  local scripts_dir="${tf_dir}/scripts"
  
  mkdir -p "${scripts_dir}"
  
  echo "Generating deploy_agent.py script..."
  
  cat > "${scripts_dir}/deploy_agent.py" << EOF
#!/usr/bin/env python3
# MCP-ZERO Agent Deployment Script
# Implements offline-first resilience pattern

import os
import sys
import json
import argparse
import datetime
import time
from pathlib import Path

# Set up offline-first resilience
OFFLINE_MODE = os.environ.get("OFFLINE_FIRST", "0") == "1"
SINGLE_CONNECTION_ATTEMPT = os.environ.get("SINGLE_CONNECTION_ATTEMPT", "0") == "1"

class AgentDeployer:
    """Agent deployment with offline-first resilience"""
    
    def __init__(self, agent_id, agent_type):
        self.agent_id = agent_id
        self.agent_type = agent_type
        self.log_file = Path("deploy.log")
        self.lock_file = Path("deploy.lock")
        self.init_log()
    
    def init_log(self):
        """Initialize log file"""
        with open(self.log_file, "w") as f:
            f.write(f"# MCP-ZERO Agent Deployment Log\n")
            f.write(f"# Started at: {datetime.datetime.now().isoformat()}\n")
            f.write(f"# Agent ID: {self.agent_id}\n")
            f.write(f"# Agent Type: {self.agent_type}\n")
            f.write(f"# Offline Mode: {OFFLINE_MODE}\n\n")
    
    def log(self, message):
        """Add log message"""
        timestamp = datetime.datetime.now().isoformat()
        with open(self.log_file, "a") as f:
            f.write(f"[{timestamp}] {message}\n")
        print(message)
    
    def create_lock_file(self, success):
        """Create immutable lock file for audit trail"""
        with open(self.lock_file, "w") as f:
            data = {
                "agent_id": self.agent_id,
                "agent_type": self.agent_type,
                "timestamp": datetime.datetime.now().isoformat(),
                "success": success,
                "offline_mode": OFFLINE_MODE
            }
            json.dump(data, f, indent=2)
        # Make lock file read-only
        os.chmod(self.lock_file, 0o444)
    
    def connect_to_service(self, service_name, timeout=5):
        """Implement single connection attempt pattern"""
        if OFFLINE_MODE:
            self.log(f"Offline mode enabled, skipping connection to {service_name}")
            return False
            
        self.log(f"Attempting to connect to {service_name}...")
        
        # Simulate connection attempt
        if SINGLE_CONNECTION_ATTEMPT:
            # Just one attempt
            success = False  # Simulated failure
            if not success:
                self.log(f"Connection to {service_name} failed, enabling offline mode")
                os.environ["OFFLINE_FIRST"] = "1"
                return False
        else:
            # Multiple attempts (not recommended)
            for i in range(3):
                self.log(f"Connection attempt {i+1} to {service_name}...")
                time.sleep(1)
                success = False  # Simulated failure
                if success:
                    break
                    
            if not success:
                self.log(f"All connection attempts to {service_name} failed")
                os.environ["OFFLINE_FIRST"] = "1"
                return False
                
        return success
    
    def deploy(self):
        """Deploy agent with offline-first resilience"""
        self.log(f"Starting deployment for {self.agent_type} agent {self.agent_id}")
        
        # Try to connect to deployment service
        connected = self.connect_to_service("deployment-api")
        
        # Handle deployment in offline or online mode
        if connected:
            self.log("Connected to deployment service, deploying in online mode")
            success = True  # Simulated successful deployment
        else:
            self.log("Deploying in offline mode with local resources")
            
            # Create local deployment files
            agent_dir = Path(f"agent_{self.agent_id}")
            agent_dir.mkdir(exist_ok=True)
            
            with open(agent_dir / "config.json", "w") as f:
                config = {
                    "agent_id": self.agent_id,
                    "agent_type": self.agent_type,
                    "offline_mode": True,
                    "created_at": datetime.datetime.now().isoformat(),
                    "fallback_enabled": True
                }
                json.dump(config, f, indent=2)
                
            success = True
            
        # Create lock file for audit trail
        self.create_lock_file(success)
        
        if success:
            self.log(f"Deployment completed successfully for agent {self.agent_id}")
            return 0
        else:
            self.log(f"Deployment failed for agent {self.agent_id}")
            return 1

def main():
    parser = argparse.ArgumentParser(description="MCP-ZERO Agent Deployer")
    parser.add_argument("--agent-id", required=True, help="Agent ID")
    parser.add_argument("--type", required=True, help="Agent type")
    args = parser.parse_args()
    
    deployer = AgentDeployer(args.agent_id, args.type)
    return deployer.deploy()

if __name__ == "__main__":
    sys.exit(main())
EOF

  chmod +x "${scripts_dir}/deploy_agent.py"
  echo "deploy_agent.py script generated successfully"
}

# Generate all Terraform files
generate_all_terraform() {
  local tf_dir="$1"
  local agent_type="$2"
  local offline_mode="$3"
  local contracts_dir="contracts"
  local burned_dir="burned_contracts"
  
  # Create directories
  mkdir -p "${tf_dir}/scripts"
  mkdir -p "${tf_dir}/${contracts_dir}"
  mkdir -p "${tf_dir}/${burned_dir}"
  
  # Generate files
  generate_main_tf "${tf_dir}" "${agent_type}" "${offline_mode}"
  generate_vpods_tf "${tf_dir}" "${agent_type}"
  generate_contracts_tf "${tf_dir}" "${contracts_dir}" "${burned_dir}"
  generate_variables_tf "${tf_dir}"
  generate_deploy_script "${tf_dir}"
  
  # Create minimal example contract if directory is empty
  if [ ! "$(ls -A "${tf_dir}/${contracts_dir}" 2>/dev/null)" ]; then
    cat > "${tf_dir}/${contracts_dir}/healthcare_agent.yml" << EOF
# Healthcare Agent Contract
name: healthcare_agent
type: agent
version: 1.0
created_at: $(date -Iseconds)

resources:
  memory: 512Mi
  cpu: 0.5

capabilities:
  - memory
  - reasoning
  - api_access

offline_mode:
  enabled: true
  fallback_strategy: local_processing
EOF
  fi
  
  # Create .terraform-version file for version pinning
  echo "1.0.0" > "${tf_dir}/.terraform-version"
  
  echo "All Terraform files generated successfully at ${tf_dir}"
}

# If script is executed directly, show usage
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  echo "This script is intended to be sourced by burn.sh"
  echo "Usage: source $(basename "$0")"
fi
