package email

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

	"sproutgate-backend/internal/storage"
)

func SendVerificationEmail(cfg storage.EmailConfig, to string, code string, expiresIn time.Duration) error {
	if strings.TrimSpace(to) == "" {
		return fmt.Errorf("email is required")
	}
	fromName := strings.TrimSpace(cfg.FromName)
	if fromName == "" {
		fromName = "萌芽账户认证中心"
	}
	fromAddress := strings.TrimSpace(cfg.FromAddress)
	if fromAddress == "" {
		return fmt.Errorf("from address is required")
	}
	username := strings.TrimSpace(cfg.Username)
	if username == "" {
		username = fromAddress
	}
	subject := "萌芽账户认证中心 - 邮箱验证"
	encodedName := mime.QEncoding.Encode("UTF-8", fromName)
	fromHeader := fmt.Sprintf("%s <%s>", encodedName, fromAddress)

	body := fmt.Sprintf("您的验证码是：%s\n有效期：%d 分钟\n\n如非本人操作，请忽略此邮件。",
		code, int(expiresIn.Minutes()))

	var msg bytes.Buffer
	msg.WriteString("From: " + fromHeader + "\r\n")
	msg.WriteString("To: " + to + "\r\n")
	msg.WriteString("Subject: " + mime.QEncoding.Encode("UTF-8", subject) + "\r\n")
	msg.WriteString("MIME-Version: 1.0\r\n")
	msg.WriteString("Content-Type: text/plain; charset=\"UTF-8\"\r\n")
	msg.WriteString("Content-Transfer-Encoding: 8bit\r\n")
	msg.WriteString("\r\n")
	msg.WriteString(body)

	addr := fmt.Sprintf("%s:%d", cfg.SMTPHost, cfg.SMTPPort)
	auth := smtp.PlainAuth("", username, cfg.Password, cfg.SMTPHost)
	encryption := strings.ToUpper(strings.TrimSpace(cfg.Encryption))

	if cfg.SMTPPort == 465 || encryption == "SSL" {
		tlsConfig := &tls.Config{
			ServerName:         cfg.SMTPHost,
			MinVersion:         tls.VersionTLS12,
			InsecureSkipVerify: false,
		}
		conn, err := tls.Dial("tcp", addr, tlsConfig)
		if err != nil {
			return err
		}
		client, err := smtp.NewClient(conn, cfg.SMTPHost)
		if err != nil {
			return err
		}
		defer client.Close()
		if err := client.Auth(auth); err != nil {
			return err
		}
		if err := client.Mail(fromAddress); err != nil {
			return err
		}
		if err := client.Rcpt(to); err != nil {
			return err
		}
		writer, err := client.Data()
		if err != nil {
			return err
		}
		if _, err := writer.Write(msg.Bytes()); err != nil {
			return err
		}
		if err := writer.Close(); err != nil {
			return err
		}
		return client.Quit()
	}

	return smtp.SendMail(addr, auth, fromAddress, []string{to}, msg.Bytes())
}

func SendResetPasswordEmail(cfg storage.EmailConfig, to string, code string, expiresIn time.Duration) error {
	if strings.TrimSpace(to) == "" {
		return fmt.Errorf("email is required")
	}
	fromName := strings.TrimSpace(cfg.FromName)
	if fromName == "" {
		fromName = "萌芽账户认证中心"
	}
	fromAddress := strings.TrimSpace(cfg.FromAddress)
	if fromAddress == "" {
		return fmt.Errorf("from address is required")
	}
	username := strings.TrimSpace(cfg.Username)
	if username == "" {
		username = fromAddress
	}
	subject := "萌芽账户认证中心 - 重置密码"
	encodedName := mime.QEncoding.Encode("UTF-8", fromName)
	fromHeader := fmt.Sprintf("%s <%s>", encodedName, fromAddress)

	body := fmt.Sprintf("您的重置密码验证码是：%s\n有效期：%d 分钟\n\n如非本人操作，请忽略此邮件。",
		code, int(expiresIn.Minutes()))

	var msg bytes.Buffer
	msg.WriteString("From: " + fromHeader + "\r\n")
	msg.WriteString("To: " + to + "\r\n")
	msg.WriteString("Subject: " + mime.QEncoding.Encode("UTF-8", subject) + "\r\n")
	msg.WriteString("MIME-Version: 1.0\r\n")
	msg.WriteString("Content-Type: text/plain; charset=\"UTF-8\"\r\n")
	msg.WriteString("Content-Transfer-Encoding: 8bit\r\n")
	msg.WriteString("\r\n")
	msg.WriteString(body)

	addr := fmt.Sprintf("%s:%d", cfg.SMTPHost, cfg.SMTPPort)
	auth := smtp.PlainAuth("", username, cfg.Password, cfg.SMTPHost)
	encryption := strings.ToUpper(strings.TrimSpace(cfg.Encryption))

	if cfg.SMTPPort == 465 || encryption == "SSL" {
		tlsConfig := &tls.Config{
			ServerName:         cfg.SMTPHost,
			MinVersion:         tls.VersionTLS12,
			InsecureSkipVerify: false,
		}
		conn, err := tls.Dial("tcp", addr, tlsConfig)
		if err != nil {
			return err
		}
		client, err := smtp.NewClient(conn, cfg.SMTPHost)
		if err != nil {
			return err
		}
		defer client.Close()
		if err := client.Auth(auth); err != nil {
			return err
		}
		if err := client.Mail(fromAddress); err != nil {
			return err
		}
		if err := client.Rcpt(to); err != nil {
			return err
		}
		writer, err := client.Data()
		if err != nil {
			return err
		}
		if _, err := writer.Write(msg.Bytes()); err != nil {
			return err
		}
		if err := writer.Close(); err != nil {
			return err
		}
		return client.Quit()
	}

	return smtp.SendMail(addr, auth, fromAddress, []string{to}, msg.Bytes())
}
