package com.sqx.modules.userSign.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sqx.common.exception.SqxException;
import com.sqx.modules.app.dao.UserDao;
import com.sqx.modules.app.dao.UserMoneyDetailsDao;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.entity.UserMoneyDetails;
import com.sqx.modules.common.dao.CommonInfoDao;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.userSign.dao.UserSignRecordDao;
import com.sqx.modules.userSign.dto.UserSignDTO;
import com.sqx.modules.userSign.dto.UserSignRecordDTO;
import com.sqx.modules.userSign.entity.UserSignRecord;
import com.sqx.modules.userSign.service.UserSignRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserSignRecordServiceImpl extends ServiceImpl<UserSignRecordDao, UserSignRecord> implements UserSignRecordService {


    @Autowired
    private CommonInfoDao commonInfoDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserMoneyDetailsDao userMoneyDetailsDao;

    @Override
    public UserSignDTO getUserSignData(long userId) {
        UserEntity currentUser = userDao.selectById(userId);
        UserSignDTO dto = new UserSignDTO();
        dto.setUserId(currentUser.getUserId());
        dto.setUsername(currentUser.getUserName());
        dto.setMobile(currentUser.getPhone());
        dto.setSignDays(0);
        dto.setEnable(1);
        dto.setIsReceived(0);
        CommonInfo config = commonInfoDao.findOne(918);
        if (config == null) {
            throw new SqxException("签到活动配置不存在");
        }
        // 活动天数
        int activeDays = Convert.toInt(config.getValue().split(",")[0]);
        // 当前日期
        LocalDate beginDay = LocalDate.now();
        // 签到记录
        List<UserSignRecordDTO> recordList = new ArrayList<>();
        // 连续签到日期
        List<String> flowDays = buildFlowDays(beginDay, activeDays);
        // 实际签到记录
        List<UserSignRecord> list = baseMapper.selectList(Wrappers.<UserSignRecord>lambdaQuery().eq(UserSignRecord::getUserId, currentUser.getUserId()).orderByAsc(UserSignRecord::getSignDay).orderByAsc(UserSignRecord::getCreateTime).orderByAsc(UserSignRecord::getId));
        // 第x天
        int index = 1;
        // 连续签到天数
        int signDays = 0;
        if (CollUtil.isEmpty(list)) {
            for (String day : flowDays) {
                UserSignRecordDTO record = new UserSignRecordDTO();
                record.setSignDay(day);
                record.setStatus("0");
                record.setShowText(StrUtil.format("第{}天", index));
                record.setSignDate("");
                recordList.add(record);
                index++;
            }
            dto.setRecordList(recordList);
            dto.setSignDays(signDays);
            return dto;
        }
        LocalDate beginSignDay = LocalDate.parse(list.get(0).getSignDay(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //LocalDate endDay = LocalDate.parse(list.get(list.size() - 1).getSignDay(), DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(activeDays);
        LocalDate endDay = LocalDate.now().plusDays(activeDays - 1);
        flowDays = buildFlowDays(beginSignDay, endDay);
        // 需要移除的记录
        List<UserSignRecordDTO> removeList = new ArrayList<>();
        Map<String, Date> signMap = list.stream().collect(Collectors.toMap(UserSignRecord::getSignDay, UserSignRecord::getCreateTime));
        for (String day : flowDays) {
            Date date = signMap.get(day);
            UserSignRecordDTO record = new UserSignRecordDTO();
            if (date != null) {
                String signDay = DateUtil.formatDateTime(signMap.get(day));
                record.setSignDay(day);
                record.setStatus("1");
                record.setSignDate(signDay);
                record.setShowText("已签到");
                signDays++;
            } else {
                record.setSignDay(day);
                record.setStatus("0");
                record.setSignDate("");
                LocalDate thisDay = LocalDate.parse(day);
                LocalDate currentDay = LocalDate.now();
                long daysBetween = ChronoUnit.DAYS.between(thisDay, currentDay);
                if (daysBetween > 0) {
                    signDays = 0;
                    record.setShowText("未签到");
                } else if (daysBetween == 0) {
                    record.setShowText("待签到");
                } else {
                    record.setShowText("第{}天");
                }
            }
            recordList.add(record);
            if (signDays == activeDays) {
                break;
            }
            if (LocalDate.parse(record.getSignDay(), DateTimeFormatter.ofPattern("yyyy-MM-dd")).isEqual(endDay)) {
                List<UserSignRecordDTO> tempList = CollUtil.reverseNew(recordList);
                Long isInclude = tempList.stream().filter(item -> DateUtil.today().equals(item.getSignDay()) && "1".equals(item.getStatus())).collect(Collectors.counting());
                int removeSize = signDays;
                if (isInclude > 0){
                    removeSize = signDays - 1;
                }
                for (int i = 0; i < removeSize; i++) {
                    removeList.add(tempList.get(i));
                }
                break;
            }
        }
        recordList.removeAll(removeList);
        Collections.reverse(recordList);
        recordList = recordList.stream().limit(activeDays).collect(Collectors.toList());
        Collections.reverse(recordList);
        index = 1;
        for (UserSignRecordDTO record : recordList) {
            record.setShowText(StrUtil.format(record.getShowText(), index));
            index++;
        }
        dto.setRecordList(recordList);
        dto.setSignDays(signDays);
        // 该用户是否可以继续签到
        if (signDays >= activeDays) {
            dto.setEnable(0);
        }
        int count = userMoneyDetailsDao.selectCount(
                Wrappers.<UserMoneyDetails>lambdaQuery()
                        .eq(UserMoneyDetails::getUserId, userId)
                        .eq(UserMoneyDetails::getType, 1)
                        .eq(UserMoneyDetails::getClassify, 7)
                        .eq(UserMoneyDetails::getMoneyType, 1)
                        .likeLeft(UserMoneyDetails::getTitle, "[连续签到")
                        .likeRight(UserMoneyDetails::getTitle, "天]")
        );
        if (count > 0) {
            dto.setIsReceived(1);
        } else {
            dto.setIsReceived(0);
        }
        return dto;
    }

    @Override
    public int getUserSignCount(long userId) {
        QueryWrapper<UserSignRecord> signWrapper = new QueryWrapper<>();
        signWrapper.eq("user_id", userId);
        signWrapper.gt("sign_day", DateUtil.format(new Date(), "yyyy-MM") + "-00");
        signWrapper.orderByAsc("create_time");
        int signCount = baseMapper.selectCount(signWrapper);
        return signCount;
    }

    @Override
    public Map<Long, Integer> getTaskWCount(long userId, int wCount) {
        Date thirtyDaysAgo = DateUtil.offsetDay(new Date(), -30);
        List<Long> noRecordTasks = baseMapper.getNoRecordTask(userId, DateUtil.format(thirtyDaysAgo, "yyyy-MM-dd") + " 00:00:00");
        List<UserSignRecord> taskWCount = baseMapper.getTaskWCount(userId, wCount, DateUtil.format(thirtyDaysAgo, "yyyy-MM-dd") + " 00:00:00", noRecordTasks);
        Map<Long, Integer> map = taskWCount.stream()
                .collect(Collectors.groupingBy(
                        UserSignRecord::getId,
                        Collectors.summingInt(UserSignRecord::getDay)
                ));
        return map;
    }

    @Override
    public Integer getWSignCount(long userId) {
        return baseMapper.getWSignCount(userId, DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd") + " 00:00:00");
    }

    @Override
    public String[] getUserSignAwardConfig() {
        CommonInfo config = commonInfoDao.findOne(918);
        if (config == null) {
            throw new SqxException("签到活动配置不存在");
        }
        return config.getValue().split(",");
    }

    private List<String> buildFlowDays(LocalDate beginDay, int activeDays) {
        List<String> flowDays = new ArrayList<>();
        for (int i = 0; i < activeDays; i++) {
            flowDays.add(beginDay.plusDays(i).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        }
        return flowDays;
    }

    private List<String> buildFlowDays(LocalDate beginDay, LocalDate endDay) {
        List<String> flowDays = new ArrayList<>();
        LocalDate tempDay = beginDay;
        flowDays.add(tempDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        while (true) {
            if (tempDay.isEqual(endDay)) {
                break;
            }
            tempDay = tempDay.plusDays(1);
            flowDays.add(tempDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        }
        return flowDays;
    }
}

