package cn.iocoder.yudao.module.member.service.activityuser;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.controller.admin.activityawardsuser.vo.ActivityAwardsUserCountVO;
import cn.iocoder.yudao.module.member.controller.admin.activityuser.vo.ActivityUserCountVO;
import cn.iocoder.yudao.module.member.controller.admin.activityuser.vo.ActivityUserPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.activityuser.vo.ActivityUserSaveReqVO;
import cn.iocoder.yudao.module.member.controller.app.activity.vo.AppActivityRespVO;
import cn.iocoder.yudao.module.member.controller.app.activity.vo.AppActivityUserRespVO;
import cn.iocoder.yudao.module.member.controller.app.activity.vo.AppUserApplyVO;
import cn.iocoder.yudao.module.member.dal.dataobject.activity.ActivityDO;
import cn.iocoder.yudao.module.member.dal.dataobject.activityuser.ActivityUserDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.activityuser.ActivityUserMapper;
import cn.iocoder.yudao.module.member.service.activity.ActivityService;
import cn.iocoder.yudao.module.member.service.activityawardsuser.ActivityAwardsUserService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;

/**
 * 活动参加人员 Service 实现类
 *
 * @author 我是秦俊旗
 */
@Service
@Validated
public class ActivityUserServiceImpl implements ActivityUserService {

    @Resource
    private ActivityUserMapper activityUserMapper;

    @Resource
    private ActivityService activityService;
    @Resource
    private ActivityAwardsUserService activityAwardsUserService;

    @Resource
    private MemberUserService memberService;

    @Override
    public Long createActivityUser(ActivityUserSaveReqVO createReqVO) {
        // 插入
        ActivityUserDO activityUser = BeanUtils.toBean(createReqVO, ActivityUserDO.class);
        activityUserMapper.insert(activityUser);
        // 返回
        return activityUser.getId();
    }

    @Override
    public void updateActivityUser(ActivityUserSaveReqVO updateReqVO) {
        // 校验存在
        validateActivityUserExists(updateReqVO.getId());
        // 更新
        ActivityUserDO updateObj = BeanUtils.toBean(updateReqVO, ActivityUserDO.class);
        activityUserMapper.updateById(updateObj);
    }

    @Override
    public void deleteActivityUser(Long id) {
        // 校验存在
        validateActivityUserExists(id);
        // 删除
        activityUserMapper.deleteById(id);
    }

    private void validateActivityUserExists(Long id) {
        if (activityUserMapper.selectById(id) == null) {
            throw exception(ACTIVITY_USER_NOT_EXISTS);
        }
    }

    @Override
    public ActivityUserDO getActivityUser(Long id) {
        return activityUserMapper.selectById(id);
    }

    @Override
    public PageResult<ActivityUserDO> getActivityUserPage(ActivityUserPageReqVO pageReqVO) {
        return activityUserMapper.selectPage(pageReqVO);
    }

    @Override
    public Map<Long, ActivityUserCountVO> countByActivityIds(List<Long> activityIds) {
        List<ActivityUserCountVO> activityUserCountVOS = activityUserMapper.countByActivityIds(activityIds);
        if (activityUserCountVOS.isEmpty()) {
            return Collections.emptyMap();
        }
        return activityUserCountVOS.stream().collect(Collectors.toMap(ActivityUserCountVO::getActivityId, v -> v));
    }

    @Override
    public List<Long> isApplyByActivityIds(List<Long> activityIds, Long userId) {

        List<ActivityUserDO> activityUserDOS = activityUserMapper.selectList(Wrappers.<ActivityUserDO>lambdaQuery()
                .in(ActivityUserDO::getActivityId, activityIds)
                .eq(ActivityUserDO::getUserId, userId));
        if (activityUserDOS.isEmpty()) {
            return Collections.emptyList();
        }

        return activityUserDOS.stream().map(ActivityUserDO::getActivityId).collect(Collectors.toList());
    }

