# ===========================================================================
# Langfuse LLM Observability Infrastructure
#
# Self-hosted Langfuse requires: PostgreSQL, ClickHouse, Redis, S3.
# Redis is shared with existing ElastiCache cluster (DB index 1).
# ===========================================================================

# ---------------------------------------------------------------------------
# KMS key for Langfuse Secrets Manager entries
# ---------------------------------------------------------------------------

resource "aws_kms_key" "langfuse_secrets" {
  count = local.create_langfuse ? 1 : 0

  description             = "KMS key for ${var.environment}-${local.langfuse_service_name} Secrets Manager"
  deletion_window_in_days = 14
  enable_key_rotation     = true
}

resource "aws_kms_alias" "langfuse_secrets" {
  count = local.create_langfuse ? 1 : 0

  name          = "alias/${var.environment}-${local.langfuse_service_name}-secrets"
  target_key_id = aws_kms_key.langfuse_secrets[0].key_id
}

# ---------------------------------------------------------------------------
# Generated passwords (stored in Secrets Manager, never in code or CLI)
# ---------------------------------------------------------------------------

resource "random_password" "langfuse_db" {
  count   = local.create_langfuse ? 1 : 0
  length  = 32
  special = false # Aurora Postgres disallows some special chars in master password
}

resource "random_password" "langfuse_clickhouse" {
  count   = local.create_langfuse ? 1 : 0
  length  = 32
  special = false
}

resource "random_password" "langfuse_nextauth" {
  count   = local.create_langfuse ? 1 : 0
  length  = 32
  special = true
}

resource "random_password" "langfuse_salt" {
  count   = local.create_langfuse ? 1 : 0
  length  = 32
  special = false
}

resource "random_password" "langfuse_init_user" {
  count   = local.create_langfuse ? 1 : 0
  length  = 32
  special = false
}

# ENCRYPTION_KEY must be 256-bit hex (64 chars). random_id produces hex natively.
resource "random_id" "langfuse_encryption_key" {
  count       = local.create_langfuse ? 1 : 0
  byte_length = 32
}

# ---------------------------------------------------------------------------
# Aurora PostgreSQL (metadata, prompts, API keys)
# ---------------------------------------------------------------------------

module "langfuse_rds" {
  count  = local.create_langfuse ? 1 : 0
  source = "git@github.com:theorchard/terraform-rds.git//?ref=8.0.0"

  providers = {
    aws.dns = aws.networking
  }

  environment        = var.environment
  service_name       = local.langfuse_service_name
  application_family = var.application_family
  vpc_id             = module.vpc_info.vpc_id

  rds_engine         = "aurora-postgresql"
  rds_engine_version = "16.11"

  rds_db_cluster_parameter_group_family     = "aurora-postgresql16"
  rds_cluster_instance_parameter_group_name = "default.aurora-postgresql16"

  rds_cluster_instance_class = "db.t4g.medium"
  rds_cluster_instance_count = 1

  rds_availability_zones = ["${var.region}a", "${var.region}d"]
  rds_db_subnet_ids      = module.vpc_info.default_private_subnet_ids

  rds_ingress_prefix_list_names = ["shared-orcd-jump-box-private-subnet-prefix-list"]
  rds_ingress_security_groups   = [aws_security_group.langfuse_task[0].id]

  rds_master_username = var.langfuse_db_username
  rds_master_password = random_password.langfuse_db[0].result

  enabled_cloudwatch_logs_exports = ["postgresql"]

  custom_kms_key_enabled           = true
  rds_performance_insights_enabled = true
  route53_record_creation_enabled  = false
}

# ---------------------------------------------------------------------------
# ClickHouse (OLAP analytics — EC2 with EBS for persistent storage)
# ---------------------------------------------------------------------------

data "aws_ami" "amazon_linux_2023" {
  count = local.create_langfuse ? 1 : 0

  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }

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

resource "aws_kms_key" "langfuse_ebs" {
  count = local.create_langfuse ? 1 : 0

  description             = "KMS key for ${var.environment}-${local.langfuse_service_name} ClickHouse EBS"
  deletion_window_in_days = 14
  enable_key_rotation     = true
}

