# Phf sales data process state machine.
#
# This module describes all required resources for phf sales data process
# state machine and also an event rule for put object to S3 API calls from CloudTrail.


# Policy for lambda invocation initiated by state machine.
data "aws_iam_policy_document" "assume_role_for_states_policy" {

  statement {
    actions = [
      "sts:AssumeRole"
    ]
    principals {
      type = "Service"
      identifiers = [
        "states.${var.region}.amazonaws.com"
      ]
    }
  }
}

data "aws_iam_policy_document" "invoke_lambda_policy" {

  statement {
    actions = [
      "lambda:InvokeFunction"
    ]
    resources = [
      "${var.phf_sales_data_verify_lambda_arn}",
      "${var.phf_sales_data_process_lambda_arn}",
      "${var.phf_send_notifications_lambda_arn}"
    ]
  }
}

resource "aws_iam_role_policy" "invoke_lambda_role_policy" {
  name = "${var.env}_invoke_phf_sales_data_verify_lambda_role_policy"
  role = "${aws_iam_role.invoke_publishing_lambdas_role_by_states_role.id}"
  policy = "${data.aws_iam_policy_document.invoke_lambda_policy.json}"
}

# States role for lambda invocation
resource "aws_iam_role" "invoke_publishing_lambdas_role_by_states_role" {
  name = "${var.env}_invoke_publishing_lambdas_role_by_states_role"
  assume_role_policy = "${data.aws_iam_policy_document.assume_role_for_states_policy.json}"
}

#  Policy for execution starting initiated by a CloudWatch rule.
data "aws_iam_policy_document" "start_execution_policy" {

  statement {
    actions = [
      "states:StartExecution"
    ]
    resources = [
      "${aws_sfn_state_machine.state_machine.id}"
    ]
  }
}

data "aws_iam_policy_document" "assume_role_for_events_policy" {

  statement {
    sid = "AllowCWEServiceToAssumeRole"
    actions = [
      "sts:AssumeRole"
    ]
    principals {
      type = "Service"
      identifiers = [
        "events.amazonaws.com"
      ]
    }
  }
}

resource "aws_iam_role_policy" "start_execution_role_policy" {
  name = "${var.env}_start_phf_sales_data_process_state_machine_execution_role_policy"
  role = "${aws_iam_role.phf_sales_data_process_state_machine_role.id}"
  policy = "${data.aws_iam_policy_document.start_execution_policy.json}"
}

# CloudWatch event rule role for execution start
resource "aws_iam_role" "phf_sales_data_process_state_machine_role" {
  name = "${var.env}_execute_phf_sales_data_process_state_machine_role"
  assume_role_policy = "${data.aws_iam_policy_document.assume_role_for_events_policy.json}"
}

resource "aws_cloudwatch_event_target" "state_machine_target" {
  rule = "${aws_cloudwatch_event_rule.put_asset_filtration_rule.name}"
  role_arn = "${aws_iam_role.phf_sales_data_process_state_machine_role.arn}"
  target_id = "${var.env}_put_asset_filtration_rule_target"
  arn = "${aws_sfn_state_machine.state_machine.id}"
}

# Event rule for new input assets filtration.
resource "aws_cloudwatch_event_rule" "put_asset_filtration_rule" {

  name = "${var.env}_phf_sales_data_process_state_machine_filtration_rule"
  description = "The CloudWatch event rule for put object events filtration."
  event_pattern = <<PATTERN
{
  "source": [
    "aws.s3"
  ],
  "detail-type": [
    "AWS API Call via CloudTrail"
  ],
  "detail": {
    "eventSource": [
      "s3.amazonaws.com"
    ],
    "eventName": [
      "PutObject",
      "CompleteMultipartUpload"
    ],
    "requestParameters": {
      "bucketName": [
        "${var.observed_bucket_name}"
      ]
    }
  }
}
PATTERN
}

resource "aws_sfn_state_machine" "state_machine" {
  name = "${var.phf_sales_data_process_state_machine_name}"
  role_arn = "${aws_iam_role.invoke_publishing_lambdas_role_by_states_role.arn}"
  definition = <<EOF
  {
    "StartAt": "PHF Sales Data Verify",
    "States": {
      "PHF Sales Data Verify": {
        "Type": "Task",
        "Resource": "${var.phf_sales_data_verify_lambda_arn}",
        "Next": "PHF Passed Verification Rules?",
        "Retry": [
          {
            "ErrorEquals": [
              "States.ALL"
            ],
            "IntervalSeconds": 1,
            "MaxAttempts": 1,
            "BackoffRate": 2
          }
        ]
      },
      "PHF Passed Verification Rules?": {
        "Type": "Choice",
        "Choices": [
          {
            "Not": {
              "Variable": "$.status",
              "NumericEquals": 200
            },
            "Next": "PHF Send Notifications"
          },
          {
            "Variable": "$.status",
            "NumericEquals": 200,
            "Next": "Is Count Reached"
          }
        ]
      },
      "Is Count Reached": {
          "Type": "Choice",
          "Choices": [
              {
                  "Variable": "$.status",
                  "NumericEquals": 200,
                  "Next": "PHF Sales Data Process"
              },
              {
                  "Variable": "$.status",
                  "NumericEquals": 201,
                  "Next": "PHF Send Notifications"
              }
          ],
          "Default": "PHF Send Notifications"
      },
      "PHF Sales Data Process": {
        "Type": "Task",
        "Resource": "${var.phf_sales_data_process_lambda_arn}",
        "Next": "Is Count Reached",
        "Retry": [
          {
            "ErrorEquals": [
              "States.ALL"
            ],
            "IntervalSeconds": 1,
            "MaxAttempts": 1,
            "BackoffRate": 2
          }
        ]
      },
      "PHF Send Notifications": {
        "Type": "Task",
        "Resource": "${var.phf_send_notifications_lambda_arn}",
        "End": true
      }
    }
  }
  EOF
}
