package com.mmc.iuav.user.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.mmc.iuav.page.PageResult;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.user.controller.userpoints.config.UserPointsEnum;
import com.mmc.iuav.user.dao.ActivityDao;
import com.mmc.iuav.user.entity.activity.ActivityDO;
import com.mmc.iuav.user.entity.activity.ActivityPartDO;
import com.mmc.iuav.user.model.dto.UserAccountSimpleDTO;
import com.mmc.iuav.user.model.dto.activity.ActivityDTO;
import com.mmc.iuav.user.model.dto.activity.ActivityPartDTO;
import com.mmc.iuav.user.model.qo.ActivityQO;
import com.mmc.iuav.user.model.vo.activity.ActivityVO;
import com.mmc.iuav.user.model.vo.userpoints.ChangeUserPointVO;
import com.mmc.iuav.user.service.ActivityService;
import com.mmc.iuav.user.service.UserAccountService;
import com.mmc.iuav.user.service.userpoints.UserPointsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: zj
 * @Date: 2023/10/16 15:09
 */
@Service
@Slf4j
public class ActivityServiceImpl implements ActivityService {
    @Autowired
    private ActivityDao activityDao;

    @Autowired
    private UserPointsService userPointsService;

    @Autowired
    private UserAccountService userAccountService;

    @Override
    public ResultBody insertActivity(ActivityVO activity) {
        ActivityDO activityDO = new ActivityDO(activity);
        int countSame = activityDao.countSameActivityName(activityDO);
        if (countSame > 0) {
            return ResultBody.error("活动名称已存在！");
        }
        // 活动时间不能有交集
        int count = activityDao.countCurrentActivity(activityDO);
        if (count > 0) {
            return ResultBody.error("当前有活动正在进行中！");
        }
        activityDao.insertActivity(activityDO);
        return ResultBody.success();
    }

    @Override
    public ResultBody updateActivity(ActivityVO activity) {
        ActivityDO activityDO = new ActivityDO(activity);
        int countSame = activityDao.countSameActivityName(activityDO);
        if (countSame > 0) {
            return ResultBody.error("活动名称已存在！");
        }
        // 活动时间不能有交集
        int count = activityDao.countCurrentActivity(activityDO);
        if (count > 0) {
            return ResultBody.error("当前有活动正在进行中！");
        }
        activityDao.updateActivity(activityDO);
        return ResultBody.success();
    }

    @Override
    public ResultBody details(Integer id) {
        ActivityDO activityDO = activityDao.details(id);
        if (activityDO != null) {
            return ResultBody.success(activityDO.buildActivityDTO());
        }
        return ResultBody.success();
    }

    @Override
    public ResultBody listActivityPages(ActivityQO activityQO) {
        int count = activityDao.countListActivityPages(activityQO);
        if (count == 0) {
            return ResultBody.success(PageResult.buildPage(activityQO.getPageNo(), activityQO.getPageSize(), count));
        }
        Integer pageNo = activityQO.getPageNo();
        activityQO.buildCurrentPage();
        List<ActivityDO> activityDOS = activityDao.listActivityPages(activityQO);
        List<ActivityDTO> activityDTOS = activityDOS.stream().map(ActivityDO::buildActivityDTO).collect(Collectors.toList());
        return ResultBody.success(PageResult.buildPage(pageNo, activityQO.getPageSize(), count, activityDTOS));
    }

    @Transactional
    @Override
    public ResultBody participateActivity(Integer activityType, Integer userAccountId, Integer pUserAccountId) {
        ActivityDO activityDO = activityDao.currentActivity(activityType);
        if (activityDO == null) {
            return ResultBody.success();
        }
        // 查询是否超过奖励限制
        int count = activityDao.countActivityPart(activityDO.getId(), userAccountId);
        if (activityDO.getRequireNum() == 0 || count < activityDO.getRequireNum()) {
            log.info("Activity invite award! userAccountId:{}", userAccountId);
            // 暂时只奖励积分
            ChangeUserPointVO changePoint = new ChangeUserPointVO();
            changePoint.setUserAccountId(userAccountId);
            changePoint.setChangePoint(activityDO.getRewardValue());
            changePoint.setChangeType(UserPointsEnum.INVITE_USER.getCode());
            userPointsService.change(changePoint);
            // 记录领取信息（被邀请）
            ActivityPartDO activityPartDO = new ActivityPartDO();
            activityPartDO.setActivityId(activityDO.getId());
            activityPartDO.setUserAccountId(userAccountId);
            activityPartDO.setPUserAccountId(pUserAccountId);
            activityDao.insertActivityPart(activityPartDO);
        }
        return ResultBody.success();
    }

