package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import shop.alien.entity.store.*;
import shop.alien.entity.store.vo.ActivityPeriodVo;
import shop.alien.entity.store.vo.ActivityPointInfoVo;
import shop.alien.entity.store.vo.SignInVo;
import shop.alien.entity.store.vo.UserSignInRecordVo;
import shop.alien.mapper.ActivityPeriodMapper;
import shop.alien.mapper.ActivitySignInConfigMapper;
import shop.alien.mapper.ActivitySignRewardMapper;
import shop.alien.mapper.UserSignInRecordMapper;
import shop.alien.mapper.system.SignInActivityMapper;
import shop.alien.store.service.SignInService;
import shop.alien.store.service.UserPointService;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * 签到类型活动服务
 * @author zhangchen
 * @since 2025-9-8
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SignInServiceImpl extends ServiceImpl<UserSignInRecordMapper, UserSignInRecord> implements SignInService {

    private final ActivitySignInConfigMapper activitySignInConfigMapper;
    private final ActivitySignRewardMapper activitySignRewardMapper;
    private final ActivityPeriodMapper activityPeriodMapper;
    private final UserSignInRecordMapper userSignInRecordMapper;
    private final SignInActivityMapper signInActivityMapper;
    private final UserPointService userPointService;

    @Override
    public UserSignInRecordVo signIn(int userId) {

        UserSignInRecordVo userSignInRecordVo = new UserSignInRecordVo();

        // 查询特殊方案活动
        List<ActivityPeriodVo> activityPeriodVoList = activityPeriodMapper.getCurrentActivityPeriodList();

        // 查询默认方案活动
        LambdaQueryWrapper<ActivitySignInConfig> connomActivitySignInConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        connomActivitySignInConfigLambdaQueryWrapper.eq(ActivitySignInConfig::getDeleteFlag, 0);
        connomActivitySignInConfigLambdaQueryWrapper.eq(ActivitySignInConfig::getPlanConfigType, 1);
        ActivitySignInConfig commonActivitySignInConfig = activitySignInConfigMapper.selectOne(connomActivitySignInConfigLambdaQueryWrapper);
        if(commonActivitySignInConfig == null){
            // 默认方案为空
            return null;
        }


        // 检查是否已经签到
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate = simpleDateFormat.format(new Date());

        LambdaQueryWrapper<UserSignInRecord> userSignInRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userSignInRecordLambdaQueryWrapper.between(UserSignInRecord::getSignInDate, currentDate + " 00:00:00", currentDate + " 23:59:59");
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getDeleteFlag, 0);
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getUserId, userId);
        UserSignInRecord userSignInRecord =  userSignInRecordMapper.selectOne(userSignInRecordLambdaQueryWrapper);
        if(userSignInRecord != null){
            BeanUtils.copyProperties(userSignInRecord, userSignInRecordVo);
            return userSignInRecordVo;
        }

        // 计算连续签到天数
        int continueDay = calculateContinuousDays(userId, 1);
        // 计算总计连续签到天数
        int totalContinueDay = totalContinuousDays(userId, 1);
        totalContinueDay++;

        // 方案奖励
        Map<Integer, Integer> activityPoint = new HashMap<>();
        // 获取默认方案奖励
        int basePoints = commonActivitySignInConfig.getBasePoints();
        List<ActivityPointInfoVo> activityPointInfoVoList = new ArrayList<>();
        ActivityPointInfoVo activityPointInfoVo = new ActivityPointInfoVo();
        activityPointInfoVo.setPoint(basePoints);
        activityPointInfoVo.setPointInfo("今日签到奖励"+basePoints+"积分");
        activityPointInfoVoList.add(activityPointInfoVo);

        LambdaQueryWrapper<ActivitySignInReward> activitySignInRewardLambdaQueryWrapper = new LambdaQueryWrapper<>();
        activitySignInRewardLambdaQueryWrapper.eq(ActivitySignInReward::getDeleteFlag,0);
        activitySignInRewardLambdaQueryWrapper.eq(ActivitySignInReward::getActivityId, commonActivitySignInConfig.getId());
        List<ActivitySignInReward> activitySignInRewardList = activitySignRewardMapper.selectList(activitySignInRewardLambdaQueryWrapper);
        if(!CollectionUtils.isEmpty(activitySignInRewardList)){
            int maxNum = activitySignInRewardList.stream()
                    .map(ActivitySignInReward::getDayOfSequence)
                    .max(Comparator.naturalOrder())
                    .orElse(0);
            if(continueDay >= maxNum){
                continueDay = 1;
            } else {
                continueDay++;
            }
            Map<Integer, List<ActivitySignInReward>> groupActivitySignInReward = activitySignInRewardList.stream()
                    .collect(Collectors.groupingBy(ActivitySignInReward::getDayOfSequence));
            if(groupActivitySignInReward.containsKey(continueDay)){
                List<ActivitySignInReward> activitySignInRewards =  groupActivitySignInReward.get(continueDay);
                if(!CollectionUtils.isEmpty(activitySignInRewards)){
                    ActivitySignInReward activitySignInReward = activitySignInRewards.get(0);
                    basePoints = basePoints + activitySignInReward.getPoints();
                    if(activitySignInReward.getPoints() != 0){
                        ActivityPointInfoVo groupActivityPointInfoVo = new ActivityPointInfoVo();
                        groupActivityPointInfoVo.setPoint(activitySignInReward.getPoints());
                        groupActivityPointInfoVo.setPointInfo("已连续签到"+continueDay+"天奖励积分"+activitySignInReward.getPoints());
                        activityPointInfoVoList.add(groupActivityPointInfoVo);
                    }
                }
            }
        }
        activityPoint.put(commonActivitySignInConfig.getId(), basePoints);

        // 获取特殊方案奖励
        int specialPoints = 0;
        int specialContinueDay = 0;
        if(!CollectionUtils.isEmpty(activityPeriodVoList)){
            ActivityPeriod activityPeriod = activityPeriodVoList.get(0);
            int activityId =  activityPeriod.getActivityId();
            LambdaQueryWrapper<ActivitySignInReward> specialActivitySignInRewardLambdaQueryWrapper = new LambdaQueryWrapper<>();
            specialActivitySignInRewardLambdaQueryWrapper.eq(ActivitySignInReward::getDeleteFlag, 0);
            specialActivitySignInRewardLambdaQueryWrapper.eq(ActivitySignInReward::getActivityId, activityId);
            List<ActivitySignInReward> specialActivitySignInRewardList = activitySignRewardMapper.selectList(specialActivitySignInRewardLambdaQueryWrapper);

            // 计算特殊方案连续签到天数
            specialContinueDay = specialContinuousDays(userId, 1);
            if(!CollectionUtils.isEmpty(specialActivitySignInRewardList)){
                int maxNum = specialActivitySignInRewardList.stream()
                        .map(ActivitySignInReward::getDayOfSequence)
                        .max(Comparator.naturalOrder())
                        .orElse(0);
                if(specialContinueDay >= maxNum){
                    specialContinueDay = 1;
                } else {
                    specialContinueDay++;
                }

                Map<Integer, List<ActivitySignInReward>> groupSpecialActivitySignInReward = specialActivitySignInRewardList.stream()
                        .collect(Collectors.groupingBy(ActivitySignInReward::getDayOfSequence));
                if(groupSpecialActivitySignInReward.containsKey(continueDay)){
                    List<ActivitySignInReward> specialActivitySignInRewards =  groupSpecialActivitySignInReward.get(specialContinueDay);
                    if(!CollectionUtils.isEmpty(specialActivitySignInRewards)){
                        ActivitySignInReward specialActivitySignInReward = specialActivitySignInRewards.get(0);
                        specialPoints = specialPoints + specialActivitySignInReward.getPoints();
                        ActivityPointInfoVo specialActivityPointInfoVo = new ActivityPointInfoVo();
                        specialActivityPointInfoVo.setPoint(specialActivitySignInReward.getPoints());
                        specialActivityPointInfoVo.setPointInfo("福利日签到奖励积分"+specialActivitySignInReward.getPoints());
                        activityPointInfoVoList.add(specialActivityPointInfoVo);
                    }
                }
            }
            activityPoint.put(activityId, specialPoints);
        }

        LocalDateTime now = LocalDateTime.now();
        Date date = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());

        // 保存签到记录
        UserSignInRecord record = new UserSignInRecord();
        record.setSignInDate(date);
        record.setContinuousDays(continueDay);
        record.setTotalContinuousDays(totalContinueDay);
        record.setSpecialContinuousDays(specialContinueDay);
        record.setPointsObtained(basePoints + specialPoints);
        record.setUserId(userId);
        record.setDeleteFlag(0);
        userSignInRecordMapper.insert(record);
        userPointService.addPoint(userId, basePoints + specialPoints);
        if(!CollectionUtils.isEmpty(activityPoint)){
            activityPoint.forEach((key, value) -> {
                if(value == 0 ){
                    return;
                }
                SignInActivity signInActivity = new SignInActivity();
                signInActivity.setActivityId(key);
                signInActivity.setPoint(value);
                signInActivity.setUserSignInRecordId(record.getId());
                signInActivityMapper.insert(signInActivity);
            });
        }

        BeanUtils.copyProperties(record, userSignInRecordVo);
        userSignInRecordVo.setActivityPointInfoVoList(activityPointInfoVoList);
        return userSignInRecordVo;
    }

    @Override
    public ActivitySignInConfig getActivitySignInConfigInfo() {
        // 查询默认方案信息
        LambdaQueryWrapper<ActivitySignInConfig> activitySignInConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        activitySignInConfigLambdaQueryWrapper.eq(ActivitySignInConfig::getDeleteFlag, 0);
        activitySignInConfigLambdaQueryWrapper.eq(ActivitySignInConfig::getPlanConfigType, 1);
        activitySignInConfigLambdaQueryWrapper.eq(ActivitySignInConfig::getStatus, 1);
        return activitySignInConfigMapper.selectOne(activitySignInConfigLambdaQueryWrapper);
    }

    @Override
    public boolean checkSignInStatus(int userId) {
        // 获取当天时间段
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

        LambdaQueryWrapper<UserSignInRecord> userSignInRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userSignInRecordLambdaQueryWrapper.between(UserSignInRecord::getSignInDate, todayStart, todayEnd);
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getDeleteFlag, 0);
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getUserId, userId);
        UserSignInRecord userSignInRecord =  userSignInRecordMapper.selectOne(userSignInRecordLambdaQueryWrapper);
        return userSignInRecord != null;
    }

    @Override
    public SignInVo getUserSignInInfo(int userId, int num) {
        SignInVo signInVo = new SignInVo();
        // 获取累计获得积分
        int totalPoint = 0;
        LambdaQueryWrapper<UserSignInRecord> userSignInRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getUserId, userId);
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getDeleteFlag, 0);
        userSignInRecordLambdaQueryWrapper.orderByDesc(UserSignInRecord::getSignInDate);
        List<UserSignInRecord> userSignInRecordList =  userSignInRecordMapper.selectList(userSignInRecordLambdaQueryWrapper);
        UserSignInRecord lastUserSignInRecord = null;
        if(!CollectionUtils.isEmpty(userSignInRecordList)){
            totalPoint = userSignInRecordList.stream()
                    .mapToInt(UserSignInRecord::getPointsObtained)
                    .sum();
            lastUserSignInRecord = userSignInRecordList.get(0);
        }
        signInVo.setTotalPoint(totalPoint);

        // 获取连续签到天数
        int totalContinueDay = 1;