resource "aws_kms_alias" "langfuse_ebs" {
  count = local.create_langfuse ? 1 : 0

  name          = "alias/${var.environment}-${local.langfuse_service_name}-ebs"
  target_key_id = aws_kms_key.langfuse_ebs[0].key_id
}

resource "aws_iam_role" "langfuse_clickhouse" {
  count = local.create_langfuse ? 1 : 0

  name = "${var.environment}-${local.langfuse_service_name}-clickhouse-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Effect    = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
    }]
  })
}

resource "aws_iam_instance_profile" "langfuse_clickhouse" {
  count = local.create_langfuse ? 1 : 0

  name = "${var.environment}-${local.langfuse_service_name}-clickhouse-profile"
  role = aws_iam_role.langfuse_clickhouse[0].name
}

resource "aws_iam_role_policy_attachment" "langfuse_clickhouse_ssm" {
  count = local.create_langfuse ? 1 : 0

  role       = aws_iam_role.langfuse_clickhouse[0].name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

# IAM policy for ClickHouse EC2 to read its password from Secrets Manager
data "aws_iam_policy_document" "langfuse_clickhouse_secrets" {
  count = local.create_langfuse ? 1 : 0

  statement {
    effect    = "Allow"
    actions   = ["secretsmanager:GetSecretValue"]
    resources = [aws_secretsmanager_secret.langfuse_clickhouse_password[0].arn]
  }

  statement {
    effect    = "Allow"
    actions   = ["kms:Decrypt"]
    resources = [aws_kms_key.langfuse_secrets[0].arn]
  }
}

resource "aws_iam_policy" "langfuse_clickhouse_secrets" {
  count = local.create_langfuse ? 1 : 0

  name   = "${var.environment}-${local.langfuse_service_name}-clickhouse-secrets"
  policy = data.aws_iam_policy_document.langfuse_clickhouse_secrets[0].json
}

resource "aws_iam_role_policy_attachment" "langfuse_clickhouse_secrets" {
  count = local.create_langfuse ? 1 : 0

  role       = aws_iam_role.langfuse_clickhouse[0].name
  policy_arn = aws_iam_policy.langfuse_clickhouse_secrets[0].arn
}

resource "aws_security_group" "langfuse_clickhouse" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}-${local.langfuse_service_name}-clickhouse-sg"
  description = "ClickHouse access for Langfuse"
  vpc_id      = module.vpc_info.vpc_id

  ingress {
    description     = "ClickHouse HTTP from Langfuse tasks"
    from_port       = 8123
    to_port         = 8123
    protocol        = "tcp"
    security_groups = [aws_security_group.langfuse_task[0].id]
  }

  ingress {
    description     = "ClickHouse native from Langfuse tasks"
    from_port       = 9000
    to_port         = 9000
    protocol        = "tcp"
    security_groups = [aws_security_group.langfuse_task[0].id]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name         = "${var.environment}-${local.langfuse_service_name}-clickhouse-sg"
    service_name = local.langfuse_service_name
  }
}

data "aws_subnet" "langfuse_clickhouse" {
  count = local.create_langfuse ? 1 : 0
  id    = module.vpc_info.default_private_subnet_ids[0]
}

