AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Fan-out EMEA tenants monitor dispatcher and worker tasks.

Parameters:
  DevopsDBHost:
    Type: String
    Default: placeholder
  DevopsDBPort:
    Type: String
    Default: "3306"
  DevopsDBUser:
    Type: String
    Default: placeholder
  DevopsDBPassword:
    Type: String
    NoEcho: true
    Default: placeholder
  DevopsDBName:
    Type: String
    Default: placeholder
  TargetDBHost:
    Type: String
    Default: placeholder
  TargetDatabaseURL:
    Type: String
    NoEcho: true
    Default: ""
  TargetDBPort:
    Type: String
    Default: "3306"
  TargetDBUser:
    Type: String
    Default: placeholder
  TargetDBPassword:
    Type: String
    NoEcho: true
    Default: placeholder
  TargetDBName:
    Type: String
    Default: placeholder
  DevopsAPIToken:
    Type: String
    NoEcho: true
    Default: placeholder
  ClinicAPIKey:
    Type: String
    NoEcho: true
    Default: placeholder
  OpenAIAPIKey:
    Type: String
    NoEcho: true
    Default: placeholder
  OperatorEmail:
    Type: String
    Default: ""
  TenantSelectSQL:
    Type: String
    Default: ""
  NewSignupSelectSQL:
    Type: String
    Default: ""
  ScoringQueueName:
    Type: String
    Default: EMEA-Tenants-Scoring-Queue
  DevopsBaseURL:
    Type: String
    Default: https://prod.devops.pingcap.com
  ClinicBaseURL:
    Type: String
    Default: https://clinic.pingcap.com
  OpenAIWebSearchModel:
    Type: String
    Default: gpt-4.1-mini
  DomainIntelligenceTTLDays:
    Type: String
    Default: "30"
  LLMTimeoutSeconds:
    Type: String
    Default: "60"
  BillingRequestIntervalSeconds:
    Type: String
    Default: "4"
  BillingRetryCount:
    Type: String
    Default: "3"
  MonitorWorkerBatchSize:
    Type: Number
    Default: 1
    MinValue: 1
    MaxValue: 10
  MonitorWorkerMaximumConcurrency:
    Type: Number
    Default: 2
    MinValue: 2
    MaxValue: 100

Conditions:
  HasTenantSelectSQL: !Not [!Equals [!Ref TenantSelectSQL, ""]]
  HasNewSignupSelectSQL: !Not [!Equals [!Ref NewSignupSelectSQL, ""]]

Globals:
  Function:
    Runtime: python3.12
    Architectures:
      - x86_64
    Timeout: 900
    MemorySize: 512
    Tracing: Active
    Environment:
      Variables:
        DEVOPS_DB_HOST: !Ref DevopsDBHost
        DEVOPS_DB_PORT: !Ref DevopsDBPort
        DEVOPS_DB_USER: !Ref DevopsDBUser
        DEVOPS_DB_PASSWORD: !Ref DevopsDBPassword
        DEVOPS_DB_NAME: !Ref DevopsDBName
        TARGET_DB_HOST: !Ref TargetDBHost
        TARGET_DATABASE_URL: !Ref TargetDatabaseURL
        TARGET_DB_PORT: !Ref TargetDBPort
        TARGET_DB_USER: !Ref TargetDBUser
        TARGET_DB_PASSWORD: !Ref TargetDBPassword
        TARGET_DB_NAME: !Ref TargetDBName
        DEVOPS_API_TOKEN: !Ref DevopsAPIToken
        CLINIC_API_KEY: !Ref ClinicAPIKey
        OPENAI_API_KEY: !Ref OpenAIAPIKey
        OPERATOR_EMAIL: !Ref OperatorEmail
        TENANT_SELECT_SQL: !If [HasTenantSelectSQL, !Ref TenantSelectSQL, !Ref AWS::NoValue]
        NEW_SIGNUP_SELECT_SQL: !If [HasNewSignupSelectSQL, !Ref NewSignupSelectSQL, !Ref AWS::NoValue]
        DEVOPS_BASE_URL: !Ref DevopsBaseURL
        CLINIC_BASE_URL: !Ref ClinicBaseURL
        OPENAI_WEB_SEARCH_MODEL: !Ref OpenAIWebSearchModel
        DOMAIN_INTELLIGENCE_TTL_DAYS: !Ref DomainIntelligenceTTLDays
        LLM_TIMEOUT_SECONDS: !Ref LLMTimeoutSeconds
        BILLING_REQUEST_INTERVAL_SECONDS: !Ref BillingRequestIntervalSeconds
        BILLING_RETRY_COUNT: !Ref BillingRetryCount

