package mail

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	netmail "net/mail"
	"strings"

	"golang.org/x/net/idna"
)

const senderSubjectDomain = "agentteam/email/external-subject/v1\x00"

func CanonicalSenderAddress(value string) (string, error) {
	trimmed := strings.TrimSpace(value)
	if trimmed == "" || len(trimmed) > 320 {
		return "", fmt.Errorf("senderAddress is invalid")
	}
	parsed, err := netmail.ParseAddress(trimmed)
	if err != nil || parsed.Address != trimmed {
		return "", fmt.Errorf("senderAddress must be one bare email address")
	}
	at := strings.LastIndexByte(parsed.Address, '@')
	if at <= 0 || at == len(parsed.Address)-1 {
		return "", fmt.Errorf("senderAddress is invalid")
	}
	local := parsed.Address[:at]
	domain, err := idna.Lookup.ToASCII(parsed.Address[at+1:])
	if err != nil || domain == "" {
		return "", fmt.Errorf("senderAddress domain is invalid")
	}
	return local + "@" + strings.ToLower(domain), nil
}

func ExternalSubjectRef(
	credentialKey []byte,
	senderAddress string,
) (string, error) {
	if len(credentialKey) < 32 {
		return "", fmt.Errorf("Email credential key is unavailable")
	}
	canonical, err := CanonicalSenderAddress(senderAddress)
	if err != nil {
		return "", err
	}
	mac := hmac.New(sha256.New, credentialKey)
	_, _ = mac.Write([]byte(senderSubjectDomain))
	_, _ = mac.Write([]byte(canonical))
	return "email:h1:" + hex.EncodeToString(mac.Sum(nil)), nil
}