resource "aws_instance" "langfuse_clickhouse" {
  count = local.create_langfuse ? 1 : 0

  ami                    = data.aws_ami.amazon_linux_2023[0].id
  instance_type          = "t3.medium"
  subnet_id              = module.vpc_info.default_private_subnet_ids[0]
  vpc_security_group_ids = [aws_security_group.langfuse_clickhouse[0].id]
  iam_instance_profile   = aws_iam_instance_profile.langfuse_clickhouse[0].name
  ebs_optimized          = true
  monitoring             = true

  metadata_options {
    http_endpoint               = "enabled"
    http_tokens                 = "required"
    http_put_response_hop_limit = 1
  }

  root_block_device {
    volume_type           = "gp3"
    volume_size           = 30 # AL2023 AMI snapshot requires >= 30GB
    encrypted             = true
    delete_on_termination = true
  }

  # The ClickHouse password is retrieved from Secrets Manager at boot via AWS CLI.
  # The EC2 IAM role has secretsmanager:GetSecretValue permission for this secret.
  user_data = base64encode(<<-EOF
#!/bin/bash
set -euo pipefail

# Install Docker + AWS CLI
dnf install -y docker aws-cli
systemctl enable docker
systemctl start docker

# Wait for EBS data volume
while [ ! -b /dev/xvdb ]; do sleep 1; done

# Format if new volume
if ! blkid /dev/xvdb; then
  mkfs.ext4 /dev/xvdb
fi

# Mount data volume
mkdir -p /data/clickhouse
mount /dev/xvdb /data/clickhouse
echo '/dev/xvdb /data/clickhouse ext4 defaults,nofail 0 2' >> /etc/fstab

# Retrieve ClickHouse password from Secrets Manager into a temp env file.
# Written to a restrictive file to avoid exposure in cloud-init logs or process table.
ENV_FILE=$(mktemp)
chmod 600 "$ENV_FILE"
{
  echo "CLICKHOUSE_DB=langfuse"
  echo "CLICKHOUSE_USER=langfuse"
  printf "CLICKHOUSE_PASSWORD=%s\n" "$(aws secretsmanager get-secret-value \
    --secret-id "${aws_secretsmanager_secret.langfuse_clickhouse_password[0].name}" \
    --region "${var.region}" \
    --query SecretString --output text)"
} > "$ENV_FILE"

# Run ClickHouse with authentication enabled
docker run -d \
  --name clickhouse \
  --restart unless-stopped \
  --ulimit nofile=262144:262144 \
  -p 8123:8123 \
  -p 9000:9000 \
  -v /data/clickhouse:/var/lib/clickhouse \
  --env-file "$ENV_FILE" \
  clickhouse/clickhouse-server:24.3

# Remove the env file — Docker has already read it
rm -f "$ENV_FILE"
  EOF
  )

  tags = {
    Name         = "${var.environment}-${local.langfuse_service_name}-clickhouse"
    Service      = local.langfuse_service_name
    service_name = local.langfuse_service_name
  }

  lifecycle {
    # Ignore AMI and user_data changes to prevent instance replacement.
    # To update: taint the resource or do a manual rolling replacement.
    ignore_changes = [ami, user_data]
  }
}

resource "aws_ebs_volume" "langfuse_clickhouse_data" {
  count = local.create_langfuse ? 1 : 0

  availability_zone = data.aws_subnet.langfuse_clickhouse[0].availability_zone
  type              = "gp3"
  size              = 100
  encrypted         = true
  kms_key_id        = aws_kms_key.langfuse_ebs[0].arn

  tags = {
    Name         = "${var.environment}-${local.langfuse_service_name}-clickhouse-data"
    Service      = local.langfuse_service_name
    service_name = local.langfuse_service_name
  }
}

resource "aws_volume_attachment" "langfuse_clickhouse_data" {
  count = local.create_langfuse ? 1 : 0

  device_name = "/dev/xvdb"
  volume_id   = aws_ebs_volume.langfuse_clickhouse_data[0].id
  instance_id = aws_instance.langfuse_clickhouse[0].id
}

# ---------------------------------------------------------------------------
# ClickHouse monitoring — status check alarm + EBS snapshots
# ---------------------------------------------------------------------------

resource "aws_sns_topic" "langfuse_alerts" {
  count = local.create_langfuse ? 1 : 0

  name              = "${var.environment}-${local.langfuse_service_name}-alerts"
  kms_master_key_id = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_cloudwatch_metric_alarm" "langfuse_clickhouse_status" {
  count = local.create_langfuse ? 1 : 0

  alarm_name          = "${var.environment}-${local.langfuse_service_name}-clickhouse-status-check"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "StatusCheckFailed"
  namespace           = "AWS/EC2"
  period              = 60
  statistic           = "Maximum"
  threshold           = 0
  alarm_description   = "ClickHouse EC2 instance status check failed"
  alarm_actions       = [aws_sns_topic.langfuse_alerts[0].arn]

  dimensions = {
    InstanceId = aws_instance.langfuse_clickhouse[0].id
  }
}

