package msp

import (
	"context"
	"time"

	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

type UserServicesAgreementFilter struct {
	UserID        entity.ID
	CustomerOrgID entity.ID
	IsAgree       *bool
	Status        *string
	CreatedAtGte  *time.Time
}

func (d *MspDao) CreateMspUserServicesAgreement(ctx context.Context, tx *gorm.DB, mspUserServicesAgreement *entity.MspUserServicesAgreement) error {
	err := tx.Create(mspUserServicesAgreement).Error
	if err != nil {
		return err
	}
	tilog.Info(ctx, "MspDao CreateMspUserServicesAgreement success: ", zap.Any("mspUserServicesAgreement: ", mspUserServicesAgreement))

	return nil
}

func (d *MspDao) BatchCreateMspUserServicesAgreements(ctx context.Context, tx *gorm.DB, mspUserServicesAgreements []entity.MspUserServicesAgreement) error {

	err := tx.CreateInBatches(mspUserServicesAgreements, len(mspUserServicesAgreements)).Error
	if err != nil {
		tilog.Error(ctx, "MspDao BatchCreateMspUserServicesAgreement fail: ", zap.Error(err))
		return err
	}
	tilog.Info(ctx, "MspDao BatchCreateMspUserServicesAgreement success: ", zap.Any("size: ", len(mspUserServicesAgreements)))
	return nil
}

//func (d *MspDao) GetMspUserServicesAgreement(ctx context.Context, tx *gorm.DB, userId, customerOrgId uint64) (*entity.MspUserServicesAgreement, error) {
//	var objs []entity.MspUserServicesAgreement
//	err := entity.NewMspUserServicesAgreementQuerySet(tx).UserIDEq(entity.ID(userId)).CustomerOrgIDEq(entity.ID(customerOrgId)).CreatedAtGte().All(&objs)
//
//	if err != nil {
//		if err != gorm.ErrRecordNotFound {
//			tilog.Error(ctx, "GetMspUserServicesAgreement fail: ", zap.Error(err))
//			return nil, err
//		}
//		return nil, nil
//	}
//	tilog.Info(ctx, "MspDao GetMspUserServicesAgreement success: ", zap.Any("userId: ", userId), zap.Any("mspCustomerOrgId: ", customerOrgId))
//
//	return &obj, err
//}

func (d *MspDao) ListMspUserServicesAgreements(ctx context.Context, tx *gorm.DB, filter UserServicesAgreementFilter) ([]entity.MspUserServicesAgreement, error) {
	var objs = make([]entity.MspUserServicesAgreement, 0)

	//if filter.UserID == 0 && filter.CustomerOrgID == 0 {
	//	tilog.Info(ctx, "ListGetMspUserServicesAgreements  param UserID and  CustomerOrgID is nil ", zap.Error(nil))
	//	return objs, errs.NewBadRequest("ListGetMspUserServicesAgreements  param UserID and  CustomerOrgID  should not be empty", nil)
	//}

	if filter.IsAgree == nil && filter.Status == nil {
		tilog.Info(ctx, "ListGetMspUserServicesAgreements  param  is nil ", zap.Error(nil))
		return nil, errs.NewBadRequest("ListGetMspUserServicesAgreements IsAgree and Status should not be empty", nil)
	}

	qs := entity.NewMspUserServicesAgreementQuerySet(tx)

	if filter.UserID != 0 {
		qs = qs.UserIDEq(filter.UserID)
	}
	if filter.CustomerOrgID != 0 {
		qs = qs.CustomerOrgIDEq(filter.CustomerOrgID)
	}
	if filter.IsAgree != nil {
		qs = qs.IsAgreeEq(*filter.IsAgree)
	}

	if filter.Status != nil {
		qs = qs.StatusIn(*filter.Status)
	}

	if filter.CreatedAtGte != nil {
		qs = qs.CreatedAtGte(*filter.CreatedAtGte)
	}

	qs = qs.OrderDescByCreatedAt()
	err := qs.All(&objs)
	if err != nil && err != gorm.ErrRecordNotFound {
		tilog.Error(ctx, "ListGetMspUserServicesAgreements fail", zap.Error(err))
		return nil, err
	}
	tilog.Info(ctx, "ListGetMspUserServicesAgreements  success", zap.Any("filter", filter), zap.Any("size", len(objs)))
	return objs, nil
}

func (d *MspDao) UpdateMspUserServicesAgreementByIds(ctx context.Context, tx *gorm.DB, ids []uint64, mspUserServicesAgreements entity.MspUserServicesAgreement) error {
	var entityIDs []entity.ID
	for _, id := range ids {
		entityIDs = append(entityIDs, entity.ID(id))

	}
	if len(entityIDs) == 0 {
		return nil
	}
	updater := entity.NewMspUserServicesAgreementQuerySet(tx).IDIn(entityIDs...).GetUpdater()

	if mspUserServicesAgreements.CustomerOrgID != 0 {
		updater.SetCustomerOrgID(mspUserServicesAgreements.CustomerOrgID)
	}

	if mspUserServicesAgreements.UserID != 0 {
		updater.SetUserID(mspUserServicesAgreements.UserID)
	}
	if mspUserServicesAgreements.Status != "" {
		updater.SetStatus(mspUserServicesAgreements.Status)
	}

	err := updater.Update()

	if err != nil {
		return err
	}
	return nil
}

func (d *MspDao) UpdateMspUserServicesAgreementByParam(ctx context.Context, tx *gorm.DB, param UserServicesAgreementFilter, updaterEntity entity.MspUserServicesAgreement) error {

	// 1 : query entity
	qs := entity.NewMspUserServicesAgreementQuerySet(tx)

	if param.UserID != 0 {
		qs = qs.UserIDEq(param.UserID)
	}
	if param.CustomerOrgID != 0 {
		qs = qs.CustomerOrgIDEq(param.CustomerOrgID)
	}
	if param.IsAgree != nil {
		qs = qs.IsAgreeEq(*param.IsAgree)
	}

	if param.Status != nil {
		qs = qs.StatusIn(*param.Status)
	}

	if param.CreatedAtGte != nil {
		qs = qs.CreatedAtGte(*param.CreatedAtGte)
	}
	updater := qs.GetUpdater()

	// 2: update entity
	if updaterEntity.CustomerOrgID != 0 {
		updater.SetCustomerOrgID(updaterEntity.CustomerOrgID)
	}

	if updaterEntity.UserID != 0 {
		updater.SetUserID(updaterEntity.UserID)
	}
	if updaterEntity.Status != "" {
		updater.SetStatus(updaterEntity.Status)
	}
	updater.SetIsAgree(updaterEntity.IsAgree)

	err := updater.Update()

	if err != nil {
		tilog.Error(ctx, "UpdateMspUserServicesAgreementByParam fail", zap.Any("param", param), zap.Any("updaterEntity", updaterEntity), zap.Error(err))
		return err
	}
	tilog.Info(ctx, "UpdateMspUserServicesAgreementByParam result", zap.Any("param", param), zap.Any("updaterEntity", updaterEntity))
	return nil
}
