module Cody::AwsServices
  module Helpers
    def find_stack(stack_name)
      return if ENV['TEST']
      resp = cfn.describe_stacks(stack_name: stack_name)
      resp.stacks.first
    rescue Aws::CloudFormation::Errors::ValidationError => e
      # example: Stack with id demo-web does not exist
      if e.message =~ /Stack with/ && e.message =~ /does not exist/
        nil
      else
        raise
      end
    end

    def stack_exists?(stack_name)
      return false if ENV['TEST']

      exist = nil
      begin
        # When the stack does not exist an exception is raised. Example:
        # Aws::CloudFormation::Errors::ValidationError: Stack with id blah does not exist
        cfn.describe_stacks(stack_name: stack_name)
        exist = true
      rescue Aws::CloudFormation::Errors::ValidationError => e
        if e.message =~ /does not exist/
          exist = false
        elsif e.message.include?("'stackName' failed to satisfy constraint")
          # Example of e.message when describe_stack with invalid stack name
          # "1 validation error detected: Value 'instance_and_route53' at 'stackName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*|arn:[-a-zA-Z0-9:/._+]*"
          puts "Invalid stack name: #{stack_name}"
          puts "Full error message: #{e.message}"
          exit 1
        else
          raise # re-raise exception  because unsure what other errors can happen
        end
      end
      exist
    end

    def project_name_convention(name_base)
      items = [@project_name, @options[:type], Cody.extra]
      items.insert(2, Cody.env) if Cody.settings.dig(:stack_naming, :append_env)
      items.reject(&:blank?).compact.join("-")
    end

    def inferred_project_name
      # Essentially the project's parent folder
      File.basename(Dir.pwd).gsub('_','-').gsub(/\.+/,'-').gsub(/[^0-9a-zA-Z,-]/, '')
    end

    # Examples:
    #
    #     myapp-ci-deploy # with Settings stack_naming append_env set to false.
    #     myapp-ci-deploy-development
    #     myapp-ci-deploy-development-2
    #
    def inferred_stack_name(project_name)
      append_stack_name = Cody.settings.dig(:stack_naming, :append_stack_name) || "cody"
      items = [project_name, @options[:type], Cody.extra, append_stack_name]
      items.insert(3, Cody.env) if Cody.settings.dig(:stack_naming, :append_env)
      items.reject(&:blank?).reject {|i| i == false}.compact.join("-")
    end

    def are_you_sure?(stack_name, action)
      if @options[:yes]
        sure = 'y'
      else
        message = case action
        when :update
          "Are you sure you want to want to update the #{stack_name.color(:green)} stack with the changes? (y/N)"
        when :delete
          "Are you sure you want to want to delete the #{stack_name.color(:green)} stack? (y/N)"
        end
        puts message
        sure = $stdin.gets
      end

      unless sure =~ /^y/
        puts "Whew! Exiting without running #{action}."
        exit 0
      end
    end

    def normalize_stack_name(name)
      name.gsub('_','-') # cloudformation stack names dont allow _
    end
  end
end