/**
 * Description: CmCreditRecord数据访问实现类
 * Copyright:   Copyright (c)2015
 * Company:     江苏三六五网络股份有限公司
 *
 * @author: 江苏三六五网络股份有限公司
 * @version: 1.0
 * Create at:   2015-08-14 上午 09:30:51
 * <p/>
 * Modification History:
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2015-08-14   江苏三六五网络股份有限公司   1.0         Initial
 */
package com.house365.ws.dao.impl;

import com.house365.beans.entity.*;
import com.house365.beans.system.QueryParams;
import com.house365.dao.system.impl.DefaultDaoImpl;
import com.house365.rest.context.CmConstant;
import com.house365.ws.dao.interfaces.*;
import com.house365.ws.service.interfaces.ICmUserService;
import com.house365.ws.util.CmCommonUtils;
import com.house365.ws.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.*;

/**
 * CmCreditRecord数据访问实现类<br>
 *
 * @author 江苏三六五网络股份有限公司
 * @version 1.0, 2015-08-14
 * @see
 * @since 1.0
 */
@Repository("cmCreditRecordDao")
public class CmCreditRecordDaoImpl extends DefaultDaoImpl<CmCreditRecordEntity> implements ICmCreditRecordDao<CmCreditRecordEntity> {

    private static final Logger LOGGER = LoggerFactory.getLogger("InterfaceLog");

    @Resource(name = "cmUserDao")
    ICmUserDao<CmUserEntity> cmUserDao;

    @Resource(name = "cmCreditRuleDao")
    ICmCreditRuleDao<CmCreditRuleEntity> cmCreditRuleDao;

    @Resource(name = "cmBrokerCommentDao")
    ICmBrokerCommentDao<CmBrokerCommentEntity> cmBrokerCommentDao;

    @Resource(name = "cmCreditGoodsDao")
    ICmCreditGoodsDao<CmCreditGoodsEntity> cmCreditGoodsDao;
    @Autowired
    private ICmUserService cmUserService;

    public static final Map<Integer, String> ruleCRMrel = new HashMap<>();

    static {
        ruleCRMrel.put(CmConstant.CREDITS_RULE_SIGN, "169");
        //        ruleCRMrel.put(CmConstant.CREDITS_RULE_REGISTER, "153");
        ruleCRMrel.put(CmConstant.CREDITS_RULE_UPLOAD_PHOTO, "103");
        ruleCRMrel.put(CmConstant.CREDITS_RULE_INVITE_USER, "103");
        ruleCRMrel.put(CmConstant.CREDITS_RULE_HOUSE_COMMENT, "103");
        ruleCRMrel.put(CmConstant.CREDITS_RULE_SIGN_LOTTERY, "255");
        ruleCRMrel.put(CmConstant.CREDITS_RULE_EXCHANGE_GOODS, "254");
    }

    /**
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param user          用户id（app端id）
     * @param credits       增加或扣除的积分（区分正负）, 如果为空，则从rule配置中获取
     * @param creditsRuleId 积分规则id
     * @since [产品/模块版本](可选)
     */
    private synchronized CmCreditRecordEntity generateRecord(
        CmUserEntity user, int creditsRuleId, Integer credits
    ) throws Exception {
        CmCreditRecordEntity record = new CmCreditRecordEntity();

        record.setUserId(user.getId());
        record.setUserName(user.getUserName());
        record.setUserPhone(user.getPhoneNumber());

        CmCreditRuleEntity rule = cmCreditRuleDao.getById(creditsRuleId);

        if (rule == null) {
            throw new Exception("rule is not exsited");
        }

        if (rule.getCredits() == null) {
            rule.setCredits(0);
        }

        if (credits == null) {
            credits = rule.getCredits();
        }

        //活动加权
        boolean inActive = false;
        Date now = new Date();
        Date startDate = null;
        Date endDate = null;
        if (rule.getActiveStartTime() != null) {
            startDate = rule.getActiveStartTime();
        }
        if (rule.getActiveEndTime() != null) {
            endDate = rule.getActiveEndTime();
        }

        if (startDate != null && endDate != null && now.compareTo(startDate) >= 0 && now.compareTo(endDate) <= 0) {
            inActive = true;
        } else if (startDate != null && endDate == null && now.compareTo(startDate) >= 0) {
            inActive = true;
        } else if (endDate != null && startDate == null && now.compareTo(endDate) <= 0) {
            inActive = true;
        }

        //目前只计算整数
        if (inActive) {
            rule.setCredits(rule.getCredits() * rule.getActiveWeight().intValue());
        }

        //如果是签到积分，则需要加上额外奖励（连续签到）
        if (creditsRuleId == CmConstant.CREDITS_RULE_SIGN) {
            credits = credits + rule.getCredits();
        }

        record.setRuleId(rule.getId());
        record.setRuleName(rule.getCreditRuleName());
        record.setAmount(credits);
        record.setHappenTime(new Date());
        if (user.getCredits() == null) {
            user.setCredits(0);
        }

        record.setRemainingAmount(user.getCredits() + credits);
        LOGGER.info("generateRecord user:{}, rule:{} {}, credits : {}, remainAmount:{}", user.getUserId(),
                    creditsRuleId, rule.getCreditRuleName(), credits, record.getRemainingAmount());

        //调用CRM接口
        if (ruleCRMrel.containsKey(rule.getId())) {
            CmCommonUtils.callCRM(user.getPhoneNumber(), user.getCityId(), ruleCRMrel.get(rule.getId()),
                                  record.getRuleName());
        }

        return record;
    }

