package service

import (
	"crypto/tls"
	"fmt"
	"mime"
	"net/smtp"
	"strconv"
	"strings"
)

type EmailService struct{}

func NewEmailService() *EmailService {
	return &EmailService{}
}

type EmailConfig struct {
	Host      string
	Port      int
	User      string
	Password  string
	FromName  string
	FromEmail string
	UseSSL    bool
}

func (s *EmailService) SendEmail(config EmailConfig, to, subject, body string) error {
	if config.Host == "" || config.User == "" || config.Password == "" {
		return fmt.Errorf("邮件配置不完整")
	}

	from := config.FromEmail
	if from == "" {
		from = config.User
	}

	addr := fmt.Sprintf("%s:%d", config.Host, config.Port)

	msg := s.buildMessage(config.FromName, from, to, subject, body)

	auth := smtp.PlainAuth("", config.User, config.Password, config.Host)

	if config.Port == 465 || config.UseSSL {
		return s.sendWithImplicitTLS(addr, auth, from, []string{to}, []byte(msg))
	}

	return s.sendWithSTARTTLS(addr, auth, from, []string{to}, []byte(msg))
}

func (s *EmailService) sendWithImplicitTLS(addr string, auth smtp.Auth, from string, to []string, msg []byte) error {
	host := strings.Split(addr, ":")[0]

	tlsConfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         host,
	}

	conn, err := tls.Dial("tcp", addr, tlsConfig)
	if err != nil {
		return fmt.Errorf("TLS连接失败: %v", err)
	}

	client, err := smtp.NewClient(conn, host)
	if err != nil {
		return fmt.Errorf("创建SMTP客户端失败: %v", err)
	}
	defer client.Close()

	if err = client.Auth(auth); err != nil {
		return fmt.Errorf("SMTP认证失败: %v", err)
	}

	if err = client.Mail(from); err != nil {
		return fmt.Errorf("设置发件人失败: %v", err)
	}

	for _, addr := range to {
		if err = client.Rcpt(addr); err != nil {
			return fmt.Errorf("设置收件人失败: %v", err)
		}
	}

	w, err := client.Data()
	if err != nil {
		return fmt.Errorf("准备邮件数据失败: %v", err)
	}

	_, err = w.Write(msg)
	if err != nil {
		return fmt.Errorf("写入邮件内容失败: %v", err)
	}

	err = w.Close()
	if err != nil {
		return fmt.Errorf("关闭邮件写入失败: %v", err)
	}

	return client.Quit()
}

func (s *EmailService) sendWithSTARTTLS(addr string, auth smtp.Auth, from string, to []string, msg []byte) error {
	host := strings.Split(addr, ":")[0]

	client, err := smtp.Dial(addr)
	if err != nil {
		return fmt.Errorf("连接SMTP服务器失败: %v", err)
	}
	defer client.Close()

	if err = client.Hello("localhost"); err != nil {
		return fmt.Errorf("HELO命令失败: %v", err)
	}

	tlsConfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         host,
	}

	if ok, _ := client.Extension("STARTTLS"); ok {
		if err = client.StartTLS(tlsConfig); err != nil {
			return fmt.Errorf("STARTTLS失败: %v", err)
		}
	}

	if err = client.Auth(auth); err != nil {
		return fmt.Errorf("SMTP认证失败: %v", err)
	}

	if err = client.Mail(from); err != nil {
		return fmt.Errorf("设置发件人失败: %v", err)
	}

	for _, addr := range to {
		if err = client.Rcpt(addr); err != nil {
			return fmt.Errorf("设置收件人失败: %v", err)
		}
	}

	w, err := client.Data()
	if err != nil {
		return fmt.Errorf("准备邮件数据失败: %v", err)
	}

	_, err = w.Write(msg)
	if err != nil {
		return fmt.Errorf("写入邮件内容失败: %v", err)
	}

	err = w.Close()
	if err != nil {
		return fmt.Errorf("关闭邮件写入失败: %v", err)
	}

	return client.Quit()
}

func (s *EmailService) buildMessage(fromName, from, to, subject, body string) string {
	msg := ""

	if fromName != "" {
		encodedName := mime.QEncoding.Encode("UTF-8", fromName)
		msg += fmt.Sprintf("From: %s <%s>\r\n", encodedName, from)
	} else {
		msg += fmt.Sprintf("From: %s\r\n", from)
	}

	msg += fmt.Sprintf("To: %s\r\n", to)
	msg += fmt.Sprintf("Subject: %s\r\n", mime.QEncoding.Encode("UTF-8", subject))
	msg += "MIME-version: 1.0;\r\nContent-Type: text/html; charset=\"UTF-8\";\r\n\r\n"
	msg += body

	return msg
}

func (s *EmailService) SendTestEmail(config EmailConfig, to, siteName string) error {
	subject := fmt.Sprintf("测试邮件 - %s", siteName)
	body := fmt.Sprintf(`
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
</head>
<body style="font-family: Arial, sans-serif; padding: 20px; background-color: #f5f5f5;">
	<div style="max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
		<h2 style="color: #333; margin-bottom: 20px;">邮件发送测试成功</h2>
		<p style="color: #666; line-height: 1.6;">这是一封测试邮件，如果您收到此邮件，说明您的SMTP配置正确。</p>
		<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
		<p style="color: #999; font-size: 12px;">此邮件由 %s 系统自动发送，请勿回复。</p>
	</div>
</body>
</html>
`, siteName)
	return s.SendEmail(config, to, subject, body)
}

func ParseBool(value string) bool {
	return value == "true" || value == "1" || strings.ToLower(value) == "yes"
}

func ParseInt(value string, defaultValue int) int {
	if value == "" {
		return defaultValue
	}
	val, err := strconv.Atoi(value)
	if err != nil {
		return defaultValue
	}
	return val
}
