package com.liquidnet.service.stone.service.impl;

import com.github.pagehelper.PageInfo;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.UserPathDto;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.stone.entity.StoneScoreLogs;
import com.liquidnet.service.stone.service.IStoneScoreLogsService;
import com.liquidnet.service.stone.util.ObjectUtils;
import com.liquidnet.service.stone.util.QueueUtils;
import com.liquidnet.service.stone.util.StoneMongoUtils;
import com.liquidnet.service.stone.util.StoneRedisUtils;
import com.liquidnet.service.stone.vo.StoneLogsListVo;
import com.liquidnet.service.stone.vo.StoneTaskVo;
import com.liquidnet.service.stone.vo.StoneUserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 积分日志表 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-10-19
 */
@Service
@Slf4j
public class StoneScoreLogsServiceImpl implements IStoneScoreLogsService {

    @Autowired
    StoneRedisUtils stoneRedisUtils;
    @Autowired
    StoneMongoUtils stoneMongoUtils;
    @Autowired
    QueueUtils queueUtils;
    private final static int dayMax = 300;
    private final static int monthMax = 1000;

    @Override
    public String deScore(String uid, Integer score, Integer TaskId, String reason) {
        if (score <= 0) {
            return "积分不能小于0";
        }
        if (TaskId == 2111) {
            changeUse(uid, score, reason, reason);
            return "成功";
        } else {
            changeUse(uid, score, "", reason);
            return "成功";
        }
    }

    @Override
    public String inScore(String uid, Integer score, Integer TaskId, String reason) {
        if (score <= 0) {
            return "积分不能小于0";
        }

        if (TaskId == 2111 && !reason.equals("历史积分")) {
            StoneUserVo vo = stoneRedisUtils.getUserData(uid);
            if (vo == null) {
                vo = StoneUserVo.getNew();
                vo.getTask();
                vo.setUid(uid);
                vo.setStatus(1);
                //redis
                stoneRedisUtils.setUserData(uid, vo);
                //mongo
                stoneMongoUtils.userCreate(vo);
                //mysql 创建用户积分表数据
                queueUtils.sendMsgByRedis(MQConst.StoneQueue.STONE_INSERT_USER.getKey(),
                        SqlMapping.get("stone_score_user.insert", IDGenerator.nextTimeId2(), vo.getUid(), vo.getStatus(), LocalDateTime.now())
                );
            }
            Date userMonth = DateUtil.parse(vo.getCurrentMonth() == null ? DateUtil.getNowTime() : vo.getCurrentMonth(), "yyyy-MM");
            int monthScore = vo.getMonthScore() == null ? 0 : vo.getMonthScore();
            if (DateUtil.compareMonth(userMonth, DateUtil.parse(DateUtil.getNowTime(), "yyyy-MM")) == 0) {//当月
                if ((monthScore + score) >= monthMax) {
                    score = monthMax - monthScore;
                }
            } else {
                if (score >= monthMax) {
                    score = monthMax;
                }
            }
//            Date userDay = DateUtil.parse(vo.getCurrentDay() == null ? DateUtil.getNowTime() : vo.getCurrentDay(), "yyyy-MM-dd");
//            int dayScore = vo.getDayScore() == null ? 0 : vo.getDayScore();
//            if (DateUtil.compareDay(userDay, DateUtil.parse(DateUtil.getNowTime(), "yyyy-MM-dd")) == 0) {//当日
//                if ((dayScore + score) >= dayMax) {
//                    score = dayMax - dayScore;
//                }
//            } else {
//                if (score >= dayMax) {
//                    score = dayMax;
//                }
//            }
            vo.setCurrentMonth(DateUtil.format(userMonth, DateUtil.Formatter.yyyyMMddHHmmss));
            vo.setMonthScore(monthScore + score);
            stoneRedisUtils.setUserData(uid, vo);
            if (score == 0) {
                return "成功";
            }
            changeRest(uid, score, reason, reason);
            return "成功";
        } else {
            changeRest(uid, score, "", reason);
            return "成功";
        }
    }

