package device

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// BatchUpdateRealnamePolicy 批量更新设备实名认证策略，整批校验后在单事务内全成全败。
func (s *Service) BatchUpdateRealnamePolicy(ctx context.Context, req *dto.BatchUpdateAssetRealnamePolicyRequest) (*dto.BatchUpdateAssetRealnamePolicyResponse, error) {
	if middleware.GetUserTypeFromContext(ctx) == constants.UserTypeEnterprise {
		return nil, errors.New(errors.CodeForbidden, "企业账号无权修改设备实名认证策略")
	}
	ids, err := validateBatchRealnamePolicyRequest(req)
	if err != nil {
		return nil, err
	}
	err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		var devices []model.Device
		query := middleware.ApplyShopFilter(ctx, tx.Model(&model.Device{})).Clauses(clause.Locking{Strength: "UPDATE"})
		if err := query.Where("id IN ?", ids).Find(&devices).Error; err != nil {
			return errors.Wrap(errors.CodeDatabaseError, err, "查询批量设备资产失败")
		}
		if len(devices) != len(ids) {
			return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
		}
		result := tx.Model(&model.Device{}).Where("id IN ?", ids).Update("realname_policy", req.RealnamePolicy)
		if result.Error != nil {
			return errors.Wrap(errors.CodeDatabaseError, result.Error, "批量更新设备实名认证策略失败")
		}
		if result.RowsAffected != int64(len(ids)) {
			return errors.New(errors.CodeConflict, "设备资产状态已变化，请刷新后重试")
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	s.logDeviceOperation(
		ctx,
		constants.AssetAuditOpAssetRealnamePolicy,
		"批量更新设备实名认证策略",
		constants.AssetAuditResultSuccess,
		nil,
		nil,
		map[string]any{"asset_ids": ids, "realname_policy": req.RealnamePolicy},
		len(ids),
		len(ids),
		0,
		nil,
	)
	return &dto.BatchUpdateAssetRealnamePolicyResponse{SuccessCount: len(ids), RealnamePolicy: req.RealnamePolicy}, nil
}

func validateBatchRealnamePolicyRequest(req *dto.BatchUpdateAssetRealnamePolicyRequest) ([]uint, error) {
	if req == nil || len(req.AssetIDs) == 0 || len(req.AssetIDs) > 500 || !isValidRealnamePolicy(req.RealnamePolicy) {
		return nil, errors.New(errors.CodeInvalidParam)
	}
	seen := make(map[uint]struct{}, len(req.AssetIDs))
	ids := make([]uint, 0, len(req.AssetIDs))
	for _, id := range req.AssetIDs {
		if id == 0 {
			return nil, errors.New(errors.CodeInvalidParam)
		}
		if _, exists := seen[id]; exists {
			return nil, errors.New(errors.CodeInvalidParam, "资产ID不能重复")
		}
		seen[id] = struct{}{}
		ids = append(ids, id)
	}
	return ids, nil
}

func isValidRealnamePolicy(policy string) bool {
	return policy == constants.RealnamePolicyNone ||
		policy == constants.RealnamePolicyBeforeOrder ||
		policy == constants.RealnamePolicyAfterOrder
}
