require "yaml"
require "json"
require "./kubernetes_client"
require "../../types"

module ContainerMom
  class DnsManager
    class Error < Exception; end

    def self.instance
      @@instance ||= new
    end

    @client : K8sClientWrapper

    def initialize
      @client = ContainerMom::K8S_CLIENT
      load_config
    end

    def setup_domain(name : String, namespace : String, spec : ContainerMom::Types::ContainerDeploymentSpec)
      # Get domain configuration
      domain = if domain_config = spec.domain
        if custom = domain_config["custom"]?
          custom
        else
          "#{name}.container.mom"
        end
      else
        "#{name}.container.mom"
      end

      # Create Certificate resource for each region
      spec.regions.each do |region_name|
        create_certificate(name, namespace, region_name, domain)
      end

      # Update DNS records
      update_dns_records(name, namespace, domain, spec)
    end

    private def create_certificate(name, namespace, region, domain)
      manifest = JSON.parse({
        "metadata": {
          "name": "#{name}-#{region}-tls",
          "namespace": namespace,
          "labels": {
            "app.kubernetes.io/managed-by": "container-mom-operator",
            "app.kubernetes.io/region": region
          }
        },
        "spec": {
          "secretName": "#{name}-#{region}-tls",
          "dnsNames": [domain],
          "issuerRef": {
            "name": @cert_issuer_name,
            "kind": @cert_issuer_kind
          }
        }
      }.to_json).as_h
      @client.apply_certificate(manifest)
    end

    private def update_dns_records(name, namespace, domain, spec)
      # For now, just log the DNS updates
      # In a real implementation, this would update DNS records via API
      puts "Would update DNS records for #{domain}:"
      spec.regions.each do |region_name|
        puts "  #{region_name}: #{name}-#{region_name}.#{@base_domain}"
      end
    end

    private def load_config
      begin
        response = @client.get("/api/v1/namespaces/system/configmaps/manager-config") do |response|
          case response.status
          when .ok?
            JSON.parse(response.body_io)
          else
            raise Error.new("Failed to get manager config: #{response.status}")
          end
        end

        if data = response["data"]?.try(&.as_h)
          if config_yaml = data["controller_manager_config.yaml"]?.try(&.as_s)
            config_data = YAML.parse(config_yaml)
            
            @cert_issuer_name = config_data.dig?("cert_issuer", "name").try(&.as_s) || "letsencrypt-prod"
            @cert_issuer_kind = config_data.dig?("cert_issuer", "kind").try(&.as_s) || "ClusterIssuer"
            @base_domain = config_data.dig?("dns", "base_domain").try(&.as_s) || "container.mom"
          end
        end
      rescue ex
        # Use defaults if config doesn't exist
        @cert_issuer_name = "letsencrypt-prod"
        @cert_issuer_kind = "ClusterIssuer"
        @base_domain = "container.mom"
      end
    end
  end
end
