package mail

import (
	"bytes"
	"context"
	"crypto/tls"
	"fmt"
	"html/template"
	"net/mail"
	"net/smtp"
	"strings"

	"bsm/full/module/base/sender/internal/config"
	"bsm/full/module/base/sender/internal/excode"
	"bsm/full/module/base/sender/internal/impl"
	"bsm/full/module/base/sender/internal/models"
	pb "bsm/full/module/base/sender/pb"
	"git.apinb.com/bsm-sdk/core/errcode"
	"git.apinb.com/bsm-sdk/core/vars"
)

func Send(ctx context.Context, in *pb.SendMailRequest) (reply *pb.SendMailReply, err error) {
	provider := strings.ToLower(in.GetProvider())

	// 校验参数
	if in.GetTemplateKey() == "" || provider == "" || in.GetTo() == "" {
		return nil, errcode.ErrInvalidArgument
	}

	// 校验配置
	cfg, ok := config.Spec.SMTP[provider]
	if !ok || cfg == nil {
		return nil, excode.ErrProviderIsNil
	}

	// 检验邮箱格式
	if !ValidateEmail(in.GetTo()) {
		return nil, excode.ErrEmail
	}

	// 获取模板
	var tplRecord models.SenderTemplate
	err = impl.DBService.Where("key=?", in.GetTemplateKey()).First(&tplRecord).Error
	if err != nil {
		return nil, errcode.ErrNotFound(1404, "template")
	}

	// 解析模板
	tmpl, err := template.New("page").Parse(tplRecord.Body)
	if err != nil {
		return nil, excode.ErrTemplate
	}

	// 发送邮件
	switch provider {
	case "qq":
		err = QQ(cfg, tmpl, in.GetTo(), tplRecord.Subjet, in.GetParamters())
	default:
		return nil, excode.ErrNotProvider
	}

	if err != nil {
		return nil, err
	}

	return &pb.SendMailReply{
		Data: vars.OK,
	}, nil
}

func ValidateEmail(s string) bool {
	_, err := mail.ParseAddress(s)
	return err == nil
}

func QQ(cfg *config.SmtpConf, tmpl *template.Template, to string, subject string, args map[string]string) error {
	// 建立TLS加密连接
	conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", cfg.Endpoint, cfg.Port), &tls.Config{
		ServerName:         cfg.Endpoint,
		MinVersion:         tls.VersionTLS12, // 强制TLS1.2+
		InsecureSkipVerify: false,
	})
	if err != nil {
		fmt.Println("TLS连接失败: ", err)
		return err
	}

	// 创建SMTP客户端（带超时控制）
	client, err := smtp.NewClient(conn, cfg.Endpoint)
	if err != nil {
		client.Close()
		fmt.Println("SMTP客户端初始化失败: ", err)
		return err
	}

	// 设置认证
	auth := smtp.PlainAuth("", cfg.Username, cfg.Password, cfg.Endpoint)
	if err := client.Auth(auth); err != nil {
		client.Close()
		fmt.Println("认证失败: ", err)
		return err
	}

	// 设置发件人和收件人
	err = client.Mail(cfg.FromAddress)
	if err != nil {
		client.Close()
		fmt.Println("发件人设置失败: ", err)
		return err
	}
	err = client.Rcpt(to)
	if err != nil {
		fmt.Println("发件人设置失败: ", err)
		client.Close()
		return err
	}

	// 创建一个写入SMTP服务器的标准写入器
	writer, err := client.Data()
	if err != nil {
		client.Close()
		return err
	}
	defer writer.Close()

	// 构建邮件正文
	mailBody := "From: " + cfg.FromName + "<" + cfg.FromAddress + ">\n"
	mailBody += "To: " + to + "\n"
	mailBody += "Subject: " + subject + "\n\n"

	// 执行模板，将结果写入邮件正文
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, args)
	if err != nil {
		return err
	}
	mailBody += buf.String()

	// 将邮件正文发送到SMTP服务器
	if _, err := writer.Write([]byte(mailBody)); err != nil {
		client.Close()
		fmt.Printf("写入邮件内容失败: %v", err)
		return err
	}

	if err := writer.Close(); err != nil {
		client.Close()
		fmt.Printf("关闭数据流失败: %v", err)
		return err
	}
	return nil
}
