package region

import (
	"context"
	"errors"

	"github.com/pingcap/log"
	"github.com/samber/lo"
	"go.uber.org/zap"
	"gorm.io/gorm"

	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/schema"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func (i *regionRepoImpl) UpsertRegionOpsAuditLogSetting(ctx context.Context, setting *entity.RegionOpsAuditLogSetting) bizerr.BizError {
	ctx, span := tracer.Start(ctx, "regionRepo.UpsertRegionOpsAuditLogSetting")
	defer span.End()

	if setting == nil {
		return bizerr.New(bizerr.ErrCodeParams, "region ops audit log setting is nil")
	}
	if setting.RegionID == 0 {
		return bizerr.New(bizerr.ErrCodeParams, "region id is required for upsert")
	}

	wdb := i.provider.WriteDB(ctx)

	var existingSetting schema.RegionOpsAuditLogSetting
	if err := wdb.Model(&schema.RegionOpsAuditLogSetting{}).
		Where("`region_id` = ?", setting.RegionID).
		First(&existingSetting).Error; err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			return bizerr.WrapGormError(err, "get existing region ops audit log setting for region %d", setting.RegionID)
		}
	}

	if existingSetting.ID != 0 {
		log.Debug("found existing setting, will update",
			zap.Uint("ID", existingSetting.ID),
			zap.Time("CreatedAt", existingSetting.CreatedAt))

		existingSetting.Enabled = lo.ToPtr(setting.Enabled)

		if setting.GetLogRotation() != nil {
			existingSetting.BucketUri = setting.GetLogLocation().GetBucketUri()
			existingSetting.RoleArn = setting.GetLogLocation().GetRoleArn()
			existingSetting.Type = setting.GetLogLocation().GetType().String()
		}
		if setting.GetLogRotation() != nil {
			existingSetting.RotationIntervalInMin = setting.GetLogRotation().GetRotationIntervalInMin()
			existingSetting.FileSizeLimitInMb = setting.GetLogRotation().GetFileSizeLimitInMb()
		}

		if err := wdb.Model(&existingSetting).Omit("created_at").Save(existingSetting).Error; err != nil {
			return bizerr.WrapGormError(err, "update region ops audit log setting for region %d", setting.RegionID)
		}
	} else {
		log.Debug("no existing setting found, will create new one")
		schemaSetting, err := convertRegionOpsAuditLogSettingEntityToModel(setting)
		if err != nil {
			return bizerr.WrapError(err, "convert region ops audit log setting entity to model")
		}
		if err := wdb.Create(&schemaSetting).Error; err != nil {
			return bizerr.WrapGormError(err, "insert region ops audit log setting for region %d", setting.RegionID)
		}
	}

	return nil
}