    @Override
    public ResponseDto<HashMap<String, Object>> doTask(Integer taskId, String uid) {
        if (uid == null) {
            uid = CurrentUtil.getCurrentUid();
        }
        StoneUserVo vo = stoneRedisUtils.getUserData(uid);
        if (vo == null) {
            vo = StoneUserVo.getNew();
            vo.getTask();
            vo.setUid(uid);
            vo.setStatus(1);
            //redis
            stoneRedisUtils.setUserData(uid, vo);
            //mongo
            stoneMongoUtils.userCreate(vo);
            //mysql 创建用户积分表数据
            queueUtils.sendMsgByRedis(MQConst.StoneQueue.STONE_INSERT_USER.getKey(),
                    SqlMapping.get("stone_score_user.insert", IDGenerator.nextTimeId2(), vo.getUid(), vo.getStatus(), LocalDateTime.now())
            );
        }
        List<StoneTaskVo> taskList = vo.getTask();
        boolean isIn = false; //标示是否操作
        //增加积分
        int score = 0;
        int count = 0;
        for (int i = 0; i < taskList.size(); i++) {
            StoneTaskVo item = taskList.get(i);
            //判断任务
            if (item.getTaskId().equals(taskId)) {
                if (item.getTaskType().equals(1) && item.getTaskTime().equals(DateUtil.getNowTime(DateUtil.DATE_SMALL_STR))) {
                    return ResponseDto.failure("今日已完成");
                } else if (item.getTaskType().equals(2) && item.getTaskCount() >= 1) {
                    return ResponseDto.failure("该任务已完成");
                } else {
                    //记录完成任务
                    if (taskId == 0) { //每日签到
                        if (DateUtil.intervalDays(DateUtil.parse(item.getTaskTime(), "yyyy-MM-dd"),
                                DateUtil.parse(DateUtil.getNowTime(), "yyyy-MM-dd")
                        ) == 1L) {//连续签到
                            if (item.getTaskCount() >= 7) {
                                item.setTaskCount(1);
                                score = item.getTaskCount();
                            } else {
                                item.setTaskCount(item.getTaskCount() + 1);
                                score = item.getTaskCount();
                            }
                        } else {//非连续签到
                            item.setTaskCount(1);
                            score = item.getTaskCount();
                        }
                    } else {//其他
                        switch (taskId) {
                            case 3:
                                score = 1;
                                break;
                            case 4:
                                score = 50;
                                break;
                            case 5:
                            case 6:
                            case 7:
                                score = 10;
                                break;
                            default:
                                score = 0;
                                break;
                        }
                        item.setTaskCount(1);
                    }
                    count = item.getTaskCount();
                    item.setTaskTime(DateUtil.getNowTime(DateUtil.DATE_SMALL_STR));
                    taskList.set(i, item);
                    vo.setTask(taskList);
                    //mongo
                    stoneMongoUtils.userUpdateByUid(vo);
                    //redis
                    stoneRedisUtils.setUserData(uid, vo);
                    //添加积分
                    inScore(uid, score, taskId, item.getTaskName());
                    isIn = true;
                    break;
                }
            }
        }
        if (isIn) {
            HashMap<String, Object> map = CollectionUtil.mapStringObject();
            map.put("score", score);
            map.put("count", count);
            return ResponseDto.success(map);
        } else {
            return ResponseDto.failure("任务不存在");
        }
    }

    @Override
    public ResponseDto<StoneUserVo> taskDetail() {
        String uid = CurrentUtil.getCurrentUid();
        StoneUserVo vo = stoneRedisUtils.getUserData(uid);
        List<StoneTaskVo> taskList = vo.getTask();
        for (int i = 0; i < taskList.size(); i++) {
            StoneTaskVo item = taskList.get(i);
            if (item.getTaskType().equals(1) && item.getTaskTime().equals(DateUtil.getNowTime(DateUtil.DATE_SMALL_STR))) {
                item.setIsFinish(1);
            } else if (item.getTaskType().equals(2) && item.getTaskCount() >= 1) {
                item.setIsFinish(1);
            } else {
                item.setIsFinish(0);
            }
            taskList.set(i, item);
        }
        vo.setTask(taskList);
        return ResponseDto.success(vo);
    }

