package msp

import (
	"context"
	"fmt"
	"strconv"

	"github.com/spf13/viper"

	"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"
	accountH "github.com/tidbcloud/account/thirdparty/account"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

/**
MSP notice
Email Template          Direct customer convert to MSP customer   Branding new MSP customer registration

To PingCAP Deal desk    d-8b17af10f1e44cb8b066dbec075091df        d-8b17af10f1e44cb8b066dbec075091df
To MSP                  d-0819002f421243eda90515f29cccd700        d-0819002f421243eda90515f29cccd700
To MSP customer         d-7022a3e796d0401784394425f7261cac        d-7022a3e796d0401784394425f7261cac


CPPO noitce
Email Template          Direct customer convert to CPPO customer
To PingCAP Deal desk	d-8b17af10f1e44cb8b066dbec075091df
To CPPO					d-0819002f421243eda90515f29cccd700
To CPPO customer		d-0122d2791a84481cbf0fe2cde4acb71b

*/

const layout = "2006-01-02 15:04:05"

func (s *MspSvc) CustomerRegistrationNotice(ctx context.Context, customerOrgId uint64) error {
	customerOrg, err := s.hub.Org.GetOrgByOrgID(ctx, s.db.WithContext(ctx), customerOrgId)
	if err != nil {
		return err
	}

	customer, err := s.hub.Msp.GetCustomerByCustomerID(ctx, s.db.WithContext(ctx), entity.ID(customerOrgId))
	if err != nil {
		return err
	}
	// 20260319 an NPE issue was encountered, so add nil check
	if customer == nil {
		tilog.Info(ctx, "do not found customer partner relation, ignore to send", zap.Any("customerOrgId", customerOrgId))
		return nil
	}
	partnerOrg, err := s.hub.Org.GetOrgByOrgID(ctx, s.db.WithContext(ctx), customer.PartnerOrgID.Uint64())
	if err != nil {
		return err
	}
	sendEmailNotices(ctx, *customer, *partnerOrg, *customerOrg)
	return nil
}

// NoticePartner
//
//	@Description: send notice email to Partner when Direct customer convert to MSP customer
//	@Author wangletian 2024-07-10 19:55:21
//	@param ctx
//	@param customer
//	@param partnerOrg
//	@param customerOrg
//	@return error
func noticePartner(ctx context.Context, customer entity.PartnerCustomer, partnerOrg, customerOrg entity.Tenant) {

	email := partnerOrg.Email
	customerOrgName := utils.EscapeStr(ctx, customerOrg.Name)
	partnerOrgName := utils.EscapeStr(ctx, partnerOrg.Name)
	partnerOrgId := strconv.FormatUint(partnerOrg.ID.Uint64(), 10)

	partnerType := customer.PartnerType
	emailVars := map[string]string{
		"partnerType":     partnerType,
		"partnerOrgName":  partnerOrgName,
		"partnerOrgId":    partnerOrgId,
		"customerOrgName": customerOrgName,
	}
	tilog.Info(ctx, "NoticePartner emailVars", zap.Any("emailVars", emailVars))

	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("notice_partner_emailTN:%s_partner:%d_customer:%d", config.TNToPartnerNewCustomerRegistered, partnerOrg.ID.Uint64(), customerOrg.ID.Uint64())
	// f63eb7baaa84422ba2d85e730b0cf8e1
	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        customerOrg.ID.Uint64(),
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       []string{email},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNToPartnerNewCustomerRegistered],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "NoticePartner send  email req", zap.Any("sendEmailReq", sendEmailReq))

	accountHandler := accountH.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send NoticePartner email", zap.String("email", email), zap.Error(err))

	}
	tilog.Info(ctx, "NoticePartner resp", zap.Any("resp", resp))

}

