# frozen_string_literal: true

require 'litany/resource'

module Litany
  class VPCEndpoint < Resource
    cfn_type 'AWS::EC2::VPCEndpoint'
    parent_resource :vpc

    output(:DNSName) { select(1, split(':', select(0, ref(self, :DnsEntries)))) }
    output(:HostedZoneID) { select(0, split(':', select(0, ref(self, :DnsEntries)))) }

    property :type, :interface, [:interface, :gateway]
    property :service, nil, [:cloudformation, :cloudtrail, :codebuild, :codebuild_fips, :config, :dynamodb, :ec2, :ec2_messages, :elb, :events, :execute, :kinesis, :kms, :logs, :monitoring, :necco, :s3, :sagemaker, :sagemaker_api, :sagemaker_fips, :sagemaker_notebook, :secrets_manager, :service_catalog, :sns, :ssm, :ssm_messages, :sts, String]

    resource_references SecurityGroup, :security_group
    resource_references Subnet, :subnet, required: false

    def finalize_resource
      type(:gateway) if [:dynamodb, :s3].include?(service)

      return if set_security_groups?

      sg = vpc.security_group(:"#{vpc.name}_endpoint")
      sg.description 'allows open access to VPC endpoints from the VPC CIDR'
      sg.ingress port: 0..65535, source: vpc.cidr, protocol: :tcp

      security_group(sg)
    end

    def properties
      props = {
        VpcId: ref(vpc),
        ServiceName: full_service_name,
        VpcEndpointType: type.capitalize
      }

      if type == :interface
        props[:SecurityGroupIds] = ref(security_groups)
        props[:SubnetIds] = set_subnets? ? ref(subnets) : ref(vpc.subnets)
        props[:PrivateDnsEnabled] = service.is_a?(Symbol)
      elsif type == :gateway
        props[:RouteTableIds] = ref(vpc.subnets.collect(&:route_table))
      end

      props
    end

    def full_service_name
      @service_aliases ||= {
        codebuild_fips: :'codebuild-fips',
        ec2_messages: :ec2messages,
        elb: :elasticloadbalancing,
        execute: :'execute-api',
        kinesis: :'kinesis-streams',
        sagemaker: :'sagemaker.runtime',
        sagemaker_api: :'sagemaker.api',
        sagemaker_fips: :'sagemaker.runtime-fips',
        sagemaker_notebook: "aws.sagemaker.#{active_environment&.region}.notebook",
        secrets_manager: :secretsmanager,
        service_catalog: :servicecatalog,
        ssm_messages: :ssmmessages
      }

      service_id = @service_aliases.fetch(service, service)

      case service_id
        when Symbol
          "com.amazonaws.#{active_environment&.region}.#{service_id}"
        when /^vpce-.*$/
          "com.amazonaws.vpce.#{active_environment&.region}.#{service_id}"
        when String
          service_id
        else
          raise "Unexpected value for service_id calculated: #{service_id.inspect}"
      end
    end

    # Gateway interfaces do not have outputs our complex outputs are based from.
    def skip_output?(_attribute)
      type == :gateway
    end
  end
end