    @Override
    public PageInfo<List<StoneLogsListVo>> logList(Integer page) {
        String uid = CurrentUtil.getCurrentUid();
        PageInfo<List<StoneLogsListVo>> mPageInfo;
        int size = 40;
        if (page == null || page == 1 || page == 0) {
            page = 1;
        }
        List<StoneScoreLogs> voList;
        long count;
        if (page == 1) {
            voList = stoneRedisUtils.getLogsList(uid);
            count = voList.size();
        } else {
            HashMap<String, Object> info = stoneMongoUtils.logList(uid, page, size);
            try {
                voList = (List<StoneScoreLogs>) info.get("data");
                count = (long) info.get("total");
            } catch (Exception e) {
                voList = new ArrayList();
                count = 0;
            }
        }
        List<StoneLogsListVo> returnVoList = ObjectUtils.getStoneLogsListVoArrayList();
        for (int i = 0; i < voList.size(); i++) {
            StoneScoreLogs vo = voList.get(i);
            StoneLogsListVo returnVo = StoneLogsListVo.getNew().copy(vo);
            returnVoList.add(returnVo);
        }
        mPageInfo = new PageInfo(returnVoList);
        mPageInfo.setTotal(count);
        log.info(UserPathDto.setData("积分日志列表", "", voList));
        return mPageInfo;
    }

    private void changeRest(String uid, Integer score, String reason, String content) {
        //redis
        stoneRedisUtils.changeUserScoreRest(uid, score);
        //mongo
        StoneScoreLogs logs = new StoneScoreLogs();
        logs.setLogsId(IDGenerator.nextTimeId2());
        logs.setContent(content);
        logs.setReason(reason);
        logs.setUid(uid);
        logs.setScore(BigDecimal.valueOf(score));
        logs.setCreatedAt(LocalDateTime.now());
        stoneMongoUtils.logCreate(logs);
        stoneRedisUtils.addLogsList(uid,logs);
        //mysql 入库 积分日志
        queueUtils.sendMsgByRedis(MQConst.StoneQueue.STONE_INSERT_LOGS.getKey(),
                SqlMapping.get("stone_score_logs.insert", logs.getLogsId(), logs.getUid(), logs.getScore(), logs.getContent(), logs.getReason(), getOverdueAt(), LocalDateTime.now())
        );
    }

    private void changeUse(String uid, Integer score, String reason, String content) {
        //redis
        stoneRedisUtils.changeUserScoreUse(uid, score);
        stoneRedisUtils.changeUserScoreRest(uid, -score);
        //mongo
        StoneScoreLogs logs = new StoneScoreLogs();
        logs.setLogsId(IDGenerator.nextTimeId2());
        logs.setContent(content);
        logs.setReason(reason);
        logs.setUid(uid);
        logs.setScore(BigDecimal.valueOf(score).negate());
        logs.setCreatedAt(LocalDateTime.now());
        stoneMongoUtils.logCreate(logs);
        stoneRedisUtils.addLogsList(uid,logs);
        //mysql 入库 积分日志
        queueUtils.sendMsgByRedis(MQConst.StoneQueue.STONE_INSERT_LOGS.getKey(),
                SqlMapping.get("stone_score_logs.insert", logs.getLogsId(), logs.getUid(), logs.getScore(), logs.getContent(), logs.getReason(), getOverdueAt(), LocalDateTime.now())
        );
    }

    /**
     * 获取 积分过期时间
     * @return
     */
    private LocalDateTime getOverdueAt() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime overdueAt = LocalDateTime.of(now.getYear(), 10, 27, 0, 0, 0);
        if (now.isAfter(overdueAt)) {
            overdueAt = LocalDateTime.of(now.getYear() + 1, 12, 27, 0, 0, 0);
        } else {
            overdueAt = LocalDateTime.of(now.getYear(), 12, 27, 0, 0, 0);
        }
        return overdueAt;
    }
}