# Daily EBS snapshots via Data Lifecycle Manager
resource "aws_dlm_lifecycle_policy" "langfuse_clickhouse_snapshots" {
  count = local.create_langfuse ? 1 : 0

  description        = "Daily snapshots for Langfuse ClickHouse data volume"
  execution_role_arn = aws_iam_role.langfuse_dlm[0].arn
  state              = "ENABLED"

  policy_details {
    resource_types = ["VOLUME"]

    schedule {
      name = "daily-snapshot"

      create_rule {
        interval      = 24
        interval_unit = "HOURS"
        times         = ["03:00"]
      }

      retain_rule {
        count = 7
      }

      tags_to_add = {
        SnapshotCreator = "DLM"
        Service         = local.langfuse_service_name
        service_name    = local.langfuse_service_name
      }
    }

    target_tags = {
      Name = "${var.environment}-${local.langfuse_service_name}-clickhouse-data"
    }
  }
}

resource "aws_iam_role" "langfuse_dlm" {
  count = local.create_langfuse ? 1 : 0

  name = "${var.environment}-${local.langfuse_service_name}-dlm-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Effect    = "Allow"
      Principal = { Service = "dlm.amazonaws.com" }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "langfuse_dlm" {
  count = local.create_langfuse ? 1 : 0

  role       = aws_iam_role.langfuse_dlm[0].name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSDataLifecycleManagerServiceRole"
}

# ---------------------------------------------------------------------------
# S3 (raw events, attachments, exports)
# ---------------------------------------------------------------------------

module "s3_langfuse" {
  count  = local.create_langfuse ? 1 : 0
  source = "git@github.com:theorchard/terraform-s3.git//modules/s3_bucket?ref=3.15.7"

  env                 = var.environment
  application_family  = var.application_family
  bucket_name         = "${local.langfuse_service_name}-storage"
  block_public_access = true

  apply_server_side_encryption_by_default = {
    sse_algorithm     = "aws:kms"
    kms_master_key_id = data.aws_kms_alias.s3.target_key_arn
  }

  # Lifecycle rules — passed through the module (it creates its own lifecycle config)
  lifecycle_rules_options_current_version_transition = [
    {
      prefix        = ""
      enabled       = true
      days          = 90
      storage_class = "STANDARD_IA"
    },
  ]

  # Module default: abort incomplete multipart uploads after 7 days (no override needed)
}

# ---------------------------------------------------------------------------
# Secrets Manager (KMS-encrypted, passwords auto-generated)
# ---------------------------------------------------------------------------

# Secrets created via the org module (empty — values populated below or manually)
module "langfuse_secrets" {
  source = "git@github.com:theorchard/terraform-secrets-manager.git//?ref=1.6.1"
  for_each = local.create_langfuse ? toset([
    "LANGFUSE_PUBLIC_KEY",
    "LANGFUSE_SECRET_KEY",
  ]) : toset([])

  application_family = var.application_family
  environment        = var.environment
  service_name       = local.langfuse_service_name
  secret_name        = each.value
}

# Secrets with auto-generated values — created directly for version control
resource "aws_secretsmanager_secret" "langfuse_db_password" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}/${local.langfuse_service_name}/DATABASE_PASSWORD"
  description = "Langfuse Aurora PostgreSQL master password"
  kms_key_id  = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_secretsmanager_secret_version" "langfuse_db_password" {
  count = local.create_langfuse ? 1 : 0

  secret_id     = aws_secretsmanager_secret.langfuse_db_password[0].id
  secret_string = random_password.langfuse_db[0].result
}

resource "aws_secretsmanager_secret" "langfuse_clickhouse_password" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}/${local.langfuse_service_name}/CLICKHOUSE_PASSWORD"
  description = "Langfuse ClickHouse user password"
  kms_key_id  = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_secretsmanager_secret_version" "langfuse_clickhouse_password" {
  count = local.create_langfuse ? 1 : 0

  secret_id     = aws_secretsmanager_secret.langfuse_clickhouse_password[0].id
  secret_string = random_password.langfuse_clickhouse[0].result
}

