package systemmaintenance

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"github.com/go-logr/logr"
	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	"github.com/tidbcloud/devops/pkg/infra/clients/accountcli"
	"github.com/tidbcloud/devops/pkg/infra/log"
	"github.com/tidbcloud/pkgv2/goroutine"
)

const (
	systemMaintenanceEmailTemplateId = "d-6e66ddeb9503468f8273b14da7752b94" // announce.system_maintenance
	concurrentLimit                  = 10
	emailSendScene                   = "devops:system_maintenance"
)

type Service struct {
	logger     logr.Logger
	accountCli accountcli.Client
}

func NewService(
	accountCli accountcli.Client,
) *Service {
	return &Service{
		logger:     log.Logger.WithName("systemMaintenanceEmailSender"),
		accountCli: accountCli,
	}
}

func (s *Service) SendSystemMaintenanceEmail(ctx context.Context, batchId string, tenantIDs []string, targetRoleStrs string) error {
	s.logger.Info("try to send system maintenance email", "batchId", batchId, "tenantIds", tenantIDs, "targetRoles", targetRoleStrs)

	var targetRoles []account.MailLabels
	for _, each := range strings.Split(targetRoleStrs, ",") {
		role, ok := account.MailLabels_value[each]
		if !ok || account.MailLabels(role) == account.MailLabels_MAIL_LABELS_UNSPECIFIED {
			return fmt.Errorf("invalid target role: %s", each)
		}
		targetRoles = append(targetRoles, account.MailLabels(role))
	}
	if len(targetRoles) == 0 {
		return fmt.Errorf("empty targetRoles")
	}

	var fns []goroutine.Handle
	for _, tenantIdStr := range tenantIDs {
		tenantId, err := strconv.ParseUint(tenantIdStr, 10, 64)
		if err != nil {
			s.logger.Error(err, "got invalid tenantId", "tenantId", tenantIdStr)
			continue
		}

		fns = append(fns, func() error {
			s.sendSystemMaintenanceEmail2OneTenant(ctx, batchId, tenantId, targetRoles)
			return nil
		})

	}
	return goroutine.ConcurrentWithLimit(ctx, concurrentLimit, fns...)
}

func (s *Service) sendSystemMaintenanceEmail2OneTenant(ctx context.Context, batchId string, tenantID uint64, targetRoles []account.MailLabels) {
	for _, role := range targetRoles {
		logger := s.logger.WithValues("batchID", batchId, "tenantID", tenantID, "role", role)
		logger.Info("try to send email, start")

		req := &account.SendEmailByLabelsReq{
			OrgId:        tenantID,
			Scene:        emailSendScene,
			Identifier:   fmt.Sprintf("%s:%d", batchId, tenantID),
			Subject:      "unused-subject",
			ToLabel:      role,
			CcLabels:     nil,
			TemplateId:   systemMaintenanceEmailTemplateId,
			TemplateVars: nil,
		}
		if err := s.accountCli.SendEmailByLabels(ctx, req); err != nil {
			logger.Error(err, "send email to target failed")
			continue
		}
		logger.Info("try to send email, done")
	}
}
