package ru.soune.nocopy.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import ru.soune.ReferralInvitee;
import ru.soune.ReferralLevel;
import ru.soune.ReferralService;
import ru.soune.ReferralStat;
import ru.soune.nocopy.dto.BaseRequest;
import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.referral.ReferralRequest;
import ru.soune.nocopy.entity.user.AuthToken;
import ru.soune.nocopy.repository.AuthTokenRepository;

import java.util.List;
import java.util.Map;


@Component
@RequiredArgsConstructor
public class ReferralHandler implements RequestHandler {

    private final ReferralService referralService;

    private final AuthTokenRepository authTokenRepository;

    private final ObjectMapper mapper = new ObjectMapper();

    @Override
    public BaseResponse handle(BaseRequest request) throws Exception {
        ReferralRequest referralRequest = mapper.convertValue(request.getMessageBody(), ReferralRequest.class);
        String action = referralRequest.getAction();
        String token = referralRequest.getToken();
        AuthToken authToken = authTokenRepository.findByToken(token).orElseThrow();

        switch (action) {
            case "refill":
                return handleRefill(request, authToken.getUser().getId(), referralRequest.getAmount());
            case "levels":
                return handleReferralLevels(request);
            case "level":
                return handleUserLevel(request, authToken.getUser().getId());
            case "userStats" :
                return handleUserStats(request, authToken.getUser().getId());
            case "invitees":
                return handleInvitees(referralRequest, request, authToken.getUser().getId());
        }

        return null;
    }

    private BaseResponse handleRefill(BaseRequest request, Long userId, Integer amount) {
        referralService.onUserAccountRefill(userId, amount);

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(), Map.of("account", "refill"));
    }

    private BaseResponse handleReferralLevels(BaseRequest request) {
        List<ReferralLevel> referralLevels = referralService.getReferralLevels();

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(), referralLevels);

    }

    private BaseResponse handleUserLevel(BaseRequest request, Long userId) {
        ReferralLevel referralLevelForUser = referralService.getReferralLevelForUser(userId);

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(), referralLevelForUser);
    }

    private BaseResponse handleUserStats(BaseRequest request, Long userId) {
        ReferralStat referralStatForUser = referralService.getReferralStatForUser(userId);

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(), referralStatForUser);
    }

    private BaseResponse handleInvitees(ReferralRequest referralRequest, BaseRequest request, Long userId) {
        List<ReferralInvitee> inviteeForUser = referralService.getInviteeForUser(userId, referralRequest.getPageSize(),
                referralRequest.getPageNumber());

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(), inviteeForUser);
    }
}
