package com.microservices.zone.member.service.points.handler;

import com.microservices.zone.member.domain.points.ZonePointsAccount;
import com.microservices.zone.member.mapper.ZonePointsAccountMapper;
import com.microservices.zone.member.mapper.ZonePointsTransactionMapper;
import com.microservices.zone.member.service.points.IPointsTaskHandler;
import com.microservices.zone.member.service.points.PointsAccountOperations;
import com.microservices.zone.member.service.points.PointsTaskContext;
import com.microservices.zone.utils.ZoneConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 文章被设为精选 — 积分奖励
 *
 * @author otto
 */
@Component
public class FeaturedDocPointsHandler implements IPointsTaskHandler {

    @Autowired
    private PointsAccountOperations pointsAccountOperations;

    @Autowired
    private ZonePointsAccountMapper zonePointsAccountMapper;

    @Autowired
    private ZonePointsTransactionMapper zonePointsTransactionMapper;

    private static final Logger logger = LoggerFactory.getLogger(FeaturedDocPointsHandler.class);

    @Override
    public String getSourceType() {
        return ZoneConstants.FeaturedDoc.SOURCE_TYPE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handle(PointsTaskContext ctx) {
        // CMS 侧写入任务时不携带 zoneId，需通过 deptId 解析补齐
        pointsAccountOperations.resolveZoneId(ctx);

        ZonePointsAccount account = pointsAccountOperations.getOrCreateAccount(ctx.getUserId(), ctx.getZoneId());
        if (account == null) {
            return;
        }

        // 幂等检查：同一文章被精选同一用户只发放一次
        if (zonePointsTransactionMapper.countByEventTypeAndSourceAndUser(ZoneConstants.FeaturedDoc.SOURCE_TYPE, ctx.getSourceId(), account.getId()) > 0) {
            logger.info("积分-文章精选：积分已发放，跳过 sourceId={} userId={}", ctx.getSourceId(), ctx.getUserId());
            return;
        }

        ZonePointsAccount locked = zonePointsAccountMapper.selectZonePointsAccountByIdForUpdate(account.getId());
        int availableAfter = locked.getAvailablePoints() + ZoneConstants.FeaturedDoc.POINTS;
        int frozenAfter = locked.getFrozenPoints();

        zonePointsAccountMapper.addPointsAtomic(account.getId(), ZoneConstants.FeaturedDoc.POINTS);

        pointsAccountOperations.recordPointsTransaction(account.getId(),
                ZoneConstants.TransactionType.ADD,
                ZoneConstants.FeaturedDoc.POINTS,
                availableAfter, frozenAfter,
                ZoneConstants.FeaturedDoc.REASON, 0L, ctx.getSourceId(),
                ZoneConstants.FeaturedDoc.SOURCE_TYPE, null,
                ZoneConstants.FeaturedDoc.SUBJECT, ctx.getSubjectDesc(),
                null);
    }
}
