package com.pandoli365.bibimbap.badge;

import org.springframework.stereotype.Service;

import com.pandoli365.bibimbap.mapper.ReputationEventsMapper;
import com.pandoli365.bibimbap.mapper.UserBadgesMapper;
import com.pandoli365.bibimbap.mapper.UsersMapper;

@Service
public class BadgeService {

    private final ReputationEventsMapper reputationEventsMapper;
    private final UserBadgesMapper userBadgesMapper;
    private final UsersMapper usersMapper;

    public BadgeService(ReputationEventsMapper reputationEventsMapper,
                        UserBadgesMapper userBadgesMapper,
                        UsersMapper usersMapper) {
        this.reputationEventsMapper = reputationEventsMapper;
        this.userBadgesMapper = userBadgesMapper;
        this.usersMapper = usersMapper;
    }

    // 자동부여: 해당 배지의 평판 누적이 임계 도달 시 멱등 부여.
    // 자동 경로의 badgeKey 는 항상 코드 상수(ReputationService)라 정상엔 무효 키가 도달하지 않으나, 방어적으로 무시한다.
    public void evaluateAndSync(long userId, String badgeKey) {
        if (!BadgeKeys.isValid(badgeKey)) {
            return;
        }
        BadgeKeys badge = BadgeKeys.valueOf(badgeKey);
        long count = reputationEventsMapper.countActive(userId, badge.eventType());
        if (count >= badge.threshold()) {
            // ux_user_badges_active ON CONFLICT DO NOTHING (멱등)
            userBadgesMapper.insertIgnore(userId, badgeKey);
        }
    }

    // 수동 부여: 컨트롤러가 CSRF+BADGE_MANAGE 게이트 통과 후 호출. 도메인 검증(키유효/대상존재/중복)만 수행.
    public GrantResult grantManual(long userId, String badgeKey, long awardedBy) {
        if (!BadgeKeys.isValid(badgeKey)) {
            return GrantResult.INVALID_BADGE;
        }
        if (usersMapper.getUser(userId) == null) {
            return GrantResult.USER_NOT_FOUND;
        }
        if (userBadgesMapper.existsActive(userId, badgeKey)) {
            return GrantResult.ALREADY_ACTIVE;
        }
        userBadgesMapper.insert(userId, badgeKey, awardedBy);
        return GrantResult.GRANTED;
    }

    // 수동 회수: revoked_at+reason 설정. 활성 미보유면 NOT_ACTIVE. 키 유효성 선검사.
    public RevokeResult revokeManual(long userId, String badgeKey, String reason) {
        if (!BadgeKeys.isValid(badgeKey)) {
            return RevokeResult.INVALID_BADGE;
        }
        int affected = userBadgesMapper.revoke(userId, badgeKey, reason);
        return affected > 0 ? RevokeResult.REVOKED : RevokeResult.NOT_ACTIVE;
    }

    public enum GrantResult {
        GRANTED,
        ALREADY_ACTIVE,
        INVALID_BADGE,
        USER_NOT_FOUND
    }

    public enum RevokeResult {
        REVOKED,
        NOT_ACTIVE,
        INVALID_BADGE
    }
}
