package repository

import (
	"backend/pkg/notification/config"
	"backend/pkg/notification/domain"
	"backend/pkg/notification/domain/repository"
	"context"
	"time"

	"backend/pkg/library/errs/code"
	pool "backend/pkg/library/worker_pool"

	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/service/ses/types"
	"github.com/zeromicro/go-zero/core/logx"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/ses"
)

// AwsEmailDeliveryParam 傳送參數配置
type AwsEmailDeliveryParam struct {
	Conf *config.AmazonSesSettings
}

type AwsEmailDeliveryRepository struct {
	Client *ses.Client
	Pool   pool.WorkerPool
}

func MustAwsSesMailRepository(param AwsEmailDeliveryParam) repository.MailRepository {
	// 手動指定 AWS 配置，不使用默認配置
	cfg := aws.Config{
		Region: param.Conf.Region, // 自定義的 AWS 區域
		Credentials: credentials.NewStaticCredentialsProvider(
			param.Conf.AccessKey, // AWS Access Key
			param.Conf.SecretKey, // AWS Secret Key
			"",
		),
	}
	// 創建 SES 客戶端
	sesClient := ses.NewFromConfig(cfg)

	return &AwsEmailDeliveryRepository{
		Client: sesClient,
		Pool:   pool.NewWorkerPool(param.Conf.PoolSize),
	}
}

func (use *AwsEmailDeliveryRepository) SendMail(ctx context.Context, req repository.MailReq) error {
	err := use.Pool.Submit(func() {
		// 設置郵件參數
		to := make([]string, 0, len(req.To))
		to = append(to, req.To...)

		input := &ses.SendEmailInput{
			Destination: &types.Destination{
				ToAddresses: to,
			},
			Message: &types.Message{
				Body: &types.Body{
					Html: &types.Content{
						Charset: aws.String("UTF-8"),
						Data:    aws.String(req.Body),
					},
				},
				Subject: &types.Content{
					Charset: aws.String("UTF-8"),
					Data:    aws.String(req.Subject),
				},
			},
			Source: aws.String(req.From),
		}

		// 發送郵件
		// TODO 不明原因送不出去，會被 context cancel 這裡先把它手動加到100sec
		newCtx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
		defer cancel()

		//nolint:contextcheck
		if _, err := use.Client.SendEmail(newCtx, input); err != nil {
			_ = domain.ThirdPartyErrorL(
				code.CloudEPNotification,
				domain.FailedToSendEmailErrorCode,
				logx.WithContext(ctx),
				[]logx.LogField{
					{Key: "req", Value: req},
					{Key: "func", Value: "AwsEmailDeliveryU.SendEmail"},
					{Key: "err", Value: err.Error()},
				},
				"failed to send mail by aws ses")
		}
	})
	if err != nil {
		e := domain.ThirdPartyErrorL(
			code.CloudEPNotification,
			domain.FailedToSendEmailErrorCode,
			logx.WithContext(ctx),
			[]logx.LogField{
				{Key: "req", Value: req},
				{Key: "func", Value: "AwsEmailDeliveryU.SendEmail"},
				{Key: "err", Value: err.Error()},
			},
			"failed to send mail by aws ses")

		return e
	}

	return nil
}
