# frozen_string_literal: true

require 'litany/mixins'
require 'litany/resource'

module Litany
  class RedshiftCluster < Resource
    include Taggable

    cfn_type 'AWS::Redshift::Cluster'

    child_resource SecretsManagerSecretAttachment, :secret_attachment

    flag :automatic_major_version_upgrades, false, inherited: true
    flag :encrypt, true, inherited: true
    flag :publicly_accessible, false, inherited: true

    property :cluster_name, nil, [nil, /^[a-z](?:[a-z0-9]|-(?!-)){0,61}(?:[a-z0-9]$|(?<!-)$)/], inherited: true
    property :cluster_size, 2, 1..100, inherited: true
    property :db_name, 'dev', /^[a-z]{1,64}$/, inherited: true
    property :instance_type, 'dc2.large', ['ds2.xlarge', 'ds2.8xlarge', 'dc1.large', 'dc1.8xlarge', 'dc2.large', 'dc2.8xlarge', 'ra3.4xlarge', 'ra3.16xlarge'], inherited: true
    property :maintenance_window, nil, [nil, /(Mon|Tue|Wed|Thu|Fri|Sat|Sun):[0-9]{2}:[0-9]{2}-(Mon|Tue|Wed|Thu|Fri|Sat|Sun):[0-9]{2}:[0-9]{2}/], inherited: true
    property :port, 5439, 1150..65_535, inherited: true
    property :snapshot_retention, 7, 1..35, inherited: true
    property :username, 'root', /^[a-zA-Z][a-zA-Z0-9]{1,127}$/, inherited: true

    resource_reference RedshiftParameterGroup, :parameter_group, inherited: true
    resource_reference RedshiftSubnetGroup, :subnet_group, inherited: true
    resource_references IAMRole, :role, required: false, inherited: true
    resource_references SecurityGroup, :security_group, required: false, inherited: true

    def depends_on
      roles.select { |role| role.stack == stack }.collect(&:resource_name)
    end

    def finalize_resource
      template = { username: username }

      random_secret = secret_attachment.random_secret

      random_secret.description("Secret for #{resource_name}")
      random_secret.excluded_characters("\"'@/\\")
      random_secret.generate_key('password')
      random_secret.template(template.to_json)
    end

    def properties
      # Skipping: AvailabilityZone, ElasticIp, HsmClientCertificateIdentifier, HsmConfigurationIdentifier, KmsKeyId, OwnerAccount, SnapshotClusterIdentifier, SnapshotIdentifier
      #   ClusterSecurityGroups, LoggingProperties

      properties = {
        AllowVersionUpgrade: automatic_major_version_upgrades?,
        AutomatedSnapshotRetentionPeriod: snapshot_retention,
        ClusterIdentifier: cluster_name || name,
        ClusterParameterGroupName: ref(parameter_group),
        ClusterSubnetGroupName: ref(subnet_group),
        ClusterType: cluster_size == 1 ? 'single-node' : 'multi-node',
        ClusterVersion: '1.0', # not making a property out of this one given it has only one possible value
        DBName: db_name,
        Encrypted: encrypt?,
        MasterUsername: secret_attachment.resolve('username'),
        MasterUserPassword: secret_attachment.resolve('password'),
        NodeType: instance_type,
        Port: port,
        PubliclyAccessible: publicly_accessible?,
      }

      properties[:IamRoles] = ref(roles, :Arn) if set_roles?
      properties[:NumberOfNodes] = cluster_size if cluster_size > 1
      properties[:PreferredMaintenanceWindow] = maintenance_window if set_maintenance_window?
      properties[:VpcSecurityGroupIds] = ref(security_groups) if set_security_groups?

      properties
    end
  end
end