func noticePingCAPDealDesk(ctx context.Context, customer entity.PartnerCustomer, partnerOrg, customerOrg entity.Tenant) {

	emails := viper.GetStringSlice("partner.pingCAPDealDeskNoticeEmail")
	tilog.Info(ctx, "get value from viper ", zap.Any("partner.pingCAPDealDeskNoticeEmail", viper.GetStringSlice("email")))

	if len(emails) == 0 {
		tilog.Error(ctx, "get partner.pingCAPDealDeskNoticeEmail from viper failed")
		return
	}
	customerOrgId := strconv.FormatUint(customerOrg.ID.Uint64(), 10)
	customerOrgName := utils.EscapeStr(ctx, customerOrg.Name)
	partnerOrgName := utils.EscapeStr(ctx, partnerOrg.Name)
	partnerOrgId := strconv.FormatUint(partnerOrg.ID.Uint64(), 10)

	partnerType := customer.PartnerType
	emailVars := map[string]string{
		"partnerType":     partnerType,
		"partnerOrgName":  partnerOrgName,
		"partnerOrgId":    partnerOrgId,
		"customerOrgName": customerOrgName,
		"customerOrgId":   customerOrgId,
	}
	tilog.Info(ctx, "NoticePingCAPDealDesk emailVars", zap.Any("emailVars", emailVars))
	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("notice_pingcap_dealDesk_emailTN:%s_partner:%d_customer:%d", config.TNToPingCAPNewCustomerRegistered, partnerOrg.ID.Uint64(), customerOrg.ID.Uint64())
	// f63eb7baaa84422ba2d85e730b0cf8e1
	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        customerOrg.ID.Uint64(),
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       emails,
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNToPingCAPNewCustomerRegistered],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "NoticePingCAPDealDesk send  email req", zap.Any("sendEmailReq", sendEmailReq))

	accountHandler := accountH.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send NoticePingCAPDealDesk email", zap.Any("emails", emails), zap.Error(err))

	}
	tilog.Info(ctx, "NoticePingCAPDealDesk resp", zap.Any("resp", resp))

}

func noticeToMspCustomer(ctx context.Context, customer entity.PartnerCustomer, partnerOrg, customerOrg entity.Tenant) {

	email := customerOrg.Email
	customerOrgId := strconv.FormatUint(customerOrg.ID.Uint64(), 10)

	mspName := utils.EscapeStr(ctx, partnerOrg.Name)
	customerOrgName := utils.EscapeStr(ctx, customerOrg.Name)

	effectedAtStr := customer.EffectedAt.Format(layout)
	emailVars := map[string]string{
		"mspName":         mspName,
		"customerOrgName": customerOrgName,
		"effectedAt":      effectedAtStr,
		"customerOrgId":   customerOrgId,
	}
	tilog.Info(ctx, "emailVars", zap.Any("emailVars", emailVars))

	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("emailTN:%s_Msp:%d_Customer:%d", config.TNMspDirectCustomerConvertToMSPCustomer, partnerOrg.ID.Uint64(), customerOrg.ID.Uint64())
	// f63eb7baaa84422ba2d85e730b0cf8e1
	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        customerOrg.ID.Uint64(),
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       []string{email},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNMspDirectCustomerConvertToMSPCustomer],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "send  email req", zap.Any("sendEmailReq", sendEmailReq))

	accountHandler := accountH.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send noticeToMspCustomer email", zap.String("email", email), zap.Error(err))

	}
	tilog.Info(ctx, "noticeToMspCustomer resp", zap.Any("resp", resp))

}

func noticeCppoCustomer(ctx context.Context, customer entity.PartnerCustomer, partnerOrg, customerOrg entity.Tenant) {

	email := customerOrg.Email
	customerOrgId := strconv.FormatUint(customerOrg.ID.Uint64(), 10)

	partnerOrgName := utils.EscapeStr(ctx, partnerOrg.Name)
	customerOrgName := utils.EscapeStr(ctx, customerOrg.Name)

	effectedAtStr := customer.EffectedAt.Format(layout)
	emailVars := map[string]string{
		"channelPartnerName": partnerOrgName,
		"customerOrgName":    customerOrgName,
		"effectedAt":         effectedAtStr,
		"customerOrgId":      customerOrgId,
	}
	tilog.Info(ctx, "emailVars", zap.Any("emailVars", emailVars))

	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("emailTN:%s_Partner:%d_Customer:%d", config.TNDirectCustomerConvertToCppoCustomer, partnerOrg.ID.Uint64(), customerOrg.ID.Uint64())
	// f63eb7baaa84422ba2d85e730b0cf8e1
	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        customerOrg.ID.Uint64(),
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       []string{email},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNDirectCustomerConvertToCppoCustomer],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "send  email req", zap.Any("sendEmailReq", sendEmailReq))

	accountHandler := accountH.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send noticeCppoCustomer email", zap.String("email", email), zap.Error(err))

	}
	tilog.Info(ctx, "noticeCppoCustomer resp", zap.Any("resp", resp))

}