resource "aws_secretsmanager_secret" "langfuse_database_url" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}/${local.langfuse_service_name}/DATABASE_URL"
  description = "Langfuse full PostgreSQL connection URL (includes password)"
  kms_key_id  = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_secretsmanager_secret_version" "langfuse_database_url" {
  count = local.create_langfuse ? 1 : 0

  secret_id     = aws_secretsmanager_secret.langfuse_database_url[0].id
  secret_string = "postgresql://${var.langfuse_db_username}:${random_password.langfuse_db[0].result}@${module.langfuse_rds[0].rds_cluster_endpoint}:5432/langfuse"
}

resource "aws_secretsmanager_secret" "langfuse_nextauth_secret" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}/${local.langfuse_service_name}/NEXTAUTH_SECRET"
  description = "Langfuse NextAuth.js session encryption secret"
  kms_key_id  = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_secretsmanager_secret_version" "langfuse_nextauth_secret" {
  count = local.create_langfuse ? 1 : 0

  secret_id     = aws_secretsmanager_secret.langfuse_nextauth_secret[0].id
  secret_string = random_password.langfuse_nextauth[0].result
}

resource "aws_secretsmanager_secret" "langfuse_salt" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}/${local.langfuse_service_name}/SALT"
  description = "Langfuse hashing salt"
  kms_key_id  = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_secretsmanager_secret_version" "langfuse_salt" {
  count = local.create_langfuse ? 1 : 0

  secret_id     = aws_secretsmanager_secret.langfuse_salt[0].id
  secret_string = random_password.langfuse_salt[0].result
}

resource "aws_secretsmanager_secret" "langfuse_encryption_key" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}/${local.langfuse_service_name}/ENCRYPTION_KEY"
  description = "Langfuse v3 encryption key (256-bit hex)"
  kms_key_id  = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_secretsmanager_secret_version" "langfuse_encryption_key" {
  count = local.create_langfuse ? 1 : 0

  secret_id     = aws_secretsmanager_secret.langfuse_encryption_key[0].id
  secret_string = random_id.langfuse_encryption_key[0].hex
}

resource "aws_secretsmanager_secret" "langfuse_init_user_password" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}/${local.langfuse_service_name}/LANGFUSE_INIT_USER_PASSWORD"
  description = "Langfuse seed admin user password (first boot only)"
  kms_key_id  = aws_kms_key.langfuse_secrets[0].arn
}

resource "aws_secretsmanager_secret_version" "langfuse_init_user_password" {
  count = local.create_langfuse ? 1 : 0

  secret_id     = aws_secretsmanager_secret.langfuse_init_user_password[0].id
  secret_string = random_password.langfuse_init_user[0].result
}

# Construct ClickHouse URLs with auth for Fargate tasks
locals {
  langfuse_clickhouse_http_url   = local.create_langfuse ? "http://langfuse:${random_password.langfuse_clickhouse[0].result}@${aws_instance.langfuse_clickhouse[0].private_ip}:8123" : ""
  langfuse_clickhouse_native_url = local.create_langfuse ? "clickhouse://langfuse:${random_password.langfuse_clickhouse[0].result}@${aws_instance.langfuse_clickhouse[0].private_ip}:9000" : ""
}

# ---------------------------------------------------------------------------
# Security group (shared by Web + Worker tasks)
# ---------------------------------------------------------------------------

resource "aws_security_group" "langfuse_task" {
  count = local.create_langfuse ? 1 : 0

  name        = "${var.environment}-${local.langfuse_service_name}-task-sg"
  description = "Langfuse Fargate task networking"
  vpc_id      = module.vpc_info.vpc_id

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name         = "${var.environment}-${local.langfuse_service_name}-task-sg"
    service_name = local.langfuse_service_name
  }
}

# ---------------------------------------------------------------------------
# Langfuse Web (UI + API) — web_service creates its own ALB
# ---------------------------------------------------------------------------

module "langfuse_web_fargate" {
  count  = local.create_langfuse ? 1 : 0
  source = "git@github.com:theorchard/terraform-fargate.git//?ref=6.5.0"

  providers = {
    aws.dns = aws.networking
  }

