# ---------------------------------------------------------------------------------------------------------------------
# LAMBDA
# ---------------------------------------------------------------------------------------------------------------------

{%- if not lambda_zip_file %}
  data "archive_file" "{{ module_file }}" {
  source_file = "{{ project_dir }}/{{ module_dir }}/{{ module_file }}.py"
  output_path = "{{ module_file }}.zip"
  type = "zip"
  }
{% endif -%}

resource "aws_lambda_function" "{{ app_name }}" {
filename ={%- if lambda_zip_file %}{{ lambda_zip_file }}
{% else %}data.archive_file.{{ module_file }}.output_path
{% endif -%}
function_name = "{{ app_name }}"
role = aws_iam_role.{{ app_name }}.arn
handler = "{{ module_file }}.{{ handler }}"
runtime = "python3.7"
description = "This is my first coworks microservice"

source_code_hash = filebase64sha256(data.archive_file.{{ module_file }}.output_path)
layers = [aws_lambda_layer_version.coworks_layer.arn]

tags = {
Name: "{{ module_file }}"
Creator: "coworks"
}
}

resource "aws_lambda_permission" "{{ app_name }}" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.{{ app_name }}.function_name
principal = "apigateway.amazonaws.com"
}

resource "aws_iam_role" "{{ app_name }}" {
name = "{{ app_name }}"
assume_role_policy = data.aws_iam_policy_document.{{ app_name }}.json
}
data "aws_iam_policy_document" "{{ app_name }}" {
statement {
effect = "Allow"
principals {
identifiers = [
"apigateway.amazonaws.com",
"lambda.amazonaws.com",
]
type = "Service"
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role_policy_attachment" "{{ app_name }}" {
role = aws_iam_role.{{ app_name }}.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"
}

resource "aws_lambda_layer_version" "coworks_layer" {
layer_name = "coworks"
filename   = "layer.zip"

compatible_runtimes = ["python3.7"]
}

# ---------------------------------------------------------------------------------------------------------------------
# APIGATEWAY
# ---------------------------------------------------------------------------------------------------------------------

resource "aws_api_gateway_rest_api" "{{ app_name }}" {
name = "{{ app_name }}"
description = "This is my API for my first coworks microservice"
}

locals {
{{ app_name }} = {
api_id: aws_api_gateway_rest_api.{{ app_name }}.id
root_id: aws_api_gateway_rest_api.{{ app_name }}.root_resource_id
}
}

resource "aws_api_gateway_authorizer" "{{ app_name }}" {
name = "{{ module_file }}-{{ app_name }}-auth"
rest_api_id = local.{{ app_name }}.api_id
authorizer_uri = aws_lambda_function.{{ app_name }}.invoke_arn
}

{% for res, entry in writer.entries.items() %}
  {%- if entry.path %}
    resource "aws_api_gateway_resource" "{{ app_name }}_{{ res }}" {
    rest_api_id = local.{{ app_name }}.api_id
    {% if entry.parent_is_root %}
      parent_id = local.{{ app_name }}.root_id
    {% else %}
      parent_id = aws_api_gateway_resource.{{ app_name }}_{{ entry.parent_uid }}.id
    {% endif %}
    path_part = "{{ entry.path }}"
    }
  {% endif -%}
  {%- if entry.methods %}
    {% for method in entry.methods %}
      resource "aws_api_gateway_method" "{{ app_name }}_{{ res }}_{{ method }}" {
      rest_api_id = local.{{ app_name }}.api_id
      {%- if entry.is_root %}
        resource_id = local.{{ app_name }}.root_id
      {% else %}
        resource_id = aws_api_gateway_resource.{{ app_name }}_{{ res }}.id
      {% endif -%}
      http_method = "{{ method }}"
      authorization = "CUSTOM"
      authorizer_id = aws_api_gateway_authorizer.{{ app_name }}.id
      }

      resource "aws_api_gateway_integration" "{{ app_name }}_{{ res }}_{{ method }}" {
      rest_api_id = local.{{ app_name }}.api_id
      {%- if entry.is_root %}
        resource_id = local.{{ app_name }}.root_id
      {% else %}
        resource_id = aws_api_gateway_resource.{{ app_name }}_{{ res }}.id
      {% endif -%}
      http_method = aws_api_gateway_method.{{ app_name }}_{{ res }}_{{ method }}.http_method
      integration_http_method = "POST"
      type = "AWS_PROXY"
      uri = aws_lambda_function.{{ app_name }}.invoke_arn
      }
    {% endfor %}

    {%- if entry.cors %}
      resource "aws_api_gateway_method" "{{ app_name }}_{{ res }}_OPTIONS" {
      rest_api_id = local.{{ app_name }}.api_id
      {%- if entry.is_root %}
        resource_id = local.{{ app_name }}.root_id
      {% else %}
        resource_id = aws_api_gateway_resource.{{ app_name }}_{{ res }}.id
      {% endif -%}
      http_method = "OPTIONS"
      authorization = "NONE"
      }

      resource "aws_api_gateway_integration" "{{ app_name }}_{{ res }}_OPTIONS" {
      rest_api_id = local.{{ app_name }}.api_id
      {%- if entry.is_root %}
        resource_id = local.{{ app_name }}.root_id
      {% else %}
        resource_id = aws_api_gateway_resource.{{ app_name }}_{{ res }}.id
      {% endif -%}
      http_method = aws_api_gateway_method.{{ app_name }}_{{ res }}_OPTIONS.http_method
      type = "MOCK"
      request_templates = {
      "application/json" = "{ \"statusCode\": 200 }"
      }
      }
      resource "aws_api_gateway_integration_response" "{{ app_name }}_{{ res }}_OPTIONS" {
      rest_api_id = local.{{ app_name }}.api_id
      {%- if entry.is_root %}
        resource_id = local.{{ app_name }}.root_id
      {% else %}
        resource_id = aws_api_gateway_resource.{{ app_name }}_{{ res }}.id
      {% endif -%}
      http_method = aws_api_gateway_method.{{ app_name }}_{{ res }}_OPTIONS.http_method
      response_parameters = {
      {%- for k,v in entry.cors.get_access_control_headers().items() %}
        "method.response.header.{{ k }}" = "'{{ v }}'",
      {% endfor -%}
      }
      status_code = 200
      depends_on = [
      aws_api_gateway_integration.{{ app_name }}_{{ res }}_OPTIONS,
      aws_api_gateway_method_response.{{ app_name }}_{{ res }}_OPTIONS,
      ]
      }
      resource "aws_api_gateway_method_response" "{{ app_name }}_{{ res }}_OPTIONS" {
      rest_api_id = local.{{ app_name }}.api_id
      {%- if entry.is_root %}
        resource_id = local.{{ app_name }}.root_id
      {% else %}
        resource_id = aws_api_gateway_resource.{{ app_name }}_{{ res }}.id
      {% endif -%}
      http_method = aws_api_gateway_method.{{ app_name }}_{{ res }}_OPTIONS.http_method
      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
      }

      depends_on = [
      aws_api_gateway_method.{{ app_name }}_{{ res }}_OPTIONS,
      ]
      }
    {% endif -%}
  {% endif -%}
{% endfor %}


resource "aws_api_gateway_deployment" "{{ app_name }}" {
depends_on = [
{%- for res, entry in writer.entries.items() %}{%- if entry.methods %}{% for method in entry.methods %}
  aws_api_gateway_integration.{{ app_name }}_{{ res }}_{{ method }},
{% endfor %}{% endif %}{% endfor -%}
]
rest_api_id = local.{{ app_name }}.api_id
stage_name = "dev"
stage_description = md5(file("{{ module_file }}.tf"))
}


#
# OUTPUT
#

output "{{ app_name }}" {
value = {
invoke-url = aws_api_gateway_deployment.{{ app_name }}.invoke_url
}
}