package comsvc

import (
	"context"
	"fmt"

	"github.com/tidbcloud/account/commons/database"

	"github.com/google/uuid"
	"github.com/tidbcloud/account/central/utils"
	"github.com/tidbcloud/account/commons/config"
	accountpb "github.com/tidbcloud/account/idl/pbgen/proto/account"
	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/account/internel/svc/token"
	"github.com/tidbcloud/account/thirdparty/account"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

const (
	inviteTokenVerifyUrlFormat = "https://%s/invitation-verification?token=%s"
	inviteEmailSubjectFormat   = "Invitation to TiDB Cloud: %s"
)

func InvitationSendActivationEmail(ctx context.Context, inviterEmail, inviteeEmail, orgName string, orgId uint64) error {
	tilog.Info(ctx, "InvitationSendActivationEmail param", zap.Any("inviter_email", inviterEmail), zap.Any("invitee_email", inviteeEmail), zap.Any("org_id", orgId), zap.Any("org_name", orgName))
	if inviterEmail == "" || inviteeEmail == "" || orgName == "" || orgId == 0 {
		return errs.NewBadRequest("param invalid", nil)
	}
	// gen invite token
	session, _ := token.GetSession()
	inviteToken, err := session.InsertUserInviteToken(database.DBConn.DB, 0, entity.ID(orgId), token.InvitationVerificationMethod, inviteeEmail, entity.InviteTokenValidityPeriod, true)
	if err != nil {
		tilog.Error(ctx, "InvitationSendActivationEmail create invite token error", zap.Any("err", err))
		return errs.NewInternalUnknown("create invite token internal error", err)
	}
	tilog.Info(ctx, "InvitationSendActivationEmail create invite token success", zap.Any("token", inviteToken))

	subject := fmt.Sprintf(inviteEmailSubjectFormat, orgName)
	escapeOrgName := utils.EscapeStr(ctx, orgName)
	url := fmt.Sprintf(inviteTokenVerifyUrlFormat, utils.GetCentralBackendDns(), inviteToken)
	vars := map[string]string{
		"orgNameInSubject": orgName,
		"organizationName": escapeOrgName,
		"inviterName":      inviterEmail,
		"url":              url,
	}
	tilog.Info(ctx, "InvitationSendActivationEmail send email param", zap.Any("subject", subject), zap.Any("vars", vars))

	_, err = account.GetHandler().SendEmail(ctx, &accountpb.SendEmailReq{
		OrgId:        orgId,
		Scene:        string(entity.NotificationSceneInvite),
		Identifier:   uuid.New().String(),
		Subject:      subject,
		Emails:       []string{inviteeEmail},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNInviteUser],
		TemplateVars: vars,
	})
	if err != nil {
		tilog.Error(ctx, "InvitationSendActivationEmail send email error", zap.Any("err", err))
		return errs.NewInternalUnknown("failed send email", err)
	}
	tilog.Info(ctx, "InvitationSendActivationEmail send notification email success", zap.Any("invitee_email", inviteeEmail), zap.Any("org_id", orgId))

	return nil
}