    /**
     * 根据策略ID判断是否可加积分,暂不用于老策略
     *
     * @param rule   策略ID
     * @param userId 用户
     * @return true 可加分 false 不可加分
     */
    @Override
    public boolean checkByRule(CmCreditRuleEntity rule, int userId) {
        boolean flag = false;

        QueryParams<CmCreditRecordEntity> qp = new QueryParams<>();
        Map<String, Object> map = new HashMap<>();
        map.put("EQ_ruleId", rule.getId());
        map.put("EQ_userId", userId);

        //1 means today
        int days = (rule.getCountCircle() == null || rule.getCountCircle() == 1) ? 0 : rule.getCountCircle();
        int count = rule.getCountLimit() == null ? 9999 : rule.getCountLimit();

        Date begin = DateUtils.getDayBefore(days);
        Date end = new Date();

        if (days != 9999999) {
            map.put("GTE_happenTime", begin);
        }
        map.put("LTE_andHappenTime", end);
        qp.setSearchParams(map);
        if (getTotalCount(qp) < count) {
            flag = true;
        } else {
            LOGGER.info("user:[{}],规则:[{}]不可重复加分!!!", userId, rule.getCreditRuleName());
        }

        return flag;
    }

    //保存签到积分
    @Override
    public CmCreditRecordEntity saveSignCreditsRecord(CmUserEntity user, Integer credits) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_SIGN, credits);
        this.save(record);
        return record;
    }

    //保存签到抽奖积分
    @Override
    public CmCreditRecordEntity saveSignLotteryCreditsRecord(CmUserEntity user, int credits) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_SIGN_LOTTERY, credits);
        this.save(record);
        return record;
    }

    //保存签到抽奖扣除积分
    @Override
    public CmCreditRecordEntity saveLotteryCreditsRecord(CmUserEntity user, int credits) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_LOTTERY, credits);

        this.save(record);
        return record;
    }

    //保存注册积分
    @Override
    public CmCreditRecordEntity saveRegisterRecord(CmUserEntity user) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_REGISTER, null);
        this.save(record);
        return record;
    }

    //保存上传头像积分
    @Override
    public CmCreditRecordEntity saveUploadPhotoRecord(CmUserEntity user) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_UPLOAD_PHOTO, null);
        this.save(record);
        return record;
    }

    //业主社区发帖回帖
    @Override
    public CmCreditRecordEntity saveBBSRecord(CmUserEntity user) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_POST, null);
        this.save(record);
        return record;
    }

    @Override
    public CmCreditRecordEntity saveRecord(CmUserEntity user, Integer ruleId, Integer credit) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, ruleId, credit);
        this.save(record);
        return record;
    }

    //房博士提问扣积分
    @Override
    public CmCreditRecordEntity saveQuestionMinusRecord(CmUserEntity user, Integer credit) throws Exception {
        credit = (credit > 0) ? -credit : credit;
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_QUESTION_MINUS, credit);
        this.save(record);
        return record;
    }

    //保存楼盘评论积分
    @Override
    public CmCreditRecordEntity saveHouseCommentRecord(CmUserEntity user, int commentId) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_HOUSE_COMMENT, null);
        record.setCommentId(commentId);
        this.save(record);
        return record;
    }

    //保存房源积分
    @Override
    public CmCreditRecordEntity saveHouseResourceRecord(CmUserEntity user, int houseId) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_HOUSE_RESOURCE, null);
        record.setCommentId(houseId);
        this.save(record);
        return record;
    }

    //保存经纪人评论积分
    @Override
    public CmCreditRecordEntity saveBrokerCommentRecord(CmUserEntity user, int commentId) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_BROKER_COMMENT, null);
        record.setCommentId(commentId);
        this.save(record);
        return record;
    }

    //保存经纪人评论扣除积分
    @Override
    public CmCreditRecordEntity saveBrokerCommentRemoveRecord(CmUserEntity user, int commentId) throws Exception {
        QueryParams<CmCreditRecordEntity> qp = new QueryParams<>();
        Map<String, Object> map = new HashMap<>();
        map.put("EQ_commentId", commentId);
        map.put("EQ_ruleId", CmConstant.CREDITS_RULE_BROKER_COMMENT);
        qp.setSearchParams(map);
        List<CmCreditRecordEntity> list = this.queryAll(qp);
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_BROKER_COMMENT_REMOVE,
                                                     0 - list.get(0).getAmount());
        record.setCommentId(commentId);
        this.save(record);
        return record;
    }

    //保存楼盘评论扣除积分
    @Override
    public CmCreditRecordEntity saveHouseCommentRemoveRecord(CmUserEntity user, int commentId) throws Exception {
        QueryParams<CmCreditRecordEntity> qp = new QueryParams<>();
        Map<String, Object> map = new HashMap<>();
        map.put("EQ_commentId", commentId);
        map.put("EQ_ruleId", CmConstant.CREDITS_RULE_HOUSE_COMMENT);
        qp.setSearchParams(map);
        List<CmCreditRecordEntity> list = this.queryAll(qp);
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_HOUSE_COMMENT_REMOVE,
                                                     0 - list.get(0).getAmount());
        record.setCommentId(commentId);
        this.save(record);
        return record;
    }

    //保存邀请积分
    @Override
    public CmCreditRecordEntity saveInviteRecord(CmUserEntity user, int recordId) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_INVITE_USER, null);
        record.setCommonId(recordId);
        int id = this.save(record);
        record.setId(id);
        return record;
    }

    //加精积分
    @Override
    public CmCreditRecordEntity saveAddExcellentRecord(CmUserEntity user, int commonId) throws Exception {
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_ADD_EXCELLENT, null);
        record.setCommonId(commonId);
        int id = this.save(record);
        record.setId(id);
        return record;
    }

    //房管家获得积分
    @Override
    public CmCreditRecordEntity saveQuestion(CmUserEntity user, String questionId) throws Exception {
        CmCreditRecordEntity record = null;

        CmCreditRuleEntity rule = cmCreditRuleDao.getById(CmConstant.CREDITS_RULE_QUESTION);

        if (rule == null || rule.getIsShow() == 1) {
            LOGGER.warn("checkByRule warn: [rule not existed or not show]");
            return record;
        }

        if (checkByRule(rule, user.getId())) {
            record = generateRecord(user, CmConstant.CREDITS_RULE_QUESTION, rule.getCredits());
            record.setGoodsName(questionId);
            int id = this.save(record);
            record.setId(id);
        }

        return record;
    }

    /**
     * 变更会员积分
     *
     * @param user
     * @param credits
     * @return
     * @throws Exception
     */
    @Override
    public CmCreditRecordEntity saveChangeCreditsRecord(
        CmUserEntity user, Integer ruleId, Integer credits
    ) throws Exception {
        CmCreditRecordEntity record = null;
        CmCreditRuleEntity rule = cmCreditRuleDao.getById(ruleId);
        if (rule == null || rule.getIsShow() == 1) {
            throw new Exception("积分规则不存在!");
        }

        if (checkByRule(rule, user.getId())) {
            record = generateRecord(user, ruleId, credits);
            int id = this.save(record);
            record.setId(id);
        }
        return record;
    }

    /**
     * 功能描述: 保存奖品兑换扣除积分  <br>
     * 〈功能详细描述〉
     *
     * @param user       用户
     * @param orderId    订单号
     * @param goodsCount 商品数量
     * @param goodsId    商品ID
     * @author yinchangming
     * @version [v1.0.0, 2015年8月21日]
     * @since [产品/模块版本](可选)
     */
    @Override
    public CmCreditRecordEntity saveGoodsExchangeRecord(
        CmUserEntity user, int orderId, int goodsCount, int goodsId
    ) throws Exception {
        CmCreditGoodsEntity goods = cmCreditGoodsDao.getById(goodsId);
        int credits = goods.getCreditsNeeded() * goodsCount;
        CmCreditRecordEntity record = generateRecord(user, CmConstant.CREDITS_RULE_EXCHANGE_GOODS, credits);
        record.setGoodsId(goodsId);
        record.setGoodsName(goods.getGoodsName());
        record.setGoodsAmount(goodsCount);
        record.setOrderId(orderId);
        this.save(record);
        return record;
    }

    @Override
    public Integer removeCredit(Integer commentId, Integer ruleId) {
        try {
            //扣除积分
            //根据评论ID和规则ID获取之前评论记录
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("EQ_commentId", commentId);
            map.put("EQ_ruleId", ruleId);

            QueryParams<CmCreditRecordEntity> queryParams = new QueryParams<CmCreditRecordEntity>(map);
            List<CmCreditRecordEntity> cmCreditRecords = this.queryByPage(queryParams);

            if (cmCreditRecords != null && cmCreditRecords.size() > 0) {
                CmCreditRecordEntity record = cmCreditRecords.get(0);
                //获取记录中添加的积分值
                Integer amount = record.getAmount();

                CmUserEntity userEntity = cmUserDao.getById(record.getUserId());
                //根据记录中获取积分的userId获取用户当前积分
                Integer credits = userEntity.getCredits();

                if (ruleId == CmConstant.CREDITS_RULE_BROKER_COMMENT) {
                    ruleId = CmConstant.CREDITS_RULE_BROKER_COMMENT_REMOVE;
                } else if (ruleId == CmConstant.CREDITS_RULE_HOUSE_COMMENT) {
                    ruleId = CmConstant.CREDITS_RULE_HOUSE_COMMENT_REMOVE;
                }

                CmCreditRuleEntity ruleEntity = cmCreditRuleDao.getById(ruleId);

                if (ruleEntity != null) {
                    record.setId(null);

                    record.setRuleId(ruleEntity.getId());
                    record.setRuleName(ruleEntity.getCreditRuleName());

                    record.setHappenTime(new Date());

                    record.setRemainingAmount(credits - amount);

                    this.save(record);
                }

                //修改user积分数
                userEntity.setCredits(credits - amount);

                cmUserDao.update(userEntity);
                cmUserService.clearUserCache(userEntity.getUserId());
            }
            return 1;
        } catch (Exception ex) {
            ex.printStackTrace();
            return 0;
        }
    }

    @Override
    public Integer statisticsByPageCount(QueryParams<CmCreditRecordEntity> queryParams) {
        Object obj = getObject(getStatement(), queryParams);
        if (obj == null) {
            return 0;
        }
        return Integer.parseInt(obj.toString());
    }

    @Override
    public List<CmCreditRecordEntity> statisticsByPage(QueryParams<?> queryParams) {
        Object count = this.getReadTemplate().queryForList(getStatement(), queryParams);
        return (List<CmCreditRecordEntity>) (count);
    }

    @Override
    public List<CmCreditRecordEntity> queryByPageNew(QueryParams<?> params) {

        if (params != null && params.getPaging() != null) {
            int records = queryCount(getStatement(), params);

            // 如果查询出符合条件的记录数为0，那么就直接返回一个空的List，因为后面的已经没有执行的必要
            if (records == 0) {
                return new ArrayList<>(0);
            }

            params.getPaging().setRecords(records);
        }

        Object count = this.getReadTemplate().queryForList(getStatement(), params);
        return (List<CmCreditRecordEntity>) (count);
    }

    @Override
    public Integer getUserInviteCount(QueryParams<CmCreditRecordEntity> params) {
        return queryCount(getStatement(), params);
    }

    /**
     * 获取条件内用户数（不重复）
     */
    @SuppressWarnings("deprecation")
    @Override
    public Integer getDistinctUserCount(QueryParams<CmCreditRecordEntity> queryParams) {
        Object obj = getObject(getStatement(), queryParams);
        if (obj == null) {
            return 0;
        }
        return Integer.parseInt(obj.toString());
    }

    /**
     * 获取条件内积分总和
     */
    @SuppressWarnings("deprecation")
    @Override
    public Integer getTotalCreditsByCondition(QueryParams<CmCreditRecordEntity> queryParams) {
        Object obj = getObject(getStatement(), queryParams);
        if (obj == null) {
            return 0;
        }
        return Integer.parseInt(obj.toString());
    }


}