  environment        = var.environment
  service_name       = local.langfuse_web_service_name
  application_family = var.application_family
  vpc_id             = module.vpc_info.vpc_id

  task_type      = "web_service"
  container_port = tostring(local.langfuse_web_port)

  web_service_health_check_command = "node -e \"require('http').get('http://127.0.0.1:3000/api/public/health',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))\""

  route53_record_creation_enabled = false

  desired_task_count = 1
  task_cpu           = 2048
  task_memory        = 4096
  maximum_capacity   = 2
  minimum_capacity   = 1

  health_check_path         = "/api/public/health"
  load_balancer_is_internal = true

  fargate_service_subnets = module.vpc_info.default_private_subnet_ids
  load_balancer_subnets   = module.vpc_info.default_private_subnet_ids

  custom_security_group_ids = [aws_security_group.langfuse_task[0].id]

  # Secrets live under ows-coda-langfuse/*, not ows-coda-langfuse-web/*.
  execution_role_iam_managed_policy_attachments = [
    aws_iam_policy.langfuse_secrets_access[0].arn,
  ]

  environment_variables = [
    { CLICKHOUSE_URL = local.langfuse_clickhouse_http_url },
    { CLICKHOUSE_MIGRATION_URL = local.langfuse_clickhouse_native_url },
    { CLICKHOUSE_USER = "langfuse" },
    { CLICKHOUSE_CLUSTER_ENABLED = "false" },
    { NEXTAUTH_URL = "https://${var.environment}-${local.langfuse_web_service_name}.theorchard.io" },
    { LANGFUSE_S3_EVENT_UPLOAD_ENABLED = "true" },
    { LANGFUSE_S3_EVENT_UPLOAD_BUCKET = module.s3_langfuse[0].s3_bucket_name_output },
    { LANGFUSE_S3_EVENT_UPLOAD_REGION = var.region },
    { LANGFUSE_S3_MEDIA_UPLOAD_BUCKET = module.s3_langfuse[0].s3_bucket_name_output },
    { LANGFUSE_S3_MEDIA_UPLOAD_REGION = var.region },
    { LANGFUSE_S3_BATCH_EXPORT_BUCKET = module.s3_langfuse[0].s3_bucket_name_output },
    { LANGFUSE_S3_BATCH_EXPORT_REGION = var.region },
    # Redis DB 1 — DB 0 is used by the main ows-coda service
    { REDIS_CONNECTION_STRING = "rediss://${local.redis_host}:6379/1" },
    { LANGFUSE_INIT_ORG_ID = "coda" },
    { LANGFUSE_INIT_ORG_NAME = "Coda" },
    { LANGFUSE_INIT_PROJECT_ID = "coda-project" },
    { LANGFUSE_INIT_PROJECT_NAME = "Coda" },
    # Seed admin user on first boot — dummy values, ignored on subsequent starts
    { LANGFUSE_INIT_USER_EMAIL = "michael.rojas@sonymusic-pde.com" },
    { LANGFUSE_INIT_USER_NAME = "Admin" },
  ]

  secrets = [
    { DATABASE_URL = "${var.environment}/${local.langfuse_service_name}/DATABASE_URL" },
    { NEXTAUTH_SECRET = "${var.environment}/${local.langfuse_service_name}/NEXTAUTH_SECRET" },
    { SALT = "${var.environment}/${local.langfuse_service_name}/SALT" },
    { CLICKHOUSE_PASSWORD = "${var.environment}/${local.langfuse_service_name}/CLICKHOUSE_PASSWORD" },
    { ENCRYPTION_KEY = "${var.environment}/${local.langfuse_service_name}/ENCRYPTION_KEY" },
    { LANGFUSE_INIT_USER_PASSWORD = "${var.environment}/${local.langfuse_service_name}/LANGFUSE_INIT_USER_PASSWORD" },
    { LANGFUSE_INIT_PROJECT_PUBLIC_KEY = "${var.environment}/${local.langfuse_service_name}/LANGFUSE_PUBLIC_KEY" },
    { LANGFUSE_INIT_PROJECT_SECRET_KEY = "${var.environment}/${local.langfuse_service_name}/LANGFUSE_SECRET_KEY" },
  ]
}

