package msp

import (
	"context"
	"fmt"

	"github.com/duke-git/lancet/slice"
	"github.com/tidbcloud/account/internel/dao/entity"
	mspDao "github.com/tidbcloud/account/internel/dao/msp"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

// UserIsAgreeServicesAgreements
//
//	@Description:  only user in table[spUserServicesAgreements], the is isAgree=[true,false],else isAgree=true
//	@Author wangletian 2024-01-11 21:56:56
//	@receiver s
//	@param ctx
//	@param userId
//	@param customerOrgId
//	@return bool
//	@return error
func (s *MspSvc) UserIsAgreeServicesAgreements(ctx context.Context, userId, customerOrgId uint64) (bool, error) { //
	tilog.Info(ctx, "MspSvc UserIsAgreeServicesAgreements", zap.Any("userId", userId), zap.Any("customerOrgId", customerOrgId))
	//isInOrg, err := s.checkUserInOrg(ctx, userId, customerOrgId)

	status := string(entity.Active)
	filter := mspDao.UserServicesAgreementFilter{UserID: entity.ID(userId), CustomerOrgID: entity.ID(customerOrgId), Status: &status}
	objs, err := s.hub.Msp.ListMspUserServicesAgreements(ctx, s.db.WithContext(ctx), filter)
	if err != nil {
		return true, err
	}
	if len(objs) == 1 {
		tilog.Info(ctx, "MspSvc UserIsAgreeServicesAgreements  "+fmt.Sprintf("result = %t", len(objs) == 0), zap.Any("userId", userId), zap.Any("customerOrgId", customerOrgId))
		isAgree := objs[0].IsAgree
		return isAgree, nil
	} else if len(objs) == 0 {
		tilog.Info(ctx, "MspSvc UserIsAgreeServicesAgreements record not found ,set isAgree=true "+fmt.Sprintf("result = %t", len(objs) == 0), zap.Any("userId", userId), zap.Any("customerOrgId", customerOrgId))
	} else if len(objs) > 1 {
		tilog.Info(ctx, "MspSvc UserIsAgreeServicesAgreements , more than one record found, set isAgree=true "+fmt.Sprintf("result = %t", len(objs) == 0), zap.Any("userId", userId), zap.Any("customerOrgId", customerOrgId))
	}
	return true, nil

}

func (s *MspSvc) SaveMspUserServicesAgreement(ctx context.Context, userId, customerOrgId uint64) error {
	tilog.Info(ctx, "MspSvc SaveMspUserServicesAgreement ", zap.Any("userId", userId), zap.Any("customerOrgId", customerOrgId))

	isInOrg, err := s.checkUserInOrg(ctx, userId, customerOrgId)
	if err != nil {
		return err
	}

	if isInOrg {
		obj := &entity.MspUserServicesAgreement{
			UserID:        entity.ID(userId),
			CustomerOrgID: entity.ID(customerOrgId),
			IsAgree:       true,
			Status:        string(entity.Active),
		}
		return s.hub.Msp.CreateMspUserServicesAgreement(ctx, s.db.WithContext(ctx), obj)
	}

	msg := "The user does not belong to the org : " + fmt.Sprintf("%d, or illegal org_id", customerOrgId)
	return errs.NewBadRequest(msg, nil)

}
func (s *MspSvc) UpdateMspUserServicesAgreementByIds(ctx context.Context, ids []uint64, mspUserServicesAgreements entity.MspUserServicesAgreement) error {
	tilog.Info(ctx, "MspSvc UpdateMspUserServicesAgreementByIds", zap.Any("ids", ids))

	return s.hub.Msp.UpdateMspUserServicesAgreementByIds(ctx, s.db.WithContext(ctx), ids, mspUserServicesAgreements)
}
func (s *MspSvc) UpdateMspUserServicesAgreementByParam(ctx context.Context, param mspDao.UserServicesAgreementFilter, updater entity.MspUserServicesAgreement) error {
	tilog.Info(ctx, "MspSvc UpdateMspUserServicesAgreementByParam", zap.Any("param", param), zap.Any("updater", updater))

	return s.hub.Msp.UpdateMspUserServicesAgreementByParam(ctx, s.db.WithContext(ctx), param, updater)
}
func (s *MspSvc) ListMspUserServicesAgreements(ctx context.Context, filter mspDao.UserServicesAgreementFilter) ([]entity.MspUserServicesAgreement, error) {
	tilog.Info(ctx, "MspSvc ListMspUserServicesAgreements", zap.Any("filter", filter))

	return s.hub.Msp.ListMspUserServicesAgreements(ctx, s.db.WithContext(ctx), filter)
}

// checkUserInOrg
// @Description:	 Check if the user belongs to org.
// @Author wangletian 2023-12-26 14:44:32
// @receiver s
// @param ctx
// @param userId
// @param customerOrgId
// @return bool
// @return error
func (s *MspSvc) checkUserInOrg(ctx context.Context, userId, customerOrgId uint64) (bool, error) {
	// Check if the user belongs to org.

	orgUserIds, err := s.hub.Role.GetUserIdsInOrgs(ctx, s.db.WithContext(ctx), []uint64{customerOrgId})
	if err != nil {

		tilog.Error(ctx, "RoleDao GetUserIdsInOrgs err: "+fmt.Sprintf("orgId=%d", customerOrgId), zap.Error(err))
		return false, err
	}
	if slice.Contain(orgUserIds, userId) {
		return true, nil
	}
	//if !slices.Contains(orgUserIds, userId) {
	//	// user in the org
	//	return true, &roleBindings[0].CreatedAt, nil
	//}
	msg := "The user does not belong to the org : " + fmt.Sprintf("%d", customerOrgId)
	tilog.Info(ctx, msg, zap.Any("userID", userId))
	return false, nil
}

func (s *MspSvc) BatchCreateMspUserServicesAgreements(ctx context.Context, mspUserServicesAgreements []entity.MspUserServicesAgreement) error {
	tilog.Info(ctx, "MspSvc mspUserServicesAgreements", zap.Any("mspUserServicesAgreements", mspUserServicesAgreements))

	return s.hub.Msp.BatchCreateMspUserServicesAgreements(ctx, s.db.WithContext(ctx), mspUserServicesAgreements)
}

/*
func (s *MspSvc) checkUserInOrg(ctx context.Context, userId, customerOrgId uint64) (bool, error) {
	// Check if the user belongs to org.
	orgIds, err := s.hub.Role.GetUserOrgIds(ctx, s.db.WithContext(ctx), userId)
	if err != nil {
		tilog.Info(ctx, "failed to GetUserOrgIds from db", zap.Any("userId", userId), zap.Error(err))
		return false, err
	}
	if len(orgIds) != 0 && slice.Contain(orgIds, customerOrgId) {
		return true, nil
	}
	return false, nil
}
*/
