package dns

import (
	"context"
	"fmt"
	"net"
	"strings"
	"time"

	"go.uber.org/zap"
)

// Verifier handles DNS TXT record verification
type Verifier struct {
	resolver *net.Resolver
	logger   *zap.Logger
}

// ProvideVerifier creates a new DNS Verifier
func ProvideVerifier(logger *zap.Logger) *Verifier {
	return &Verifier{
		resolver: &net.Resolver{
			PreferGo: true, // Use Go's DNS resolver
		},
		logger: logger.Named("dns-verifier"),
	}
}

// VerifyDomainOwnership checks if a domain has the correct TXT record
// Expected format: "maplepress-verify=TOKEN"
func (v *Verifier) VerifyDomainOwnership(ctx context.Context, domain string, expectedToken string) (bool, error) {
	v.logger.Info("verifying domain ownership via DNS",
		zap.String("domain", domain))

	// Create context with timeout (10 seconds for DNS lookup)
	lookupCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
	defer cancel()

	// Look up TXT records for the domain
	txtRecords, err := v.resolver.LookupTXT(lookupCtx, domain)
	if err != nil {
		// Check if it's a timeout
		if lookupCtx.Err() == context.DeadlineExceeded {
			v.logger.Warn("DNS lookup timed out",
				zap.String("domain", domain))
			return false, fmt.Errorf("DNS lookup timed out after 10 seconds")
		}

		// Check if domain doesn't exist
		if dnsErr, ok := err.(*net.DNSError); ok {
			if dnsErr.IsNotFound {
				v.logger.Warn("domain not found",
					zap.String("domain", domain))
				return false, fmt.Errorf("domain not found: %s", domain)
			}
		}

		v.logger.Error("failed to lookup TXT records",
			zap.String("domain", domain),
			zap.Error(err))
		return false, fmt.Errorf("failed to lookup DNS TXT records: %w", err)
	}

	// Expected verification record format
	expectedRecord := fmt.Sprintf("maplepress-verify=%s", expectedToken)

	// Check each TXT record
	for _, record := range txtRecords {
		v.logger.Debug("checking TXT record",
			zap.String("domain", domain),
			zap.String("record", record))

		// Normalize whitespace and compare
		normalizedRecord := strings.TrimSpace(record)
		if normalizedRecord == expectedRecord {
			v.logger.Info("domain ownership verified",
				zap.String("domain", domain))
			return true, nil
		}
	}

	v.logger.Warn("verification record not found",
		zap.String("domain", domain),
		zap.String("expected", expectedRecord),
		zap.Int("records_checked", len(txtRecords)))

	return false, nil
}

// GetVerificationRecord returns the TXT record format for a given token
func GetVerificationRecord(token string) string {
	return fmt.Sprintf("maplepress-verify=%s", token)
}

// GetVerificationInstructions returns user-friendly instructions
func GetVerificationInstructions(domain string, token string) string {
	record := GetVerificationRecord(token)
	return fmt.Sprintf(`To verify ownership of %s, add this DNS TXT record:

Host/Name: %s
Type: TXT
Value: %s

Instructions:
1. Log in to your domain registrar (GoDaddy, Namecheap, Cloudflare, etc.)
2. Find DNS settings or DNS management
3. Add a new TXT record with the values above
4. Wait 5-10 minutes for DNS propagation
5. Click "Verify Domain" in MaplePress

Note: DNS changes can take up to 48 hours to propagate globally, but usually complete within 10 minutes.`,
		domain, domain, record)
}