# ---------------------------------------------------------------------------
# Langfuse Worker (async event processing) — worker type, no ALB
# ---------------------------------------------------------------------------

module "langfuse_worker_fargate" {
  count  = local.create_langfuse ? 1 : 0
  source = "git@github.com:theorchard/terraform-fargate.git//?ref=6.5.0"

  providers = {
    aws.dns = aws.networking
  }

  environment        = var.environment
  service_name       = local.langfuse_worker_service_name
  application_family = var.application_family
  vpc_id             = module.vpc_info.vpc_id

  task_type      = "worker"
  container_port = tostring(local.langfuse_worker_port)

  health_check_command = "node -e \"require('http').get('http://127.0.0.1:3030/api/health',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))\""

  desired_task_count = 1
  task_cpu           = 2048
  task_memory        = 4096
  maximum_capacity   = 2
  minimum_capacity   = 1

  fargate_service_subnets = module.vpc_info.default_private_subnet_ids

  custom_security_group_ids = [aws_security_group.langfuse_task[0].id]

  # Secrets live under ows-coda-langfuse/*, not ows-coda-langfuse-worker/*.
  execution_role_iam_managed_policy_attachments = [
    aws_iam_policy.langfuse_secrets_access[0].arn,
  ]

  environment_variables = [
    { CLICKHOUSE_URL = local.langfuse_clickhouse_http_url },
    { CLICKHOUSE_MIGRATION_URL = local.langfuse_clickhouse_native_url },
    { CLICKHOUSE_USER = "langfuse" },
    { CLICKHOUSE_CLUSTER_ENABLED = "false" },
    { LANGFUSE_S3_EVENT_UPLOAD_ENABLED = "true" },
    { LANGFUSE_S3_EVENT_UPLOAD_BUCKET = module.s3_langfuse[0].s3_bucket_name_output },
    { LANGFUSE_S3_EVENT_UPLOAD_REGION = var.region },
    { LANGFUSE_S3_MEDIA_UPLOAD_BUCKET = module.s3_langfuse[0].s3_bucket_name_output },
    { LANGFUSE_S3_MEDIA_UPLOAD_REGION = var.region },
    { LANGFUSE_S3_BATCH_EXPORT_BUCKET = module.s3_langfuse[0].s3_bucket_name_output },
    { LANGFUSE_S3_BATCH_EXPORT_REGION = var.region },
    # Redis DB 1 — DB 0 is used by the main ows-coda service
    { REDIS_CONNECTION_STRING = "rediss://${local.redis_host}:6379/1" },
    { LANGFUSE_WORKER_HOST = "0.0.0.0" },
    { LANGFUSE_WORKER_PORT = tostring(local.langfuse_worker_port) },
  ]

  secrets = [
    { DATABASE_URL = "${var.environment}/${local.langfuse_service_name}/DATABASE_URL" },
    { NEXTAUTH_SECRET = "${var.environment}/${local.langfuse_service_name}/NEXTAUTH_SECRET" },
    { SALT = "${var.environment}/${local.langfuse_service_name}/SALT" },
    { CLICKHOUSE_PASSWORD = "${var.environment}/${local.langfuse_service_name}/CLICKHOUSE_PASSWORD" },
    { ENCRYPTION_KEY = "${var.environment}/${local.langfuse_service_name}/ENCRYPTION_KEY" },
  ]
}

# ---------------------------------------------------------------------------
# Route 53 — internal DNS for Langfuse Web UI (VPN-only access via internal ALB)
# ---------------------------------------------------------------------------

resource "aws_route53_record" "langfuse" {
  count = local.create_langfuse ? 1 : 0

  provider = aws.networking
  zone_id  = data.aws_route53_zone.theorchard_io[0].zone_id
  name     = "${var.environment}-${local.langfuse_web_service_name}.theorchard.io"
  type     = "A"

  alias {
    name                   = module.langfuse_web_fargate[0].fargate_load_balancer_dns_name
    zone_id                = module.langfuse_web_fargate[0].fargate_load_balancer_dns_zone_id
    evaluate_target_health = true
  }
}