Resources:
  EMEATenantsMonitorFanoutDeadLetterQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: EMEA-Tenants-Monitor-Fanout-DLQ
      MessageRetentionPeriod: 1209600

  EMEATenantsMonitorFanoutQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: EMEA-Tenants-Monitor-Fanout-Queue
      VisibilityTimeout: 960
      MessageRetentionPeriod: 1209600
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt EMEATenantsMonitorFanoutDeadLetterQueue.Arn
        maxReceiveCount: 3

  EMEATenantsMonitorFanoutDispatcherTask:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: EMEA-Tenants-Monitor-Fanout-Dispatcher-Task
      CodeUri: fanout/
      Handler: dispatcher_function.lambda_handler
      Description: Dispatch EMEA tenant monitor work items to the fan-out SQS queue.
      Environment:
        Variables:
          MONITOR_QUEUE_URL: !Ref EMEATenantsMonitorFanoutQueue
      Policies:
        - AWSLambdaBasicExecutionRole
        - SQSSendMessagePolicy:
            QueueName: !GetAtt EMEATenantsMonitorFanoutQueue.QueueName
      Events:
        DailySchedule:
          Type: Schedule
          Properties:
            Name: EMEA-Tenants-Monitor-Fanout-Dispatcher-Task-Daily
            Description: Dispatch EMEA tenant monitor messages daily at 15:30 Asia/Shanghai.
            Schedule: cron(30 7 * * ? *)
            Enabled: true

  EMEATenantsMonitorFanoutWorkerTask:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: EMEA-Tenants-Monitor-Fanout-Worker-Task
      CodeUri: fanout/
      Handler: worker_function.lambda_handler
      Description: Process EMEA tenant monitor fan-out SQS messages.
      ReservedConcurrentExecutions: !Ref MonitorWorkerMaximumConcurrency
      Environment:
        Variables:
          SCORING_QUEUE_URL: !Sub https://sqs.${AWS::Region}.${AWS::URLSuffix}/${AWS::AccountId}/${ScoringQueueName}
      Policies:
        - AWSLambdaBasicExecutionRole
        - SQSPollerPolicy:
            QueueName: !GetAtt EMEATenantsMonitorFanoutQueue.QueueName
        - Statement:
            - Effect: Allow
              Action:
                - sqs:SendMessage
              Resource: !Sub arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:${ScoringQueueName}
      Events:
        MonitorQueue:
          Type: SQS
          Properties:
            Queue: !GetAtt EMEATenantsMonitorFanoutQueue.Arn
            BatchSize: !Ref MonitorWorkerBatchSize
            FunctionResponseTypes:
              - ReportBatchItemFailures
            ScalingConfig:
              MaximumConcurrency: !Ref MonitorWorkerMaximumConcurrency

Outputs:
  MonitorFanoutQueueUrl:
    Description: SQS queue URL for fan-out monitor work.
    Value: !Ref EMEATenantsMonitorFanoutQueue
  MonitorFanoutQueueArn:
    Description: SQS queue ARN for fan-out monitor work.
    Value: !GetAtt EMEATenantsMonitorFanoutQueue.Arn
  DispatcherFunctionName:
    Description: Fan-out dispatcher Lambda function name.
    Value: !Ref EMEATenantsMonitorFanoutDispatcherTask
  WorkerFunctionName:
    Description: Fan-out worker Lambda function name.
    Value: !Ref EMEATenantsMonitorFanoutWorkerTask
