# frozen_string_literal: true

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

module Litany
  class Route53Zone < Resource
    include Stack
    include Taggable

    cfn_type 'AWS::Route53::HostedZone'

    output

    id_validator /[A-Z0-9]{12,}/

    flag :auto_dmarc, true
    flag :sends_email, false

    property :zone_name, nil, [nil, Symbol, String]
    property :comment, nil, [nil, String]

    resource_collection DNSRecord, :dns_record, required: false
    resource_collection DNSAlias, :dns_alias, required: false

    resource_reference Environment, :environment

    resource_references VPC, :vpc, required: false
    resource_references VPCReference, :vpc_reference, required: false

    tag_key :HostedZoneTags

    def finalize_resource
      return unless auto_dmarc?

      # Not updating to use the #txt helper yet because of the comments below.
      record = dns_record :"_dmarc.#{name}"
      record.record_name "_dmarc.#{zone_name || name}"
      record.type :txt
      record.target '"v=DMARC1; p=none; adkim=s; aspf=s; fo=1; ri=3600"' if sends_email?
      record.target '"v=DMARC1; p=reject; adkim=s; aspf=s; fo=1; ri=3600"' unless sends_email?
      record.zone self
    end

    # These helpers have two main problems right now.  Both because the resource name is not properly constructed.
    #   1) If you have two records with the same name but different types you'll have unpredictable results. (only one will 'win')
    #   2) If you have two records with the same name and type but on two different zones (split-view DNS for example) you'll have a parent_resource reassignment and blow up.
    #
    # I've delayed fixing both of these because migration is very painful, the easiest way would be to delete the stack and reupload it.  This has _huge_ impact in some scenarios and cannot be done.
    #   Coming up with a clean way forward is going to be difficult at best, if not neigh impossible.
    def mx(record_name, target, priority)
      record = dns_record(record_name.to_sym)
      record.type(:mx)
      record.zone(self)
      record.target("#{priority} #{target}")
      record
    end

    def txt(record_name, target)
      record = dns_record(record_name.to_sym)
      record.type(:txt)
      record.zone(self)
      record.target("\"#{target}\"")
      record
    end

    def alias(record_name, target, alias_name: nil)
      record = dns_alias(record_name.to_sym)
      record.alias_name(alias_name)
      record.zone(self)
      record.target(target)
      record
    end

    def properties
      props = {
        Name: zone_name || name
      }

      props[:HostedZoneConfig] = {Comment: comment} if set_comment?

      if set_vpcs? || set_vpc_references?
        vpc_refs = vpcs.collect do |vpc|
          {
            VPCId: ref(vpc),
            VPCRegion: active_environment.region # TODO: Update this for multi-region support, will function incorrectly once cross region stuff is in.
          }
        end

        vpc_refs += vpc_references.collect do |ref|
          {
            VPCId: ref.id,
            VPCRegion: ref.environment.region
          }
        end

        props[:VPCs] = vpc_refs.flatten
      end

      props
    end
  end
end
