package msp

import (
	"context"
	"sync"

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

	"github.com/tidbcloud/account/internel/dao/msp"

	"github.com/tidbcloud/account/idl/pbgen/proto/account"

	"github.com/tidbcloud/account/admin/forms"

	"gorm.io/gorm"

	"github.com/tidbcloud/account/internel/dao"
	"github.com/tidbcloud/account/internel/dao/entity"
)

var (
	_ MspSvcIface = (*MspSvc)(nil)
)

type MspSvcIface interface {
	// MspConfig
	CreateMsp(ctx context.Context, msp forms.MspOrg) (mspOrg *entity.Tenant, err error)
	GetMspConfigByOrgID(ctx context.Context, orgID entity.ID) (*entity.MspConfig, error)
	UpdateMspConfig(ctx context.Context, mspConfig entity.MspConfig) error
	ListMspConfigs(ctx context.Context, req forms.ListMspReq) (*forms.PageData, error)
	GetMspLogUrl(ctx context.Context, logoName string) string
	AdvertisingArrToJsonStr(ctx context.Context, advertisingArr []forms.Advertising) (string, error)
	JsonStrToAdvertisingArr(ctx context.Context, advertisingJsonStr string) ([]forms.Advertising, error)

	// PartnerCustomer
	GetCustomerByCustomerID(ctx context.Context, orgID entity.ID) (*entity.PartnerCustomer, error)
	GetCustomerByMspID(ctx context.Context, orgID entity.ID) (resultMap map[entity.PartnerCustomer]entity.Tenant, err error)
	ListCustomers(ctx context.Context, req *account.ListPartnerCustomersReq) ([]entity.PartnerCustomer, error)
	CreateCustomer(ctx context.Context, mspCustomer *entity.PartnerCustomer, isCheckParam bool) error
	UpdateCustomer(ctx context.Context, mspCustomer entity.PartnerCustomer) error
	DeleteCustomer(ctx context.Context, mspCustomer entity.PartnerCustomer) error
	CancelCustomer(ctx context.Context, mspCustomer entity.PartnerCustomer) error
	MakeCustomerEffect(ctx context.Context, mspCustomer entity.PartnerCustomer) error

	//MspUserServicesAgreement
	SaveMspUserServicesAgreement(ctx context.Context, userId, customerOrgId uint64) error
	UserIsAgreeServicesAgreements(ctx context.Context, userId, customerOrgId uint64) (bool, error)
	BatchCreateMspUserServicesAgreements(ctx context.Context, mspUserServicesAgreements []entity.MspUserServicesAgreement) error
	ListMspUserServicesAgreements(ctx context.Context, filter msp.UserServicesAgreementFilter) ([]entity.MspUserServicesAgreement, error)
	UpdateMspUserServicesAgreementByIds(ctx context.Context, ids []uint64, updater entity.MspUserServicesAgreement) error
	UpdateMspUserServicesAgreementByParam(ctx context.Context, param msp.UserServicesAgreementFilter, updater entity.MspUserServicesAgreement) error

	// Cppo
	CreateCppoOrg(ctx context.Context, req forms.CppoOrgReq) (mspOrg *entity.Tenant, err error)
	// MCPO Reseller
	CreateMCPOResellerOrg(ctx context.Context, req forms.MCPOResellerOrgReq) (resellerOrg *entity.Tenant, err error)
	// Resale
	CreateResalePartnerOrg(ctx context.Context, req forms.ResellerOrgReq) (resellerOrg *entity.Tenant, err error)

	// notice
	CustomerRegistrationNotice(ctx context.Context, customerOrgId uint64) error
}

var (
	mspSvcInitOnce  sync.Once
	mspSvcIInstance MspSvcIface
)

func GetMspSvc() (MspSvcIface, error) {
	mspSvcInitOnce.Do(func() {
		mspSvcIInstance = NewMspSvc(database.DBConn.DB, dao.GetDaoHub())
	})
	return mspSvcIInstance, nil
}

type MspSvc struct {
	db  *gorm.DB
	hub *dao.DaoHub
}

func NewMspSvc(db *gorm.DB, hub *dao.DaoHub) MspSvcIface {
	return &MspSvc{
		db:  db,
		hub: hub,
	}
}
