package jobs

import (
	"context"
	"strconv"
	"strings"
	"time"

	"github.com/tidbcloud/pkgv2/log"
	"github.com/tidbcloud/serverless-service/idl/pbgen/proto/serverless"
	"github.com/tidbcloud/serverless-service/internal/config"
	"github.com/tidbcloud/serverless-service/internal/controller"
	"github.com/tidbcloud/serverless-service/internal/domain/service"
	"go.uber.org/zap"
)

func SendEmail(ctx context.Context, orgs, excludeOrgs string, preview bool) error {
	return controller.DiCall(func(
		billingDomainSvc service.BillingService,
		billingController serverless.ServerlessBillingServiceServer,
	) error {
		globalLogger := log.WithContextL(ctx).With(zap.String("orgs", orgs), zap.Bool("preview", preview))
		orgsAndClusters, err := billingDomainSvc.ListOrgsWithActiveLogs(ctx)
		if err != nil {
			return err
		}
		if orgs != "" {
			temp := make(map[uint64][]uint64)
			orgIdsStr := strings.Split(orgs, ",")
			for _, str := range orgIdsStr {
				orgId, err := strconv.ParseUint(str, 10, 64)
				if err != nil {
					globalLogger.Error("failed to convert org id", zap.Error(err))
					continue
				}
				if clusterIds, ok := orgsAndClusters[orgId]; ok {
					temp[orgId] = clusterIds
				}
			}
			orgsAndClusters = temp
		}
		if excludeOrgs != "" {
			excludeOrgIdsStr := strings.Split(excludeOrgs, ",")
			for _, str := range excludeOrgIdsStr {
				excludeOrgId, err := strconv.ParseUint(str, 10, 64)
				if err != nil {
					globalLogger.Error("failed to convert org id", zap.Error(err))
					continue
				}
				delete(orgsAndClusters, excludeOrgId)
			}
		}

		globalLogger.Info(
			"start to send email",
			zap.Int("orgsCount", len(orgsAndClusters)),
			zap.Any("orgIds", orgsAndClusters),
		)
		stage := config.Global().ServerConfig.Stage
		if stage == "dev" || stage == "staging" {
			globalLogger.Error("only prod stage is supported")
			return nil
		}

		succeed := 0
		start := time.Now()
		for orgId, clusterIds := range orgsAndClusters {
			childStart := time.Now()
			logger := log.WithContextL(ctx).With(zap.Uint64("org_id", orgId))
			_, err := billingController.SendExpensiveSQLEmail(
				ctx,
				&serverless.ExpensiveSqlEmailReq{
					OrgId:          orgId,
					Preview:        preview,
					SkipDownloadS3: true,
					ClusterIds:     clusterIds,
				},
			)
			if err != nil {
				logger.Error(
					"send email failed",
					zap.Error(err),
					zap.Duration("childJobDuration", time.Since(childStart)),
				)
				continue
			}
			logger.Info("send email success", zap.Duration("childJobDuration", time.Since(childStart)))
			succeed++
		}
		globalLogger.Info(
			"all child jobs finished",
			zap.Duration("duration", time.Since(start)),
			zap.Int("succeed", succeed),
			zap.Int("expected", len(orgsAndClusters)),
		)
		return nil
	})
}
