package notify

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/smtp"
	"strings"
	"time"

	"github.com/mrhid6/vantage/server/internal/models"
)

const smtpTimeout = 15 * time.Second

func dispatchSMTP(ch models.NotificationChannel, ev Event) error {
	host := ch.Config["host"]
	port := ch.Config["port"]
	from := ch.Config["from"]
	to := ch.Config["to"]
	if host == "" || port == "" || from == "" || to == "" {
		return fmt.Errorf("smtp: missing host/port/from/to")
	}

	addr := net.JoinHostPort(host, port)
	conn, err := net.DialTimeout("tcp", addr, smtpTimeout)
	if err != nil {
		return fmt.Errorf("smtp: dial %s: %w", addr, err)
	}
	_ = conn.SetDeadline(time.Now().Add(smtpTimeout))

	if port == "465" {
		conn = tls.Client(conn, &tls.Config{ServerName: host})
	}

	c, err := smtp.NewClient(conn, host)
	if err != nil {
		conn.Close()
		return fmt.Errorf("smtp: client: %w", err)
	}
	defer c.Close()

	if port != "465" {
		if ok, _ := c.Extension("STARTTLS"); ok {
			if err := c.StartTLS(&tls.Config{ServerName: host}); err != nil {
				return fmt.Errorf("smtp: starttls: %w", err)
			}
		}
	}

	if user := ch.Config["username"]; user != "" {
		if err := c.Auth(smtp.PlainAuth("", user, ch.Config["password"], host)); err != nil {
			return fmt.Errorf("smtp: auth: %w", err)
		}
	}

	recipients := strings.Split(to, ",")
	for i := range recipients {
		recipients[i] = strings.TrimSpace(recipients[i])
	}

	if err := c.Mail(from); err != nil {
		return fmt.Errorf("smtp: mail from: %w", err)
	}
	for _, rcpt := range recipients {
		if rcpt == "" {
			continue
		}
		if err := c.Rcpt(rcpt); err != nil {
			return fmt.Errorf("smtp: rcpt %s: %w", rcpt, err)
		}
	}

	msg, err := buildMIME(from, to, ev.title(), textEmail(ev), htmlEmail(ev))
	if err != nil {
		return fmt.Errorf("smtp: build message: %w", err)
	}

	w, err := c.Data()
	if err != nil {
		return fmt.Errorf("smtp: data: %w", err)
	}
	if _, err := w.Write(msg); err != nil {
		return fmt.Errorf("smtp: write: %w", err)
	}
	if err := w.Close(); err != nil {
		return fmt.Errorf("smtp: close data: %w", err)
	}
	return c.Quit()
}
