# Phase 2: Docker Compose Deployment - 5 US Commercial Azure Regions
# DeFi Oracle Meta Mainnet (ChainID 138)
# 
# Architecture:
# - Deploys multi-service docker-compose stacks to Phase 1 VMs
# - Each region gets a region-specific docker-compose file
# - Services: Besu + FireFly + Cacti + Chainlink + Databases + Monitoring
#
# NOTE: Phase 1 must be deployed first. Phase 2 deploys docker-compose files to existing VMs.

terraform {
  required_version = ">= 1.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
    null = {
      source  = "hashicorp/null"
      version = "~> 3.0"
    }
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}

provider "azurerm" {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = var.environment == "prod" ? true : false
    }
  }
}

# Local values for configuration
locals {
  cloud_provider = "az"

  env_codes = {
    prod    = "p"
    dev     = "d"
    test    = "t"
    staging = "s"
  }

  env_code = local.env_codes[var.environment]

  # Region to docker-compose file mapping
  region_compose_map = {
    centralus = "docker-compose.cus.yml"
    eastus    = "docker-compose.eus.yml"
    eastus2   = "docker-compose.eus2.yml"
    westus    = "docker-compose.wus.yml"
    westus2   = "docker-compose.wus2.yml"
  }

  # Extract region from phase1_vm_info keys
  regions = keys(var.phase1_vm_info)

  # Common tags
  common_tags = merge(var.tags, {
    Environment     = var.environment
    CostCenter      = "Blockchain"
    Owner           = "DevOps Team"
    NamingConvention = "az-env-region-resource-instance"
    DeploymentPhase = "phase2"
    Project         = "DeFi Oracle Meta Mainnet"
    ChainID         = "138"
  })
}

# Create deployment directory structure on VMs and copy docker-compose files
resource "null_resource" "deploy_docker_compose" {
  for_each = var.phase1_vm_info

  triggers = {
    # Trigger when compose file changes or VM info changes
    compose_file_hash = filemd5("${var.docker_compose_source_path}/${local.region_compose_map[each.value.region]}")
    # Use VM name, resource group, and IPs to create unique trigger
    vm_identifier = "${each.value.resource_group}/${each.value.vm_names[0]}/${join(",", each.value.private_ips)}/${join(",", each.value.public_ips)}"
  }

  # Determine connection IP (prefer private IP, fallback to public IP)
  # NOTE: This Terraform should be run from the Nginx proxy host (20.160.58.99)
  # where direct access to private IPs is available
  connection {
    type        = "ssh"
    user        = var.vm_admin_username
    private_key = file(var.ssh_private_key_path)
    host        = length(each.value.private_ips) > 0 ? each.value.private_ips[0] : (length(each.value.public_ips) > 0 ? each.value.public_ips[0] : null)
    timeout     = "5m"
  }

  # Step 1: Create directories for docker-compose and volume mounts
  provisioner "remote-exec" {
    inline = [
      "sudo mkdir -p /opt/docker-compose",
      "sudo mkdir -p /opt/besu/{data,config,keys,logs}",
      "sudo mkdir -p /opt/firefly/{postgres,postgres-primary,postgres-replica}",
      "sudo mkdir -p /opt/cacti/{postgres,postgres-primary}",
      "sudo mkdir -p /opt/prometheus",
      "sudo mkdir -p /opt/grafana",
      "sudo mkdir -p /opt/grafana-logs",
      "sudo mkdir -p /opt/alertmanager",
      "sudo mkdir -p /opt/loki/{data,config}",
      "sudo mkdir -p /opt/ipfs/data",
      "sudo mkdir -p /opt/promtail",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/docker-compose",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/besu",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/firefly",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/cacti",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/prometheus",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/grafana",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/grafana-logs",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/alertmanager",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/loki",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/ipfs",
      "sudo chown -R ${var.vm_admin_username}:${var.vm_admin_username} /opt/promtail",
    ]
  }

  # Step 2: Copy docker-compose file to VM
  provisioner "file" {
    source      = "${var.docker_compose_source_path}/${local.region_compose_map[each.value.region]}"
    destination = "/tmp/docker-compose.yml"
  }

  # Step 3: Move file to final location and set permissions
  provisioner "remote-exec" {
    inline = [
      "mv /tmp/docker-compose.yml /opt/docker-compose/docker-compose.yml",
      "chmod 644 /opt/docker-compose/docker-compose.yml",
      "chown ${var.vm_admin_username}:${var.vm_admin_username} /opt/docker-compose/docker-compose.yml",
    ]
  }

}

# Create systemd service file for docker-compose stack
resource "null_resource" "create_systemd_service" {
  for_each = var.phase1_vm_info

  triggers = {
    compose_deployed = null_resource.deploy_docker_compose[each.key].id
  }

  connection {
    type        = "ssh"
    user        = var.vm_admin_username
    private_key = file(var.ssh_private_key_path)
    host        = length(each.value.private_ips) > 0 ? each.value.private_ips[0] : (length(each.value.public_ips) > 0 ? each.value.public_ips[0] : null)
    timeout     = "5m"
  }

  # Create systemd service file
  provisioner "file" {
    content = templatefile("${path.module}/templates/phase2-stack.service.tpl", {
      admin_username = var.vm_admin_username
    })
    destination = "/tmp/phase2-stack.service"
  }

  # Install systemd service
  provisioner "remote-exec" {
    inline = [
      "sudo mv /tmp/phase2-stack.service /etc/systemd/system/phase2-stack.service",
      "sudo chmod 644 /etc/systemd/system/phase2-stack.service",
      "sudo systemctl daemon-reload",
      "sudo systemctl enable phase2-stack.service",
      "# Service will be started manually or via separate apply"
    ]
  }

  depends_on = [
    null_resource.deploy_docker_compose
  ]
}