func noticeMCPOCustomer(ctx context.Context, customer entity.PartnerCustomer, partnerOrg, customerOrg entity.Tenant) {

	email := customerOrg.Email
	customerOrgId := strconv.FormatUint(customerOrg.ID.Uint64(), 10)

	partnerOrgName := utils.EscapeStr(ctx, partnerOrg.Name)
	customerOrgName := utils.EscapeStr(ctx, customerOrg.Name)

	effectedAtStr := customer.EffectedAt.Format(layout)
	emailVars := map[string]string{
		"channelPartnerName": partnerOrgName,
		"customerOrgName":    customerOrgName,
		"effectedAt":         effectedAtStr,
		"customerOrgId":      customerOrgId,
	}
	tilog.Info(ctx, "emailVars", zap.Any("emailVars", emailVars))

	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("emailTN:%s_Partner:%d_Customer:%d", config.TNDirectCustomerConvertToMCPOCustomer, partnerOrg.ID.Uint64(), customerOrg.ID.Uint64())
	// f63eb7baaa84422ba2d85e730b0cf8e1
	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        customerOrg.ID.Uint64(),
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       []string{email},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNDirectCustomerConvertToMCPOCustomer],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "send  email req", zap.Any("sendEmailReq", sendEmailReq))

	accountHandler := accountH.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send noticeMCPOCustomer email", zap.String("email", email), zap.Error(err))

	}
	tilog.Info(ctx, "noticeMCPOCustomer resp", zap.Any("resp", resp))

}

func noticeResaleCustomer(ctx context.Context, customer entity.PartnerCustomer, partnerOrg, customerOrg entity.Tenant) {
	email := customerOrg.Email

	partnerOrgName := utils.EscapeStr(ctx, partnerOrg.Name)
	customerOrgName := utils.EscapeStr(ctx, customerOrg.Name)

	effectedAtStr := customer.EffectedAt.Format(layout)
	emailVars := map[string]string{
		"resellerName":    partnerOrgName,
		"customerOrgName": customerOrgName,
		"effectedAt":      effectedAtStr,
	}
	tilog.Info(ctx, "emailVars", zap.Any("emailVars", emailVars))

	// this is Unique Value    demo: msp_fist_key_keyId:3333
	identifier := fmt.Sprintf("emailTN:%s_Partner:%d_Customer:%d", config.TNResaleDirectCustomerConvertToResaleCustomer, partnerOrg.ID.Uint64(), customerOrg.ID.Uint64())
	// f63eb7baaa84422ba2d85e730b0cf8e1
	sendEmailReq := &accountpb.SendEmailReq{
		OrgId:        customerOrg.ID.Uint64(),
		Scene:        config.SendEmailScene,
		Identifier:   identifier,
		Emails:       []string{email},
		CcEmails:     nil,
		TemplateId:   config.SendgridTemplateName2id[config.TNResaleDirectCustomerConvertToResaleCustomer],
		TemplateVars: emailVars,
	}
	tilog.Info(ctx, "send  email req", zap.Any("sendEmailReq", sendEmailReq))

	accountHandler := accountH.GetHandler()
	resp, err := accountHandler.SendEmail(ctx, sendEmailReq)
	if err != nil && !errs.IsError(err, errs.ErrConflict) {
		tilog.Error(ctx, "failed to send noticeResaleCustomer email", zap.String("email", email), zap.Error(err))

	}
	tilog.Info(ctx, "noticeResaleCustomer resp", zap.Any("resp", resp))

}
