// Package smtp provides a config wrapper around net/smtp for sending email.
package smtp

import (
	"fmt"
	"net/mail"
	"net/smtp"
)

// SMTP holds configuration for sending emails via an SMTP server.
type SMTP struct {
	From     string `yaml:"from"`
	Host     string `yaml:"host"`
	Password string `yaml:"password"`
	Port     string `yaml:"port"`
	User     string `yaml:"user"`
}

// Address returns the host:port string.
func (s *SMTP) Address() string {
	return fmt.Sprintf("%s:%s", s.Host, s.Port)
}

// Auth creates a PlainAuth using the configured credentials.
func (s *SMTP) Auth() smtp.Auth {
	return smtp.PlainAuth("", s.User, s.Password, s.Host)
}

// Send emails the given recipients using net/smtp.
// Refer to smtp.SendMail for its parameters and limitations.
func (s *SMTP) Send(to []string, msg []byte) error {
	if err := smtp.SendMail(
		s.Address(),
		s.Auth(),
		s.From,
		to,
		msg,
	); err != nil {
		return fmt.Errorf("smtp send: %w", err)
	}

	return nil
}

// Validate checks that all required configuration fields are set.
func (s *SMTP) Validate() error {
	if s.From == "" {
		return fmt.Errorf("missing from")
	}
	if _, err := mail.ParseAddress(s.From); err != nil {
		return fmt.Errorf("invalid from: %w", err)
	}
	if s.Host == "" {
		return fmt.Errorf("missing host")
	}
	if s.Password == "" {
		return fmt.Errorf("missing password")
	}
	if s.Port == "" {
		return fmt.Errorf("missing port")
	}
	if s.User == "" {
		return fmt.Errorf("missing user")
	}
	return nil
}
