package email

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"net/smtp"
	"os/exec"
)

const (
	from     = "root@tilde.town"
	SMTPHost = "smtp.zoho.com"
	SMTPPort = 465
)

func SendLocalEmail(username, subject, body string) error {
	cmd := exec.Command("/usr/sbin/sendmail", username)
	cmd.Stdin = bytes.NewBufferString(fmt.Sprintf("Subject: %s\n\n%s", subject, body))

	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to send local email: %w", err)
	}

	return nil
}

type ExternalMailer struct {
	Password string
}

func NewExternalMailer(pw string) *ExternalMailer {
	if pw == "" {
		panic("why?")
	}
	return &ExternalMailer{
		Password: pw,
	}
}

func (m *ExternalMailer) Send(address, subject, body string) error {
	headers := map[string]string{
		"From":    from,
		"To":      address,
		"Subject": subject,
	}

	message := ""
	for k, v := range headers {
		message += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	message += "\r\n" + body

	auth := smtp.PlainAuth("", from, m.Password, SMTPHost)

	server := fmt.Sprintf("%s:%d", SMTPHost, SMTPPort)

	tlsconf := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         server,
	}

	conn, err := tls.Dial("tcp", server, tlsconf)
	if err != nil {
		return err
	}

	c, err := smtp.NewClient(conn, SMTPHost)
	if err != nil {
		return err
	}

	if err = c.Auth(auth); err != nil {
		return fmt.Errorf("auth failed for smtp: %w", err)
	}

	if err = c.Mail(from); err != nil {
		return err
	}

	if err = c.Rcpt(address); err != nil {
		return err
	}

	w, err := c.Data()
	if err != nil {
		return err
	}

	_, err = w.Write([]byte(message))
	if err != nil {
		return err
	}

	w.Close()
	c.Quit()

	return nil
}
