# ---------------------------------------------------------------------------------------------------------------------
# API GATEWAY
# ---------------------------------------------------------------------------------------------------------------------

locals {
  {{ ms_name }}_authorizer_uri = "arn:aws:apigateway:${local.region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${local.region}:${local.account_id}:function:{{ ms_name }}-$${stageVariables.stage}/invocations"
{% if workspace != "common" %}
  {{ ms_name }}_api_arn = data.aws_api_gateway_rest_api.{{ ms_name }}.arn
  {{ ms_name }}_api_id = data.aws_api_gateway_rest_api.{{ ms_name }}.id
  {{ ms_name }}_api_root_id = data.aws_api_gateway_rest_api.{{ ms_name }}.root_resource_id
{% else %}
  {{ ms_name }}_api_arn = aws_api_gateway_rest_api.{{ ms_name }}.arn
  {{ ms_name }}_api_id = aws_api_gateway_rest_api.{{ ms_name }}.id
  {{ ms_name }}_api_root_id = aws_api_gateway_rest_api.{{ ms_name }}.root_resource_id
{% endif %}
  {{ ms_name }}_api_binary_media_types = ["multipart/form-data", "application/octet-stream", "application/pdf", "image/*"
    {%- if binary_types -%}{%- for type in binary_types -%},"{{ type }}"{%- endfor -%}{%- endif -%}]
}

{% if workspace == "common" %}
resource "aws_api_gateway_rest_api" "{{ ms_name }}" {
  provider = aws.{{ ms_name }}
  {% block aws_api_gateway_rest_api %}
  name = "{{ ms_name }}"
  description = "{{ description | replace("\n", "\\n") }}"
  binary_media_types = local.{{ ms_name }}_api_binary_media_types
  endpoint_configuration {
    types = ["REGIONAL"]
  }
  {% endblock %}
}

resource "aws_api_gateway_authorizer" "{{ ms_name }}" {
  provider = aws.{{ ms_name }}
  {% block aws_api_gateway_authorizer %}
  name = "{{ ms_name }}-auth"
  rest_api_id = local.{{ ms_name }}_api_id
  authorizer_uri = local.{{ ms_name }}_authorizer_uri
  authorizer_result_ttl_in_seconds = 0
  identity_source = "method.request.header.{{ token_key if token_key else 'Authorization' }}"
  {% endblock %}
}

{% for uid, resource in api_resources.items() %}
  {% if resource.path %}
resource "aws_api_gateway_resource" "{{ ms_name }}_{{ uid }}" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.parent_is_root %}
  parent_id = local.{{ ms_name }}_api_root_id
  {% else %}
  parent_id = aws_api_gateway_resource.{{ ms_name }}_{{ resource.parent_uid }}.id
  {% endif %}
  path_part = "{{ resource.path }}"
}
  {% endif %}
  {% if resource.rules %}
    {% for rule in resource.rules %}
    {% for method in rule.methods if method not in ['HEAD', 'OPTIONS'] %}
resource "aws_api_gateway_method" "{{ ms_name }}_{{ uid }}_{{ method }}" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.path %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% else %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% endif %}
  http_method = "{{ method }}"
  {% if rule.cws_no_auth %}
  authorization = "NONE"
  {% else %}
  authorization = "CUSTOM"
  authorizer_id = aws_api_gateway_authorizer.{{ ms_name }}.id
  {% endif %}
  request_parameters = {
    "method.request.header.Accept" = false
    "method.request.header.InvocationType" = false
    "method.request.header.Referer" = false
    "method.request.header.X-Forwarded-Host" = false
  }
}
resource "aws_api_gateway_integration" "{{ ms_name }}_{{ uid }}_{{ method }}" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.path %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% else %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% endif %}
  http_method = "{{ method }}"
  integration_http_method = "POST"
  type = "AWS"
  uri = local.{{ ms_name }}_authorizer_uri
  passthrough_behavior = "NEVER"
  content_handling = "CONVERT_TO_TEXT"
  request_parameters = {
    "integration.request.header.Accept" = "method.request.header.Accept",
    "integration.request.header.Referer" = "method.request.header.Referer",
    "integration.request.header.X-Amz-Invocation-Type" = "method.request.header.InvocationType",
    "integration.request.header.X-Forwarded-Host" = "method.request.header.X-Forwarded-Host",
  }
  request_templates  = {
    {% include "terraform/request_templates.j2" %}
  }
  depends_on = [aws_api_gateway_method.{{ ms_name }}_{{ uid }}_{{ method }}]
}
resource "aws_api_gateway_integration_response" "{{ ms_name }}_{{ uid }}_{{ method }}_200" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.path %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% else %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% endif %}
  http_method = join("", aws_api_gateway_method.{{ ms_name }}_{{ uid }}_{{ method }}.*.http_method)
  status_code = "200"
  {% if rule.cws_binary_headers %}
  response_parameters = {
  {% for k, v in rule.cws_binary_headers.items() %}
    "method.response.header.{{ k }}" = "'{{ v }}'",
  {% endfor %}
  }
  {% endif %}
  {% if not rule.cws_binary_headers %}
  response_templates = {
    {% include "terraform/response_templates.j2" %}
  }
  {% endif %}
  depends_on = [aws_api_gateway_method_response.{{ ms_name }}_{{ uid }}_{{ method }}_200]
}
resource "aws_api_gateway_method_response" "{{ ms_name }}_{{ uid }}_{{ method }}_200" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.path %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% else %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% endif %}
  http_method = "{{ method }}"
  status_code = "200"
  {% if rule.cws_binary_headers %}
  response_parameters = {
    {% for k in rule.cws_binary_headers.keys() %}
    "method.response.header.{{ k }}" = true,
    {% endfor %}
  }
  {% endif %}
  depends_on = [aws_api_gateway_method.{{ ms_name }}_{{ uid }}_{{ method }}]
}
{% endfor %}
{% endfor %}

