package acmecert

import (
	"fmt"
	"os"

	"github.com/go-acme/lego/v4/challenge"
	"github.com/go-acme/lego/v4/providers/dns/cloudflare"
	"github.com/go-acme/lego/v4/providers/dns/digitalocean"
	"github.com/go-acme/lego/v4/providers/dns/gcloud"
	"github.com/go-acme/lego/v4/providers/dns/route53"
	"gopkg.in/ini.v1"
)

// buildDNSProvider constructs the lego DNS-01 provider selected by [LetsEncrypt]
// dns_provider. A plain switch is the right amount of structure for a fixed set of
// providers — no pluggable registry needed.
func buildDNSProvider(cfg *ini.File) (challenge.Provider, error) {
	sec := cfg.Section("LetsEncrypt")
	switch name := sec.Key("dns_provider").String(); name {
	case "cloudflare":
		c := cloudflare.NewDefaultConfig()
		c.AuthToken = sec.Key("cloudflare_api_token").String()
		return cloudflare.NewDNSProviderConfig(c)
	case "route53":
		c := route53.NewDefaultConfig()
		c.AccessKeyID = sec.Key("route53_access_key_id").String()
		c.SecretAccessKey = sec.Key("route53_secret_access_key").String()
		c.Region = sec.Key("route53_region").String()
		c.HostedZoneID = sec.Key("route53_hosted_zone_id").String()
		return route53.NewDNSProviderConfig(c)
	case "digitalocean":
		c := digitalocean.NewDefaultConfig()
		c.AuthToken = sec.Key("digitalocean_api_token").String()
		return digitalocean.NewDNSProviderConfig(c)
	case "gcloud":
		project := sec.Key("gcloud_project").String()
		if saPath := sec.Key("gcloud_service_account_json_path").String(); saPath != "" {
			keyBytes, err := os.ReadFile(saPath)
			if err != nil {
				return nil, fmt.Errorf("read gcloud service account file: %w", err)
			}
			return gcloud.NewDNSProviderServiceAccountKey(keyBytes)
		}
		return gcloud.NewDNSProviderCredentials(project)
	default:
		return nil, fmt.Errorf("unknown or unset Let's Encrypt DNS provider %q", name)
	}
}
