package iot_card

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	assetAuditSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_audit"
	"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 cards []model.IotCard
		query := middleware.ApplyShopFilter(ctx, tx.Model(&model.IotCard{})).Clauses(clause.Locking{Strength: "UPDATE"})
		if err := query.Where("id IN ?", ids).Find(&cards).Error; err != nil {
			return errors.Wrap(errors.CodeDatabaseError, err, "查询批量卡资产失败")
		}
		if len(cards) != len(ids) {
			return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
		}
		result := tx.Model(&model.IotCard{}).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.logCardAudit(ctx, assetAuditSvc.BuildLogParams{
		OperationType: constants.AssetAuditOpCardRealnamePolicy,
		OperationDesc: "批量更新卡实名认证策略",
		ResultStatus:  constants.AssetAuditResultSuccess,
		BatchTotal:    len(ids),
		SuccessCount:  len(ids),
		AfterData: map[string]any{
			"asset_ids":       ids,
			"realname_policy": req.RealnamePolicy,
		},
	})
	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
}
