package com.cirle.scientific.service.impl;

import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.cirle.scientific.constants.UserInfoConsts;
import com.cirle.scientific.dao.MemberDao;
import com.cirle.scientific.dao.QkjMemberTaskDao;
import com.cirle.scientific.dao.QkjMemberTaskDetailDao;
import com.cirle.scientific.dao.QkjMemberTaskInfoDao;
import com.cirle.scientific.dto.DaliyCheckInDTO;
import com.cirle.scientific.dto.QkjMemberTaskDetailDto;
import com.cirle.scientific.dto.QkjMemberTaskInfoDto;
import com.cirle.scientific.po.*;
import com.cirle.scientific.pojo.BizCodeEnum;
import com.cirle.scientific.pojo.Result;
import com.cirle.scientific.service.QkjTaskService;
import com.cirle.scientific.utils.CopyUtil;
import com.cirle.scientific.utils.page.PageBean;
import com.cirle.scientific.utils.page.Param;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
@Transactional
public class QkjTaskServiceImpl implements QkjTaskService {

    @Autowired
    QkjMemberTaskDao qkjMemberTaskDao;
    @Autowired
    QkjMemberTaskInfoDao qkjMemberTaskInfoDao;
    @Autowired
    QkjMemberTaskDetailDao qkjMemberTaskDetailDao;
    @Autowired
    MemberDao memberDao;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public Result dailyCheckInQd(String memCard, Integer taskId,  Integer dayPoints) throws ParseException {

        List<DaliyCheckInDTO> sign = sign(memCard);
        for (DaliyCheckInDTO daliyCheckInDTO : sign) {
            if (daliyCheckInDTO.getIsCuur() == 1) {
                if (daliyCheckInDTO.getIsTodayChenckIn() == 1) {
                    return Result.failed(BizCodeEnum.SIGN_NOT_IN);
                }
            }
        }

        QkjMemberTask task = qkjMemberTaskDao.findById(taskId.longValue()).get();
        QkjMemberTaskInfo info = qkjMemberTaskInfoDao.findByMemCard(memCard);

        if(task != null && task.getTaskStatus() == 0){
            QkjMemberTaskDetail detail = new QkjMemberTaskDetail();
            detail.setPoints(dayPoints);
            detail.setCompleteTime(Calendar.getInstance());
            detail.setIsReceive(1);
            detail.setMemCard(memCard);
            detail.setTaskId(task.getId().intValue());
            detail.setTaskTargetNum(task.getTaskTargetNum());
            detail.setTaskType(task.getTaskType());
            detail.setType(0);
            detail.setChangeType(1);
            qkjMemberTaskDetailDao.save(detail);
            info.setMemUnconpleteTaskNum(info.getMemUnconpleteTaskNum() -1);

            info.setMemTotalPoints(info.getMemTotalPoints() + dayPoints);
            info.setMemResidualPoints(info.getMemResidualPoints() + dayPoints);
            info = qkjMemberTaskInfoDao.save(info);

            return Result.success("2");
        }
        return Result.success("1");
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public Result dailyCheckIn(String memCard, Integer taskId,Integer dayPoints) {
        // TODO Auto-generated method stub
        QkjMemberTask task = qkjMemberTaskDao.findById(taskId.longValue()).get();
        QkjMemberTaskInfo info = qkjMemberTaskInfoDao.findByMemCard(memCard);

        if(task != null && task.getTaskStatus() == 0){
            List<QkjMemberTaskDetail> details = null;
            //已完成任务不再增加积分
            if(task.getTaskType() == 2){
                details = qkjMemberTaskDetailDao.findMemberAndTaskId(memCard, taskId);
                if(details != null && details.size() > 0){
                    return Result.success("1");
                }
            }else{
                if(details != null && details.size() >= task.getTaskTargetNum()){
                    return Result.success("1");
                }
            }
            if(taskId != 18){
                dayPoints = task.getTaskPoints();
            }

            QkjMemberTaskDetail detail = new QkjMemberTaskDetail();
            detail.setPoints(dayPoints);
            detail.setCompleteTime(Calendar.getInstance());
            detail.setIsReceive(1);
            detail.setMemCard(memCard);
            detail.setTaskId(task.getId().intValue());
            detail.setTaskTargetNum(task.getTaskTargetNum());
            detail.setTaskType(task.getTaskType());
            detail.setType(0);
            detail.setChangeType(1);
            qkjMemberTaskDetailDao.save(detail);
            info.setMemUnconpleteTaskNum(info.getMemUnconpleteTaskNum() -1);

            info.setMemTotalPoints(info.getMemTotalPoints() + dayPoints);
            info.setMemResidualPoints(info.getMemResidualPoints() + dayPoints);
            info = qkjMemberTaskInfoDao.save(info);

            return Result.success("2");
        }
        return Result.success("1");
    }

    @Override
    public Result findUserTaskInfo(String memCard) {
        List<Object[]> userTaskInfo = qkjMemberTaskDetailDao.findUserTaskInfo(memCard);
        List<QkjMemberTaskDetailDto> collect = userTaskInfo.stream().map(item -> {
            QkjMemberTaskDetailDto qkjMemberTaskDetailDto = new QkjMemberTaskDetailDto();
            if (StringUtils.isNotBlank(item[0] + "") && !"null".equals(item[0] + "")) {
                qkjMemberTaskDetailDto.setTaskDesc(item[0] + "");
            } else {
                qkjMemberTaskDetailDto.setTaskDesc("积分兑换");
            }
            qkjMemberTaskDetailDto.setPoints((Integer) item[1]);
            qkjMemberTaskDetailDto.setChangeType((Integer) item[2]);
            if (item[3] != null) {
                qkjMemberTaskDetailDto.setCompleteTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) item[3]));
            }
            return qkjMemberTaskDetailDto;
        }).collect(Collectors.toList());
        return Result.success(collect);
    }

    /**
     * 判断今日是否已完成任务，如果未完成返回任务信息，已完成返回null
     * @param memCard
     * @param taskId
     * @return
     */
    @Override
    public QkjMemberTask judeFinishTask(String memCard, Integer taskId){
        QkjMemberTask task = qkjMemberTaskDao.findById(taskId.longValue()).get();
        if(task != null && task.getTaskStatus() == 0){
            List<QkjMemberTaskDetail> details = null;
            //已完成任务不再增加积分
            if(task.getTaskType() == 2){
                details = qkjMemberTaskDetailDao.findMemberAndTaskId(memCard, taskId);
                if(details != null && details.size() > 0){
                    return null;
                }
            }else{
                details = qkjMemberTaskDetailDao.findDailyTask(memCard, taskId);
                if(details != null && details.size() >= task.getTaskTargetNum()){
                    return null;
                }
            }
            return task;
        }
        return null;
    }

    @Override
    public Result findUserTaskList(String memCard) {
        List<QkjMemberTask> list =  qkjMemberTaskDao.findUserTaskList();
        return Result.success(list);
    }
    @Override
    public Result findUserjfRanking(String memCard) {
        List<QkjMemberTaskInfo> list = qkjMemberTaskInfoDao.findUserjfRankingNew();
        List<String> memCardList = list.stream().map(QkjMemberTaskInfo::getMemCard).collect(Collectors.toList());
        List<QkjMember> members = memberDao.findAllBymemCards(memCardList);
        Map<String, QkjMember> idToObjectMap = members.stream().collect(Collectors.toMap(QkjMember::getMemCard, item -> item));
        List<QkjMemberTaskInfoDto> collect = list.stream().map(item -> {
            QkjMemberTaskInfoDto qkjMemberTaskInfoDto = CopyUtil.copy(item, QkjMemberTaskInfoDto.class);
            QkjMember qkjMember = idToObjectMap.get(item.getMemCard());
            if (qkjMember != null) {
                qkjMemberTaskInfoDto.setUserName(qkjMember.getMemNickname());
                qkjMemberTaskInfoDto.setUserHeader(qkjMember.getMemHeadimg());
                qkjMemberTaskInfoDto.setMemRegisterTime(qkjMember.getMemRegisterTime());
            }
            return qkjMemberTaskInfoDto;
        }).collect(Collectors.toList());

        collect = collect.stream()
                .sorted(Comparator.comparing(QkjMemberTaskInfoDto::getMemResidualPoints, Comparator.reverseOrder()).thenComparing(QkjMemberTaskInfoDto::getMemRegisterTime))
                .collect(Collectors.toList());
        //对结果集进行处理过滤掉username为空的情 && 只取前50名
        List<QkjMemberTaskInfoDto> resultList = Lists.newArrayList();
        for (QkjMemberTaskInfoDto q : collect) {

            if (Objects.nonNull(q) && StringUtils.isNotBlank(q.getUserName())) {
                resultList.add(q);
            }
            if (resultList.size() == 50) {
                break;
            }
        }

        //排行榜头像显示规则 1显示上传头像2显示微信头像3显示默认头像
        for (QkjMemberTaskInfoDto qkjMemberTaskInfoDto : resultList) {
            if(StringUtils.isBlank(qkjMemberTaskInfoDto.getUserHeader())){
                qkjMemberTaskInfoDto.setUserHeader(UserInfoConsts.MEM_HEADIMG);
            }
        }
        return Result.success(resultList);
    }

    public List<DaliyCheckInDTO> sign(String memCard) throws ParseException {
        // 连续签到信息
        int curDay = 0;// 判断是否当天
        String time = "2019-09-17";
        // Calendar time=DateUtil.getCalendarByStr(timeStr);
        List<DaliyCheckInDTO> ins = new ArrayList<>();
        Calendar nowC = Calendar.getInstance();
        List<Object> checkIn = qkjMemberTaskDetailDao.sevenDayCheckIn(memCard, time);
        if (checkIn != null && checkIn.size() == 1) {
            Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(checkIn.get(0) + "");
            Timestamp t1 = new Timestamp(parse.getTime());
            Calendar time1 = Calendar.getInstance();
            time1.setTime(t1);
            if (time1.get(Calendar.DAY_OF_YEAR) == nowC.get(Calendar.DAY_OF_YEAR)
                    || nowC.get(Calendar.DAY_OF_YEAR) - time1.get(Calendar.DAY_OF_YEAR) == 1) {
                DaliyCheckInDTO in = new DaliyCheckInDTO();
                if (time1.get(Calendar.DAY_OF_YEAR) == nowC.get(Calendar.DAY_OF_YEAR)) {
                    in.setIsCuur(1);
                    curDay = 1;
                } else {
                    in.setIsCuur(0);
                }
                in.setDayCalendar(time1);
                in.setDayNum(1);
                in.setDayPoints(10);
                in.setIsTodayChenckIn(1);
                ins.add(in);
            }
        } else if (checkIn != null && checkIn.size() != 1 && checkIn.size() != 0) {
            Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(checkIn.get(checkIn.size() - 1) + "");
            Timestamp t3 = new Timestamp(parse.getTime());
            Calendar time3 = Calendar.getInstance();
            time3.setTime(t3);
            // 判断 最后签到是否是前一天或者当天 若都不是这两种情况 就可以判断为 当天为第一天了
            if (time3.get(Calendar.DAY_OF_YEAR) == nowC.get(Calendar.DAY_OF_YEAR)
                    || nowC.get(Calendar.DAY_OF_YEAR) - time3.get(Calendar.DAY_OF_YEAR) == 1) {
                for (int i = 1; i < checkIn.size(); i++) {
                    {
                        if (checkIn.get(i - 1) != null && checkIn.get(i) != null) {
                            Date p = new SimpleDateFormat("yyyy-MM-dd").parse(checkIn.get(i - 1) + "");
                            Timestamp t1 = new Timestamp(p.getTime());
                            Calendar time1 = Calendar.getInstance();
                            time1.setTime(t1);
                            Integer day1 = time1.get(Calendar.DAY_OF_YEAR);

                            Date tp2 = new SimpleDateFormat("yyyy-MM-dd").parse(checkIn.get(i) + "");
                            Timestamp t2 = new Timestamp(tp2.getTime());
                            Calendar time2 = Calendar.getInstance();
                            time2.setTime(t2);
                            Integer day2 = time2.get(Calendar.DAY_OF_YEAR);
                            if (day2 - day1 != 1) {
                                ins = new ArrayList<>();
                                DaliyCheckInDTO in = new DaliyCheckInDTO();
                                if (time2.get(Calendar.DAY_OF_YEAR) == nowC.get(Calendar.DAY_OF_YEAR)) {
                                    in.setIsCuur(1);
                                    curDay = 1;
                                } else {
                                    in.setIsCuur(0);
                                }
                                in.setDayCalendar(time2);
                                in.setDayNum(1);
                                in.setDayPoints(10);
                                in.setIsTodayChenckIn(1);
                                ins.add(in);
                            } else {
                                if (i == 1) {
                                    DaliyCheckInDTO in = new DaliyCheckInDTO();
                                    in.setDayCalendar(time1);
                                    in.setDayNum(i);
                                    in.setDayPoints(i * 10);
                                    in.setIsTodayChenckIn(1);
                                    if (time1.get(Calendar.DAY_OF_YEAR) == nowC.get(Calendar.DAY_OF_YEAR)) {
                                        in.setIsCuur(1);
                                        curDay = 1;
                                    } else {
                                        in.setIsCuur(0);
                                    }
                                    ins.add(in);

                                    in = new DaliyCheckInDTO();
                                    in.setDayCalendar(time2);
                                    in.setDayNum(i + 1);
                                    in.setDayPoints((i + 1) * 10);
                                    in.setIsTodayChenckIn(1);
                                    if (time2.get(Calendar.DAY_OF_YEAR) == nowC.get(Calendar.DAY_OF_YEAR)) {
                                        in.setIsCuur(1);
                                        curDay = 1;
                                    } else {
                                        in.setIsCuur(0);
                                    }
                                    ins.add(in);
                                } else {
                                    DaliyCheckInDTO in = new DaliyCheckInDTO();
                                    in.setDayCalendar(time2);
                                    in.setDayNum(ins.size() + 1);
                                    in.setDayPoints((ins.size() + 1) * 10);
                                    in.setIsTodayChenckIn(1);
                                    if (time2.get(Calendar.DAY_OF_YEAR) == nowC.get(Calendar.DAY_OF_YEAR)) {
                                        in.setIsCuur(1);
                                        curDay = 1;
                                    } else {
                                        in.setIsCuur(0);
                                    }
                                    ins.add(in);
                                }
                            }
                        }
                    }
                }
            }

        }
        List<Object> checkInEn = qkjMemberTaskDetailDao.sevenDayCheckInEn(memCard, time);
        if (ins.size() == 0) {
            DaliyCheckInDTO in = new DaliyCheckInDTO();
            in.setDayCalendar(Calendar.getInstance());
            in.setDayNum(1);
            in.setDayPoints(10);
            in.setIsTodayChenckIn(0);
            in.setIsCuur(1);
            curDay = 1;
            ins.add(in);
        } else if (ins.size() == 6 && checkInEn.size() == 7) {
            // 当天没有签到
            // 获取前七天的签到 得到 连续签到6天
            // 获取前八天的签到 得到 连续签到7天
            // 这种情况下 连续签到的6天里面
            // 若又积分为10的 若有从10积分那一天为第一天
            // 若没有 就从当天为第一天

            List<Object> checkInFir = qkjMemberTaskDetailDao.sevenDayCheckInFirst(memCard, time);
            if (checkInFir == null || checkInFir.size() == 0) {
                ins = new ArrayList<>();
                DaliyCheckInDTO in = new DaliyCheckInDTO();
                in.setDayCalendar(Calendar.getInstance());
                in.setDayNum(1);
                in.setDayPoints(10);
                in.setIsTodayChenckIn(0);
                in.setIsCuur(1);
                curDay = 1;
                ins.add(in);
            } else {
                // 判断连续签到记录里面 是否有 第一天标识（积分为10）
                int numNew = 0;
                Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(checkInFir.get(checkInFir.size() - 1) + "");
                Timestamp t1 = new Timestamp(parse.getTime());
                Calendar time1 = Calendar.getInstance();
                time1.setTime(t1);
                Integer day1 = time1.get(Calendar.DAY_OF_YEAR);
                List<DaliyCheckInDTO> insNew = new ArrayList<>();
                for (int i = 0; i < ins.size(); i++) {
                    Integer day = ins.get(i).getDayCalendar().get(Calendar.DAY_OF_YEAR);
                    if (day >= day1) {
                        numNew++;
                        ins.get(i).setDayPoints(numNew * 10);
                        ins.get(i).setDayNum(numNew);
                        insNew.add(ins.get(i));
                        if (ins.get(i).getIsCuur() == 1) {
                        }
                    }
                }
                if (insNew != null && insNew.size() != 0) {
                    ins = new ArrayList<>();
                    for (int i = 0; i < insNew.size(); i++) {
                        ins.add(insNew.get(i));
                    }
                }
            }
        } else if (ins.size() == 7 && checkInEn.size() == 8) {
            // 当天已经签到
            // 获取前七天的签到 得到 连续签到7天
            // 获取前八天的签到 得到 连续签到8天
            // 这种情况
            // 这种情况下 连续签到的7天里面
            // 若有积分为10的 若有从10积分那一天为第一天
            // 若没有 就从当天为第一天

            List<Object> checkInFir = qkjMemberTaskDetailDao.sevenDayCheckInFirst(memCard, time);
            if (checkInFir == null || checkInFir.size() == 0) {
                Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(checkInEn.get(checkInEn.size() - 1) + "");
                Timestamp tbefore = new Timestamp(parse.getTime());
                Calendar timebefore = Calendar.getInstance();
                timebefore.setTime(tbefore);

                ins = new ArrayList<>();
                DaliyCheckInDTO in = new DaliyCheckInDTO();
                in.setDayCalendar(timebefore);
                in.setDayNum(1);
                in.setDayPoints(10);
                in.setIsTodayChenckIn(1);
                in.setIsCuur(1);
                curDay = 1;
                ins.add(in);
            } else {
                // 判断连续签到记录里面 是否有 第一天标识（积分为10）
                int numNew = 0;
                Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(checkInFir.get(checkInFir.size() - 1) + "");
                Timestamp t1 = new Timestamp(parse.getTime());
                Calendar time1 = Calendar.getInstance();
                time1.setTime(t1);
                Integer day1 = time1.get(Calendar.DAY_OF_YEAR);
                List<DaliyCheckInDTO> insNew = new ArrayList<>();
                for (int i = 0; i < ins.size(); i++) {
                    Integer day = ins.get(i).getDayCalendar().get(Calendar.DAY_OF_YEAR);
                    if (day >= day1) {
                        numNew++;
                        ins.get(i).setDayPoints(numNew * 10);
                        ins.get(i).setDayNum(numNew);
                        insNew.add(ins.get(i));
                        if (ins.get(i).getIsCuur() == 1) {
                        }
                    }
                }
                if (insNew != null && insNew.size() != 0) {
                    ins = new ArrayList<>();
                    for (int i = 0; i < insNew.size(); i++) {
                        ins.add(insNew.get(i));
                    }
                }
            }
        }
        Integer size = ins.size();
        if (size < 7) {
            for (int j = 0; j < 7 - size; j++) {
                DaliyCheckInDTO in = new DaliyCheckInDTO();
                DaliyCheckInDTO last = ins.get(ins.size() - 1);
                if (j == 0 && curDay == 0) {
                    in.setIsCuur(1);
                } else {
                    in.setIsCuur(0);
                }
                Calendar nextTime = last.getDayCalendar();
                nextTime.add(Calendar.DAY_OF_YEAR, 1);
                in.setDayCalendar(nextTime);
                in.setDayNum(last.getDayNum() + 1);
                in.setDayPoints((last.getDayNum() + 1) * 10);
                in.setIsTodayChenckIn(0);
                ins.add(in);
            }
        }
        return ins;
    }
}
