AWSTemplateFormatVersion: "2010-09-09"
Description: Updates subscriptions with outstanding holiday stops.

Parameters:

  Stage:
    Description: Stage name
    Type: String
    AllowedValues:
      - CODE
      - PROD
    Default: CODE

Conditions:
  IsProd: !Equals [!Ref "Stage", "PROD"]

Mappings:
  StageMap:
    CODE:
      FulfilmentDatesBucketUrn: "arn:aws:s3:::fulfilment-date-calculator-code/*"
      ScheduleName: holiday-stop-processor-schedule-code
    PROD:
      FulfilmentDatesBucketUrn: "arn:aws:s3:::fulfilment-date-calculator-prod/*"
      ScheduleName: holiday-stop-processor-schedule

Resources:

  HolidayStopProcessorRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: HolidayStopProcessorPolicy
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - lambda:InvokeFunction
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/holiday-stop-processor-${Stage}:log-stream:*
        - PolicyName: ReadZuoraCredentials
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action: s3:GetObject
                Resource: !Sub arn:aws:s3:::gu-reader-revenue-private/membership/support-service-lambdas/${Stage}/zuoraRest-${Stage}*.json
        - PolicyName: ReadSalesforceCredentials
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action: s3:GetObject
                Resource: !Sub arn:aws:s3:::gu-reader-revenue-private/membership/support-service-lambdas/${Stage}/sfAuth-${Stage}*.json
        - PolicyName: FulfilmentDatesCalculatorBucket
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action: s3:GetObject
                Resource:
                  - !FindInMap [StageMap, !Ref Stage, FulfilmentDatesBucketUrn]

  HolidayStopProcessor:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName:
        !Sub holiday-stop-processor-${Stage}
      Description: Updates subscriptions with outstanding holiday stops. Source - https://github.com/guardian/support-service-lambdas/tree/main/handlers/holiday-stop-processor
      Code:
        S3Bucket: support-service-lambdas-dist
        S3Key: !Sub membership/${Stage}/holiday-stop-processor/holiday-stop-processor.jar
      Handler: com.gu.holidaystopprocessor.Handler::handle
      Environment:
        Variables:
          Stage: !Ref Stage
      Role:
        !GetAtt HolidayStopProcessorRole.Arn
      MemorySize: 1024
      Runtime: java21
      Timeout: 900
      Architectures:
        - arm64
    DependsOn:
      - HolidayStopProcessorRole

  HolidayStopProcessorFailureAlarm:
    Type: AWS::CloudWatch::Alarm
    Condition: IsProd
    Properties:
      AlarmName: "URGENT 9-5 - PROD: Failed to process holiday stops"
      AlarmDescription: >
        IMPACT: If this goes unaddressed at least one subscription
        that was supposed to be suspended will be fulfilled.
        Until we document how to deal with likely problems please alert the Value team.
        For general advice, see
        https://docs.google.com/document/d/1_3El3cly9d7u_jPgTcRjLxmdG2e919zCLvmcFCLOYAk
      AlarmActions:
        - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD
      Metrics:
        - Id: errors
          Expression: "FILL(m1,0)"
          Label: ErrorCount
        - Id: m1
          ReturnData: false
          MetricStat:
            Metric:
              Namespace: AWS/Lambda
              MetricName: Errors
              Dimensions:
              - Name: FunctionName
                Value: !Ref HolidayStopProcessor
            Stat: Sum
            Period: 60
            Unit: Count
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Threshold: 1
      DatapointsToAlarm: 10
      EvaluationPeriods: 240
      TreatMissingData: notBreaching
    DependsOn:
      - HolidayStopProcessor

  HolidayStopProcessorScheduleRule:
    Type: AWS::Events::Rule
    Properties:
      Description: Trigger processing of holiday stops every 20 mins (to ensure successful processing of all batches within 24 hours)
      Name: !FindInMap [StageMap, !Ref Stage, ScheduleName]
      ScheduleExpression: "cron(0/20 * ? * * *)"
      State: ENABLED
      Targets:
        - Arn: !GetAtt HolidayStopProcessor.Arn
          Id: !Ref HolidayStopProcessor
          Input: "null"
    DependsOn:
      - HolidayStopProcessor

  HolidayStopProcessorLambdaInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      FunctionName: !Ref HolidayStopProcessor
      Principal: events.amazonaws.com
      SourceArn: !GetAtt HolidayStopProcessorScheduleRule.Arn
    DependsOn:
      - HolidayStopProcessor
      - HolidayStopProcessorScheduleRule

  # As processor runs every 20 mins anyway, there's no need to retry
  HolidayStopProcessorRetryConfig:
    Type: AWS::Lambda::EventInvokeConfig
    Properties:
      FunctionName: !Ref HolidayStopProcessor
      MaximumRetryAttempts: 0
      Qualifier: '$LATEST'
    DependsOn:
      - HolidayStopProcessor
