package mail

import (
	"fmt"
	"io"

	"gopkg.in/gomail.v2"
)

type DynamicMailSender struct {
	Username string
	Password string
	// SMTP host, smtp.gmail.com when empty
	Host string
}

func (d *DynamicMailSender) BuildMailSender(username string, password string) *gomail.Dialer {
	host := d.Host
	if host == "" {
		host = "smtp.gmail.com"
	}

	return gomail.NewDialer(
		host,
		587,
		username,
		password,
	)
}

func (d *DynamicMailSender) SendMail(username string, password string, to string, subject string, body string) error {

	dialer := d.BuildMailSender(username, password)

	message := gomail.NewMessage()
	message.SetHeader("From", username)
	message.SetHeader("to", to)
	message.SetHeader("Subject", subject)
	message.SetBody("text/plain", body)

	if err := dialer.DialAndSend(message); err != nil {
		return fmt.Errorf("failed to send mail: %w", err)
	}

	return nil
}

// Attachment is one file attached to the mail
type Attachment struct {
	FileName string
	Data     []byte
}

// SendMailWithAttachments sends the mail to "to", with cc and bcc copies and the files attached
func (d *DynamicMailSender) SendMailWithAttachments(username string, password string, to string, cc []string, bcc []string,
	subject string, body string, attachments []Attachment) error {

	dialer := d.BuildMailSender(username, password)

	message := gomail.NewMessage()
	message.SetHeader("From", username)
	message.SetHeader("To", to)
	if len(cc) > 0 {
		message.SetHeader("Cc", cc...)
	}
	if len(bcc) > 0 {
		message.SetHeader("Bcc", bcc...)
	}
	message.SetHeader("Subject", subject)
	message.SetBody("text/plain", body)

	for _, attachment := range attachments {
		data := attachment.Data
		message.Attach(attachment.FileName, gomail.SetCopyFunc(func(w io.Writer) error {
			_, err := w.Write(data)
			return err
		}))
	}

	if err := dialer.DialAndSend(message); err != nil {
		return fmt.Errorf("failed to send mail: %w", err)
	}

	return nil
}
