#
# Dedicated origin for the Auth0 ACUL login bundle (login.js / login.css).
#
# Why separate from the app static buckets: this bundle runs on Auth0's credential
# page for EVERY app in the tenant. Hosting it here — a private, OAI-only bucket with
# a tightly-scoped write surface — keeps it off the front-end deploy pipeline, and
# versioned object prefixes (v/<build>/login.js) let a new version roll out without
# breaking the URL Auth0 has cached, so login never couples to unrelated app deploys.
#
# Deploy contract (CI, not terraform):
#   1. Upload the built bundle to  s3://<bucket>/v/<build-id>/login.{js,css}   (never overwrite a prior <build-id>)
#   2. Build rendering.json with   ACUL_ASSET_BASE_URL=https://acul.<console_domain>/v/<build-id>   (gen-rendering.mjs pins SRI)
#   3. Apply rendering.json to the tenant, then optionally prune old versions once Auth0 no longer references them.
#
# Hostname reuses the nfconsole wildcard cert (*.<console_domain> already covers acul.<console_domain>).

locals {
  acul_bucket = "nf-acul-${local.deploy_environment}"
  acul_domain = "acul.${local.console_domain}"
}

# Auth0 custom login domains permitted to load the bundle. ACUL renders only on the tenant's
# custom domain, so these are the exact page origins that fetch login.js/css cross-origin.
# Keep in sync with the live Auth0 custom domain(s) — a mismatch means the browser blocks the
# bundle and login breaks. List both entries during a custom-domain migration, then trim.
variable "acul_login_origins" {
  type = map(list(string))
  default = {
    nf-sandbox     = ["https://login.sandbox-nfconsole.io", "https://login.sandbox.netfoundry.io"]
    nf-staging-int = ["https://login.staging.netfoundry.io"]
    nf-prod-int    = ["https://login.netfoundry.io"]
  }
}

resource "aws_s3_bucket" "acul" {
  bucket = local.acul_bucket
}

# Retain overwritten objects as a safety net (the primary rollover mechanism is versioned prefixes).
resource "aws_s3_bucket_versioning" "acul" {
  bucket = aws_s3_bucket.acul.id
  versioning_configuration {
    status = "Enabled"
  }
}

# Private bucket: no public ACLs or policies. CloudFront reads via the OAI below.
resource "aws_s3_bucket_public_access_block" "acul" {
  bucket                  = aws_s3_bucket.acul.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_cloudfront_origin_access_identity" "acul" {
  comment = "OAI for the ACUL login bundle origin"
}

# Only the CloudFront OAI may read; writes come solely from the CI deploy role (managed outside this file).
data "aws_iam_policy_document" "acul" {
  version = "2012-10-17"

  statement {
    sid       = "AllowCloudFrontOAIRead"
    actions   = ["s3:GetObject"]
    resources = ["${aws_s3_bucket.acul.arn}/*"]

    principals {
      type        = "AWS"
      identifiers = [aws_cloudfront_origin_access_identity.acul.iam_arn]
    }
  }
}

resource "aws_s3_bucket_policy" "acul" {
  bucket = aws_s3_bucket.acul.id
  policy = data.aws_iam_policy_document.acul.json
}

# CORS: Auth0's login page loads the bundle as a cross-origin module with crossorigin=anonymous
# (required for SRI), so the response must carry Access-Control-Allow-Origin. Versioned prefixes
# make the objects immutable, so cache them hard.
resource "aws_cloudfront_response_headers_policy" "acul" {
  name = "acul-${local.deploy_environment}"

  cors_config {
    access_control_allow_credentials = false

    access_control_allow_headers {
      items = ["*"]
    }
    access_control_allow_methods {
      items = ["GET", "HEAD", "OPTIONS"]
    }
    # Scoped to the tenant's custom login domain(s), not "*". CloudFront echoes the matching
    # request Origin per response (and adds Vary: Origin), so this stays correct across the
    # listed origins even with a shared cache.
    access_control_allow_origins {
      items = var.acul_login_origins[terraform.workspace]
    }
    origin_override = true
  }

  custom_headers_config {
    items {
      header   = "Cache-Control"
      value    = "public, max-age=31536000, immutable"
      override = true
    }
  }
}

resource "aws_cloudfront_distribution" "acul" {
  origin {
    domain_name = aws_s3_bucket.acul.bucket_regional_domain_name
    origin_id   = "S3-${local.acul_bucket}"

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.acul.cloudfront_access_identity_path
    }
  }

  enabled         = true
  is_ipv6_enabled = true
  comment         = "ACUL login bundle - ${local.deploy_environment}"

  aliases = [local.acul_domain]

  logging_config {
    include_cookies = false
    bucket          = aws_s3_bucket.nfconsole_io_logs.bucket_domain_name
    prefix          = "acul"
  }

  default_cache_behavior {
    allowed_methods            = ["GET", "HEAD", "OPTIONS"]
    cached_methods             = ["GET", "HEAD", "OPTIONS"]
    target_origin_id           = "S3-${local.acul_bucket}"
    viewer_protocol_policy     = "redirect-to-https"
    compress                   = true
    # Managed CachingOptimized cache policy; CORS is added at the edge by the response-headers
    # policy (wildcard origin, so the request Origin need not reach S3 or enter the cache key).
    cache_policy_id            = "658327ea-f89d-4fab-a63d-7e88639e58f6"
    response_headers_policy_id = aws_cloudfront_response_headers_policy.acul.id
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    acm_certificate_arn      = module.route53_nfconsole.arn
    ssl_support_method       = "sni-only"
    minimum_protocol_version = "TLSv1.2_2018"
  }

  tags = {
    Environment = local.deploy_environment
  }
}

# acul.<console_domain> -> the dedicated distribution (specific record wins over the console wildcard).
resource "aws_route53_record" "acul" {
  zone_id = module.route53_nfconsole.zone_id
  name    = local.acul_domain
  type    = "A"

  alias {
    name                   = aws_cloudfront_distribution.acul.domain_name
    zone_id                = aws_cloudfront_distribution.acul.hosted_zone_id
    evaluate_target_health = false
  }
}

output "acul_bucket" {
  value = aws_s3_bucket.acul.bucket
}

output "acul_domain" {
  value = local.acul_domain
}
