# Terraform configuration to create a simple API Gateway REST API with a Lambda proxy integration.

provider "aws" {
  region = "us-east-1"
}

# --- IAM Role and Policy for Lambda ---
data "aws_iam_policy_document" "lambda_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "api_gateway_lambda_role" {
  name               = "ApiGatewayLambdaRole-tf"
  assume_role_policy = data.aws_iam_policy_document.lambda_assume_role.json
}

# Attach the basic Lambda execution policy
resource "aws_iam_role_policy_attachment" "lambda_basic_execution" {
  role       = aws_iam_role.api_gateway_lambda_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}

# --- Lambda Function ---
data "archive_file" "lambda_zip" {
  type        = "zip"
  source_file = "${path.module}/hello_world_lambda.py"
  output_path = "${path.module}/function.zip"
}

resource "aws_lambda_function" "hello_world" {
  function_name    = "ApiGatewayHelloWorld-tf"
  handler          = "hello_world_lambda.lambda_handler"
  runtime          = "python3.9"
  role             = aws_iam_role.api_gateway_lambda_role.arn
  filename         = data.archive_file.lambda_zip.output_path
  source_code_hash = data.archive_file.lambda_zip.output_base64sha256
  
  depends_on = [aws_iam_role_policy_attachment.lambda_basic_execution]
}

# --- API Gateway ---
resource "aws_api_gateway_rest_api" "my_api" {
  name        = "MyLambdaProxyAPI-tf"
  description = "A simple Lambda proxy API managed by Terraform"
}

resource "aws_api_gateway_resource" "hello" {
  rest_api_id = aws_api_gateway_rest_api.my_api.id
  parent_id   = aws_api_gateway_rest_api.my_api.root_resource_id
  path_part   = "hello"
}

resource "aws_api_gateway_method" "get" {
  rest_api_id   = aws_api_gateway_rest_api.my_api.id
  resource_id   = aws_api_gateway_resource.hello.id
  http_method   = "GET"
  authorization = "NONE"
}

# --- API Gateway Integration ---
resource "aws_api_gateway_integration" "lambda_proxy" {
  rest_api_id             = aws_api_gateway_rest_api.my_api.id
  resource_id             = aws_api_gateway_resource.hello.id
  http_method             = aws_api_gateway_method.get.http_method
  integration_http_method = "POST" # For Lambda proxy, this must be POST
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.hello_world.invoke_arn
}

# --- API Gateway Deployment ---
resource "aws_api_gateway_deployment" "my_api_deployment" {
  rest_api_id = aws_api_gateway_rest_api.my_api.id

  # A new deployment is required for any change to the API Gateway configuration
  triggers = {
    redeployment = sha1(jsonencode([
      aws_api_gateway_resource.hello.id,
      aws_api_gateway_method.get.id,
      aws_api_gateway_integration.lambda_proxy.id,
    ]))
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_api_gateway_stage" "dev" {
  deployment_id = aws_api_gateway_deployment.my_api_deployment.id
  rest_api_id   = aws_api_gateway_rest_api.my_api.id
  stage_name    = "dev"
}

# --- Lambda Permission ---
# Grant API Gateway permission to invoke the Lambda function
resource "aws_lambda_permission" "api_gateway_invoke" {
  statement_id  = "AllowAPIGatewayInvoke"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.hello_world.function_name
  principal     = "apigateway.amazonaws.com"

  # The "/*/*" allows invocation from any method on any resource path
  # within the specified stage of the API.
  source_arn = "${aws_api_gateway_rest_api.my_api.execution_arn}/*/*"
}

# --- Outputs ---
output "api_endpoint_url" {
  value       = "${aws_api_gateway_stage.dev.invoke_url}/hello"
  description = "The invocation URL for the API Gateway stage."
}
