terraform {
  required_version = ">= 1.5"

  backend "s3" {
    bucket         = "layover-sh-terraform-state"
    key            = "layover/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "layover-sh-terraform-lock"
    encrypt        = true
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    gandi = {
      source  = "go-gandi/gandi"
      version = "~> 2.3"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

provider "gandi" {
  personal_access_token = var.gandi_api_key
}

# --- AMI ---

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

# --- Root Password ---

resource "random_password" "root" {
  length  = 32
  special = false
}

# --- SSH Key ---

resource "aws_key_pair" "layover" {
  key_name   = "layover-key"
  public_key = file(pathexpand(var.ssh_public_key_path))
}

# --- Security Group ---

resource "aws_security_group" "layover" {
  name        = "layover-relay"
  description = "Layover TCP relay"

  ingress {
    description = "TLS relay + landing page"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "ACME challenge (certbot)"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "SSH management"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = var.ssh_allowed_cidrs
  }

  egress {
    description = "All outbound (relay connects to arbitrary destinations)"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = { Name = "layover-relay" }
}

# --- EC2 Instance ---

resource "aws_instance" "layover" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = var.instance_type
  key_name               = aws_key_pair.layover.key_name
  vpc_security_group_ids = [aws_security_group.layover.id]

  root_block_device {
    volume_size = 8
    volume_type = "gp3"
  }

  tags = { Name = "layover-relay" }

  # Phase 1: Upload binary and setup script, install everything except cert
  connection {
    type        = "ssh"
    user        = "ubuntu"
    private_key = file(pathexpand(var.ssh_private_key_path))
    host        = self.public_ip
  }

  provisioner "file" {
    source      = var.binary_path
    destination = "/tmp/layover"
  }

  provisioner "file" {
    source      = "${path.module}/setup.sh"
    destination = "/tmp/setup.sh"
  }

  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/setup.sh",
      "sudo /tmp/setup.sh install '${var.hostname}' '${var.certbot_email}' '${random_password.root.result}'",
    ]
  }
}

# --- Elastic IP ---

resource "aws_eip" "layover" {
  instance = aws_instance.layover.id
  domain   = "vpc"
  tags     = { Name = "layover-relay" }
}

# --- Phase 2: Get TLS cert and start service (after EIP + DNS are ready) ---

resource "null_resource" "certbot" {
  depends_on = [aws_eip.layover, gandi_livedns_record.layover]

  triggers = {
    instance_id = aws_instance.layover.id
  }

  connection {
    type        = "ssh"
    user        = "ubuntu"
    private_key = file(pathexpand(var.ssh_private_key_path))
    host        = aws_eip.layover.public_ip
  }

  provisioner "remote-exec" {
    inline = [
      "sudo /tmp/setup.sh certbot '${var.hostname}' '${var.certbot_email}'",
    ]
  }
}

# --- Phase 3: Deploy new binary (runs on every binary change) ---

resource "null_resource" "deploy_binary" {
  depends_on = [null_resource.certbot]

  triggers = {
    binary_sha256 = filesha256(var.binary_path)
  }

  connection {
    type        = "ssh"
    user        = "ubuntu"
    private_key = file(pathexpand(var.ssh_private_key_path))
    host        = aws_eip.layover.public_ip
  }

  provisioner "file" {
    source      = var.binary_path
    destination = "/tmp/layover"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo install -m 755 /tmp/layover /usr/local/bin/layover",
      "sudo systemctl restart layover",
    ]
  }
}
