# S3 bucket for static website hosting
resource "aws_s3_bucket" "frontend" {
  bucket = "${var.app_name}-frontend"

  tags = {
    Name        = "${var.app_name}-frontend"
    Environment = var.environment
  }
}

# S3 bucket website configuration
resource "aws_s3_bucket_website_configuration" "frontend" {
  bucket = aws_s3_bucket.frontend.id

  index_document {
    suffix = "index.html"
  }

  error_document {
    key = "404.html"
  }
}

# S3 bucket public access block (we'll use CloudFront OAC instead)
resource "aws_s3_bucket_public_access_block" "frontend" {
  bucket = aws_s3_bucket.frontend.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# CloudFront Origin Access Control
resource "aws_cloudfront_origin_access_control" "frontend" {
  name                              = "${var.app_name}-frontend-oac"
  description                       = "OAC for ${var.app_name} frontend"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

# CloudFront Function for directory index rewrites
resource "aws_cloudfront_function" "index_rewrite" {
  name    = "${var.app_name}-index-rewrite"
  runtime = "cloudfront-js-1.0"
  comment = "Rewrite directory requests to index.html"
  publish = true
  code    = file("${path.module}/cloudfront-function.js")
}

# CloudFront distribution
resource "aws_cloudfront_distribution" "frontend" {
  enabled             = true
  is_ipv6_enabled     = true
  comment             = "${var.app_name} frontend"
  default_root_object = "index.html"
  price_class         = "PriceClass_100" # US, Canada, Europe only (cheapest)

  # No aliases - Cloudflare will proxy to CloudFront's default domain
  # aliases = var.domain_name != "" ? [var.domain_name, "www.${var.domain_name}"] : []

  origin {
    domain_name              = aws_s3_bucket.frontend.bucket_regional_domain_name
    origin_id                = "S3-${aws_s3_bucket.frontend.id}"
    origin_access_control_id = aws_cloudfront_origin_access_control.frontend.id
  }

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "S3-${aws_s3_bucket.frontend.id}"

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 3600   # 1 hour
    max_ttl                = 86400  # 24 hours
    compress               = true

    function_association {
      event_type   = "viewer-request"
      function_arn = aws_cloudfront_function.index_rewrite.arn
    }
  }

  # Custom error responses for SPA routing
  custom_error_response {
    error_code            = 404
    response_code         = 200
    response_page_path    = "/index.html"
    error_caching_min_ttl = 300
  }

  custom_error_response {
    error_code            = 403
    response_code         = 200
    response_page_path    = "/index.html"
    error_caching_min_ttl = 300
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  # Use default CloudFront certificate (we'll handle SSL via Cloudflare)
  viewer_certificate {
    cloudfront_default_certificate = true
    # If you want CloudFront SSL, add ACM certificate here
    # acm_certificate_arn      = aws_acm_certificate.cert.arn
    # ssl_support_method       = "sni-only"
    # minimum_protocol_version = "TLSv1.2_2021"
  }

  tags = {
    Name        = "${var.app_name}-frontend"
    Environment = var.environment
  }
}

# S3 bucket policy to allow CloudFront OAC access
resource "aws_s3_bucket_policy" "frontend" {
  bucket = aws_s3_bucket.frontend.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowCloudFrontServicePrincipal"
        Effect = "Allow"
        Principal = {
          Service = "cloudfront.amazonaws.com"
        }
        Action   = "s3:GetObject"
        Resource = "${aws_s3_bucket.frontend.arn}/*"
        Condition = {
          StringEquals = {
            "AWS:SourceArn" = aws_cloudfront_distribution.frontend.arn
          }
        }
      }
    ]
  })
}

# Cloudflare DNS records for frontend
resource "cloudflare_record" "frontend_root" {
  count   = var.domain_name != "" && var.cloudflare_api_token != "" ? 1 : 0
  zone_id = data.cloudflare_zone.domain[0].id
  name    = "@"
  type    = "CNAME"
  value   = aws_cloudfront_distribution.frontend.domain_name
  ttl     = 1
  proxied = true # Enable Cloudflare proxy for SSL and caching
  comment = "CloudFront distribution for frontend"
}

resource "cloudflare_record" "frontend_www" {
  count   = var.domain_name != "" && var.cloudflare_api_token != "" ? 1 : 0
  zone_id = data.cloudflare_zone.domain[0].id
  name    = "www"
  type    = "CNAME"
  value   = aws_cloudfront_distribution.frontend.domain_name
  ttl     = 1
  proxied = true # Enable Cloudflare proxy for SSL and caching
  comment = "CloudFront distribution for frontend (www)"
}

# Cloudflare Transform Rule to rewrite Host header for CloudFront
resource "cloudflare_ruleset" "frontend_host_header_rewrite" {
  count   = var.domain_name != "" && var.cloudflare_api_token != "" ? 1 : 0
  zone_id = data.cloudflare_zone.domain[0].id
  name    = "Rewrite Host header for CloudFront"
  kind    = "zone"
  phase   = "http_request_late_transform"

  rules {
    action = "rewrite"
    expression = "(http.host eq \"${var.domain_name}\" or http.host eq \"www.${var.domain_name}\")"
    description = "Rewrite Host header to CloudFront domain"

    action_parameters {
      headers {
        name      = "Host"
        operation = "set"
        value     = aws_cloudfront_distribution.frontend.domain_name
      }
    }
  }
}
