package com.tzy.service.question;

import com.tzy.app.domain.AppBaseUser;
import com.tzy.app.mapper.AppBaseUserMapper;
import com.tzy.common.constant.Constants;
import com.tzy.common.constant.MsgConstants;
import com.tzy.common.exception.AppAssert;
import com.tzy.common.exception.ServiceException;
import com.tzy.dto.LimitAmountConfig;
import com.tzy.dto.QuestionParam;
import com.tzy.mapper.QuestionnaireMapper;
import com.tzy.pojo.question.Question;
import com.tzy.pojo.question.QuestionAnswer;
import com.tzy.pojo.question.Questionnaire;
import com.tzy.pojo.question.UserLimitRecord;
import com.tzy.sportcard.group.service.ICardGroupOrderInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户问卷相关服务
 */
@Service
@Slf4j
public class QuestionnaireService {

    @Resource
    private QuestionnaireMapper questionnaireMapper;
    @Resource
    private AppBaseUserMapper baseUserMapper;
    @Resource
    private ICardGroupOrderInfoService orderInfoService;

    private static String LIMIT_TYPE_QUESTIONNAIRE = "questionnaire_";


    /**
     * 用户是否填写过有效的问卷
     *
     * @param userId
     * @param questionnaireId
     * @return
     */
    private boolean hasUserQuestionnaire(Integer userId, Long questionnaireId) {
        return questionnaireMapper.hasUserQuestionnaireByType(userId, LIMIT_TYPE_QUESTIONNAIRE + questionnaireId) != null;
    }

    public Questionnaire getQuestionnaireDetail(Long id) {
        Questionnaire questionnaire = questionnaireMapper.getLastQuestionnaire(null, id, null);
        AppAssert.notNull(questionnaire, MsgConstants.RECORD_EMPTY);
        List<Question> questions = questionnaireMapper.getQuestionsByQuestionnaireId(id);
        AppAssert.notEmpty(questions, MsgConstants.RECORD_EMPTY);
        questionnaire.setQuestions(questions);
        return questionnaire;
    }

    /**
     * 提交问卷,提升额度
     *
     * @param questionParam
     * @return
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public boolean submitQuestionnaire(QuestionParam questionParam) {
        boolean hasUserQuestionnaire = hasUserQuestionnaire(questionParam.getUserId(), questionParam.getQuestionnaireId());
        if (hasUserQuestionnaire) {
            log.warn("用户:{}已经提交过问卷:{}", questionParam.getUserId(), questionParam.getQuestionnaireId());
            return false;
        }
        List<QuestionAnswer> questionAnswers = questionParam.getQuestionAnswers();
        Long questionnaireId = questionParam.getQuestionnaireId();
        Questionnaire questionnaire = questionnaireMapper.getLastQuestionnaire(null, questionnaireId, null);
        AppAssert.notNull(questionnaire, MsgConstants.RECORD_EMPTY);
        boolean amountQuestion = Constants.TYPE_USER_INCR_AMOUNT.equals(questionnaire.getType());
        checkQuestionAnswer(questionnaireId, questionAnswers, amountQuestion);
        boolean hasErrAnswer = questionAnswers.stream().anyMatch(answer -> answer.getAnswerType() == 0);
        AppBaseUser user = baseUserMapper.selectAppBaseUserById(questionParam.getUserId().longValue());
        LimitAmountConfig.MemberAmount memberLimitAmount = orderInfoService.getUserExtraLimitAmount(user.getMemberLevel(), user.getCreateTime());
        UserLimitRecord record = new UserLimitRecord().setUserId(user.getId().intValue()).setType(LIMIT_TYPE_QUESTIONNAIRE + questionnaireId).setStatus(0)
                .setCreatedBy(user.getId().toString()).setStatus(0)
                .setPreviousDailyLimit(user.getDailyLimit() + memberLimitAmount.getDailyLimit())
                .setPreviousWeeklyLimit(user.getWeeklyLimit() + memberLimitAmount.getWeeklyLimit())
                .setPreviousMonthlyLimit(user.getMonthlyLimit() + memberLimitAmount.getAmount());
        if (!hasErrAnswer && amountQuestion) {
            // 提额通过
            record.setStatus(1).setNewMonthlyLimit(record.getPreviousMonthlyLimit() + questionnaire.getIncrAmount())
                    .setNewDailyLimit(record.getPreviousDailyLimit() + questionnaire.getDailyLimit())
                    .setNewWeeklyLimit(record.getPreviousWeeklyLimit() + questionnaire.getWeeklyLimit());
            AppBaseUser editUser = new AppBaseUser();
            editUser.setId(user.getId());
            editUser.setDailyLimit(user.getDailyLimit() + questionnaire.getDailyLimit());
            editUser.setWeeklyLimit(user.getWeeklyLimit() + questionnaire.getWeeklyLimit());
            editUser.setMonthlyLimit(user.getMonthlyLimit() + questionnaire.getIncrAmount());
            baseUserMapper.updateAppBaseUser(editUser);
        }
        questionnaireMapper.insertUserLimitRecord(record);
        questionAnswers.forEach(answer -> answer.setQuestionnaireId(questionnaireId).setUserId(questionParam.getUserId()).setRecordId(record.getId()));
        questionnaireMapper.batchInsertQuestionAnswers(questionAnswers);
        return !hasErrAnswer;
    }

    private void checkQuestionAnswer(Long questionnaireId, List<QuestionAnswer> questionAnswers, boolean amountQuestion) {
        List<Question> questions = questionnaireMapper.getQuestionsByQuestionnaireId(questionnaireId);
        AppAssert.notEmpty(questions, MsgConstants.RECORD_EMPTY);
        Set<Long> questionIds = questions.stream().map(Question::getId).collect(Collectors.toSet());
        boolean errQuestion = questionAnswers.stream().anyMatch(answer -> !questionIds.contains(answer.getQuestionId()));
        if (errQuestion) {
            throw new ServiceException("问卷提交信息错误");
        }
        if (amountQuestion) {
            Set<Long> answerQuestionIds = questionAnswers.stream().map(QuestionAnswer::getQuestionId).collect(Collectors.toSet());
            if (questionIds.size() != answerQuestionIds.size()) {
                throw new ServiceException("问卷提交信息错误");
            }
        }
    }
}