    @Override
    public PageResult<AppActivityRespVO> getUserRecordPage(ActivityUserPageReqVO pageReqVO) {
        PageResult<AppActivityRespVO> appActivityRespVOPageResult = activityUserMapper.selectUserRecordPage(pageReqVO);
        if (CollectionUtil.isEmpty(appActivityRespVOPageResult.getList())) {
            return appActivityRespVOPageResult;
        }
        List<AppActivityRespVO> list = appActivityRespVOPageResult.getList();
        List<Long> activityIds = list.stream().map(AppActivityRespVO::getId).collect(Collectors.toList());
        Map<Long, ActivityUserCountVO> userCountVOMap = countByActivityIds(activityIds);
        Map<Long, ActivityAwardsUserCountVO> awardsUserCountVOMap = activityAwardsUserService.countByActivityIds(activityIds);

        for (AppActivityRespVO activity : list) {
            activity.setApplyNum(userCountVOMap.getOrDefault(activity.getId(), new ActivityUserCountVO()).getApplyNum());
            activity.setAwards(activityAwardsUserService.getListByActivityIdAndUserId(activity.getId(), pageReqVO.getUserId()));
            activity.setAwardsNum(awardsUserCountVOMap.getOrDefault(activity.getId(), new ActivityAwardsUserCountVO()).getAwardsNum());
        }
        return appActivityRespVOPageResult;
    }

    @Override
    public List<ActivityUserDO> getUserListByActivityId(Long activityId) {
        return activityUserMapper.selectList(Wrappers.<ActivityUserDO>lambdaQuery().eq(ActivityUserDO::getActivityId, activityId));
    }

    @Override
    public Boolean userApply(AppUserApplyVO appUserApplyVO) {
        ActivityDO activity = activityService.getActivity(appUserApplyVO.getActivityId());
        if(activity == null){
            throw exception(ACTIVITY_NOT_EXISTS);
        }
        LocalDateTime now = LocalDateTime.now();
        //activity.getStartTime().isAfter(now) ||
        if( activity.getEndTime().isBefore(now)){
            throw exception(new ErrorCode(1_005_000_10, "活动未开始"));
        }
        List<ActivityUserDO> activityUserDOS = activityUserMapper.selectList(Wrappers.<ActivityUserDO>lambdaQuery()
                .eq(ActivityUserDO::getActivityId, appUserApplyVO.getActivityId())
                .eq(ActivityUserDO::getUserId, appUserApplyVO.getUserId()));
        if(CollectionUtil.isNotEmpty(activityUserDOS)){
            throw exception(ACTIVITY_USER_JOIN);
        }
        MemberUserDO user = memberService.getUser(appUserApplyVO.getUserId());
        if(user == null){
            throw exception(USER_NOT_EXISTS);
        }
        ActivityUserDO activityUserDO = new ActivityUserDO();
        activityUserDO.setActivityId(appUserApplyVO.getActivityId());
        activityUserDO.setUserId(appUserApplyVO.getUserId());
        activityUserDO.setMobile(appUserApplyVO.getMobile());
        activityUserDO.setNickName(user.getNickname());
        activityUserDO.setAvatar(user.getAvatar());
        int insert = activityUserMapper.insert(activityUserDO);
        return insert>0;
    }

    @Override
    public List<AppActivityUserRespVO> applyUserList(Long activityId) {
        List<ActivityUserDO> activityUserDOS = activityUserMapper.selectList(Wrappers.<ActivityUserDO>lambdaQuery()
                .eq(ActivityUserDO::getActivityId, activityId)
                .last("limit 20")
        );
        return BeanUtil.copyToList(activityUserDOS, AppActivityUserRespVO.class);
    }

    @Override
    public Boolean selectIsApply(Long activityId, Long userId) {
        List<ActivityUserDO> activityUserDOS = activityUserMapper.selectList(Wrappers.<ActivityUserDO>lambdaQuery()
                .eq(ActivityUserDO::getActivityId, activityId)
                .eq(ActivityUserDO::getUserId, userId)
        );
        return CollectionUtil.isNotEmpty(activityUserDOS);

    }
}