    @Override
    public ResultBody delete(Integer id) {
        activityDao.delete(id);
        return ResultBody.success();
    }

    @Override
    public ResultBody inviteDetail(ActivityQO activityQO) {
        log.info("InviteDetail parameter:{}", JSONObject.toJSONString(activityQO));
        int count = activityDao.countActivityPartDetail(activityQO);
        if (count == 0) {
            return ResultBody.success(PageResult.buildPage(activityQO.getPageNo(), activityQO.getPageSize(), count));
        }
        Integer pageNo = activityQO.getPageNo();
        activityQO.buildCurrentPage();
        List<ActivityPartDO> activityPartDOS = activityDao.activityPartDetail(activityQO);
        List<ActivityPartDTO> activityPartDTOS = this.buildActivityPartDTOS(activityPartDOS);
        return ResultBody.success(PageResult.buildPage(pageNo, activityQO.getPageSize(), count, activityPartDTOS));
    }

    @Override
    public ResultBody<ActivityDTO> currentActivity(Integer activityType, Integer userAccountId) {
        ActivityDO activityDO = activityDao.currentActivity(activityType);
        if (activityDO == null) {
            return ResultBody.success();
        }
        ActivityDTO activityDTO = activityDO.buildActivityDTO();
        ActivityQO activityQO = new ActivityQO();
        activityQO.setActivityId(activityDO.getId());
        activityQO.setUserAccountId(userAccountId);
        activityQO.setPageNo(0);
        activityQO.setPageSize(999999);
        List<ActivityPartDO> activityPartDOS = activityDao.activityPartDetail(activityQO);
        List<ActivityPartDTO> activityPartDTOList = this.buildActivityPartDTOS(activityPartDOS);
        activityDTO.setActivityPartDTOS(activityPartDTOList);
        return ResultBody.success(activityDTO);
    }

    public List<ActivityPartDTO> buildActivityPartDTOS(List<ActivityPartDO> activityPartDOS) {
        List<ActivityPartDTO> activityPartDTOS = activityPartDOS.stream().map(ActivityPartDO::buildActivityPartDTO).collect(Collectors.toList());
        // 邀请人id
        List<Integer> userIds = activityPartDTOS.stream().map(ActivityPartDTO::getUserAccountId).collect(Collectors.toList());
        // 被邀请人id
        List<Integer> pUserIds = activityPartDTOS.stream().map(ActivityPartDTO::getPUserAccountId).collect(Collectors.toList());
        List<UserAccountSimpleDTO> userAccountSimpleDTOS = userAccountService.feignListAllUserAccountByIds(userIds);
        List<UserAccountSimpleDTO> pUserAccountDTOS = userAccountService.feignListAllUserAccountByIds(pUserIds);
        if (!CollectionUtils.isEmpty(userAccountSimpleDTOS)) {
            Map<Integer, UserAccountSimpleDTO> userMap = userAccountSimpleDTOS.stream().collect(Collectors.toMap(UserAccountSimpleDTO::getId, k1 -> k1, (k1, k2) -> k2));
            for (ActivityPartDTO activityPartDTO : activityPartDTOS) {
                activityPartDTO.setAccountSimpleDTO(userMap.get(activityPartDTO.getUserAccountId()));
            }
        }
        if (!CollectionUtils.isEmpty(pUserAccountDTOS)) {
            Map<Integer, UserAccountSimpleDTO> pUserMap = pUserAccountDTOS.stream().collect(Collectors.toMap(UserAccountSimpleDTO::getId, k1 -> k1, (k1, k2) -> k2));
            for (ActivityPartDTO activityPartDTO : activityPartDTOS) {
                activityPartDTO.setPAccountSimpleDTO(pUserMap.get(activityPartDTO.getPUserAccountId()));
            }
        }
        return activityPartDTOS;
    }
}