//        signInVo.setTotalContinueDay(continueDay);

        // 计算连续签到天数
        int countDay = 1;
        if(lastUserSignInRecord != null && lastUserSignInRecord.getSignInDate() != null){
            boolean isToday = isSameDay(lastUserSignInRecord.getSignInDate(),0);
            if(isToday){
                countDay = lastUserSignInRecord.getContinuousDays();
                totalContinueDay = lastUserSignInRecord.getTotalContinuousDays();
            } else{
                boolean isYestDay = isSameDay(lastUserSignInRecord.getSignInDate(),1);
                if(isYestDay){
                    countDay = lastUserSignInRecord.getContinuousDays() ;
                    totalContinueDay = lastUserSignInRecord.getTotalContinuousDays();
                } else{
                    countDay = 0;
                    totalContinueDay = 0;
                }
            }
        } else {
            countDay = 0;
            totalContinueDay = 0;
        }
        signInVo.setContinuousDays(countDay);
        signInVo.setTotalContinueDay(totalContinueDay);


        // 获取签到记录
//        LambdaQueryWrapper<UserSignInRecord> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(UserSignInRecord::getUserId, userId);
//        wrapper.eq(UserSignInRecord::getDeleteFlag, 0);
//        wrapper.orderByDesc(UserSignInRecord::getSignInDate);
//        wrapper.last("Limit " + num);
//        List<UserSignInRecord> userSignInRecords = userSignInRecordMapper.selectList(wrapper);
//        signInVo.setUserSignInRecordList(userSignInRecords);
        return signInVo;
    }

    @Override
    public IPage<UserSignInRecord> getUserSignInRecordList(int pageNum, int pageSize, int userId) {
        IPage<UserSignInRecord> iPage = new Page<>(pageNum, pageSize);
        // 获取签到记录
        LambdaQueryWrapper<UserSignInRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSignInRecord::getUserId, userId);
        wrapper.eq(UserSignInRecord::getDeleteFlag, 0);
        wrapper.orderByDesc(UserSignInRecord::getSignInDate);
        return userSignInRecordMapper.selectPage(iPage, wrapper);
    }

    /**
     * 计算连续签到天数
     */
    private int calculateContinuousDays(int userId, int dayCount) {
        LambdaQueryWrapper<UserSignInRecord> userSignInRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getDeleteFlag, 0);
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getUserId, userId);
        userSignInRecordLambdaQueryWrapper.orderByDesc(UserSignInRecord::getSignInDate);
        userSignInRecordLambdaQueryWrapper.last("Limit 1");
        List<UserSignInRecord> userSignInRecordList =  userSignInRecordMapper.selectList(userSignInRecordLambdaQueryWrapper);
        if(CollectionUtils.isEmpty(userSignInRecordList)){
            return 0;
        }
        UserSignInRecord userSignInRecord = userSignInRecordList.get(0);
        Date signInDate = userSignInRecord.getSignInDate();
        boolean result = isSameDay(signInDate, dayCount);
        if(result){
            return userSignInRecord.getContinuousDays();
        } else{
            return 0;
        }
    }

    /**
     * 计算总计连续签到天数
     */
    private int totalContinuousDays(int userId, int dayCount) {
        LambdaQueryWrapper<UserSignInRecord> userSignInRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getDeleteFlag, 0);
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getUserId, userId);
        userSignInRecordLambdaQueryWrapper.orderByDesc(UserSignInRecord::getSignInDate);
        userSignInRecordLambdaQueryWrapper.last("Limit 1");
        List<UserSignInRecord> userSignInRecordList =  userSignInRecordMapper.selectList(userSignInRecordLambdaQueryWrapper);
        if(CollectionUtils.isEmpty(userSignInRecordList)){
            return 0;
        }
        UserSignInRecord userSignInRecord = userSignInRecordList.get(0);
        Date signInDate = userSignInRecord.getSignInDate();
        boolean result = isSameDay(signInDate, dayCount);
        if(result){
            return userSignInRecord.getTotalContinuousDays();
        } else{
            return 0;
        }
    }

    /**
     * 计算特殊方案连续签到天数
     */
    private int specialContinuousDays(int userId, int dayCount) {
        LambdaQueryWrapper<UserSignInRecord> userSignInRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getDeleteFlag, 0);
        userSignInRecordLambdaQueryWrapper.eq(UserSignInRecord::getUserId, userId);
        userSignInRecordLambdaQueryWrapper.orderByDesc(UserSignInRecord::getSignInDate);
        userSignInRecordLambdaQueryWrapper.last("Limit 1");
        List<UserSignInRecord> userSignInRecordList =  userSignInRecordMapper.selectList(userSignInRecordLambdaQueryWrapper);
        if(CollectionUtils.isEmpty(userSignInRecordList)){
            return 0;
        }
        UserSignInRecord userSignInRecord = userSignInRecordList.get(0);
        Date signInDate = userSignInRecord.getSignInDate();
        boolean result = isSameDay(signInDate, dayCount);
        if(result){
            return userSignInRecord.getSpecialContinuousDays();
        } else{
            return 0;
        }
    }

    /**
     * 判断两个Date对象是否是同一天（Java 8+ 推荐）
     */
    public static boolean isSameDay(Date date, int dayCount) {
        if (date == null) {
            return false;
        }
        LocalDate localDate1 = date.toInstant()
                .atZone(java.time.ZoneId.systemDefault())
                .toLocalDate();
        LocalDate today = LocalDate.now();
        LocalDate localDate2 = today.minusDays(dayCount);
        return localDate1.isEqual(localDate2);
    }
}