{# Preflighted requests in CORS #}

{% if not resource.no_cors_methods %}
resource "aws_api_gateway_method" "{{ ms_name }}_{{ uid }}_OPTIONS" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.is_root %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% else %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% endif %}
  http_method = "OPTIONS"
  authorization = "NONE"
}
resource "aws_api_gateway_integration" "{{ ms_name }}_{{ uid }}_OPTIONS" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.is_root %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% else %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% endif %}
  http_method = "OPTIONS"
  type = "MOCK"
  request_templates = {
    "application/json" = "{ \"statusCode\": 200 }"
  }
  depends_on = [aws_api_gateway_method.{{ ms_name }}_{{ uid }}_OPTIONS]
}
resource "aws_api_gateway_integration_response" "{{ ms_name }}_{{ uid }}_OPTIONS" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.is_root %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% else %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% endif %}
  http_method = "OPTIONS"
  status_code = 200
  response_templates = {
    "application/json": <<-EOF
      #set($context.responseOverride.header={
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token',
        'Access-Control-Allow-Methods': '{%- for method in resource.no_cors_methods -%}{{ method }}{%- endfor -%}'
      })
    EOF
  }
  depends_on = [aws_api_gateway_method_response.{{ ms_name }}_{{ uid }}_OPTIONS]
}
resource "aws_api_gateway_method_response" "{{ ms_name }}_{{ uid }}_OPTIONS" {
  provider = aws.{{ ms_name }}
  rest_api_id = local.{{ ms_name }}_api_id
  {% if resource.is_root %}
  resource_id = local.{{ ms_name }}_api_root_id
  {% else %}
  resource_id = aws_api_gateway_resource.{{ ms_name }}_{{ uid }}.id
  {% endif %}
  http_method = "OPTIONS"
  status_code = 200
  response_models = {
    "application/json" = "Empty"
  }
  response_parameters = {
    "method.response.header.Access-Control-Allow-Headers" = true,
    "method.response.header.Access-Control-Allow-Methods" = true,
    "method.response.header.Access-Control-Allow-Origin" = true,
    "method.response.header.Access-Control-Allow-Credentials" = true,
  }
  depends_on = [aws_api_gateway_method.{{ ms_name }}_{{ uid }}_OPTIONS]
}
{% endif %}
{% endif %}
{% endfor %}

{% else %}
data "aws_api_gateway_rest_api" "{{ ms_name }}" {
  provider = aws.{{ ms_name }}
  name = "{{ ms_name }}"
}

{# No deployment if no entries #}
{% if api_resources %}
resource "aws_api_gateway_deployment" "{{ ms_name }}" {
  provider = aws.{{ ms_name }}
  {% block aws_api_gateway_deployment %}
  rest_api_id = local.{{ ms_name }}_api_id
  description = "{{ workspace }}: at ${timestamp()}"
  triggers = {
    timestamp = timestamp() {# force redeployment #}
  }
  lifecycle {
    create_before_destroy = true
  }
  depends_on = [aws_cloudwatch_log_group.api_{{ ms_name }}]
  {% endblock %}
}

resource "aws_api_gateway_stage" "{{ ms_name }}" {
  provider = aws.{{ ms_name }}
  {% block aws_api_gateway_stage %}
  stage_name = "{{ stage }}"
  rest_api_id = local.{{ ms_name }}_api_id
  deployment_id = aws_api_gateway_deployment.{{ ms_name }}.id
  xray_tracing_enabled = true
  depends_on = [aws_cloudwatch_log_group.api_{{ ms_name }}]
  variables = {
    stage = "{{ stage }}"
  }
  {% endblock %}
}

resource "aws_cloudwatch_log_group" "api_{{ ms_name }}" {
  provider = aws.{{ ms_name }}
  {% block aws_cloudwatch_log_group %}
  name = "API-Gateway-Execution-Logs_${local.{{ ms_name }}_api_id}/{{ stage }}"
  retention_in_days = 7
  {% endblock %}
}

resource "aws_api_gateway_method_settings" "api_{{ ms_name }}" {
  provider = aws.{{ ms_name }}
  {% block aws_api_gateway_method_settings %}
  rest_api_id = local.{{ ms_name }}_api_id
  stage_name  = aws_api_gateway_stage.{{ ms_name }}.stage_name
  method_path = "*/*"

  settings {
    metrics_enabled = true
    logging_level = "INFO"
    data_trace_enabled = true
  }
  {% endblock %}
}
{% endif %}

{% endif %}
