package com.zanxiang.game.module.manage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.erp.base.ErpServer;
import com.zanxiang.erp.base.rpc.ISysUserRpc;
import com.zanxiang.erp.security.util.SecurityUtil;
import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
import com.zanxiang.game.module.manage.pojo.params.RoleGiftRecordAddParam;
import com.zanxiang.game.module.manage.pojo.params.RoleGiftRecordListParam;
import com.zanxiang.game.module.manage.pojo.vo.RoleGiftRecordListVO;
import com.zanxiang.game.module.manage.service.IGameGiftService;
import com.zanxiang.game.module.manage.service.IGameService;
import com.zanxiang.game.module.manage.service.IRoleGiftRecordService;
import com.zanxiang.game.module.manage.service.IRoleOperateService;
import com.zanxiang.game.module.mybatis.entity.GameGift;
import com.zanxiang.game.module.mybatis.entity.RoleGiftRecord;
import com.zanxiang.game.module.mybatis.entity.RoleOperate;
import com.zanxiang.game.module.mybatis.mapper.RoleGiftRecordMapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色礼包发送记录表 服务实现类
 * </p>
 *
 * @author auto
 * @since 2023-09-09
 */
@Service
public class RoleGiftRecordServiceImpl extends ServiceImpl<RoleGiftRecordMapper, RoleGiftRecord> implements IRoleGiftRecordService {
    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
    private ISysUserRpc sysUserRpc;
    @Autowired
    private IRoleOperateService roleOperateService;
    @Autowired
    private IGameGiftService gameGiftService;
    @Autowired
    private IGameService gameService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrUpdate(RoleGiftRecordAddParam param) {
                Long sysUserId = SecurityUtil.getUserId();
        LocalDateTime now = LocalDateTime.now();
        if (CollectionUtils.isEmpty(param.getIds())) {
            List<RoleGiftRecord> roleGiftRecordList = param.getRoleInfoList().stream()
                    .map(item -> RoleGiftRecord.builder()
                            .gameId(item.getGameId())
                            .serverId(item.getServerId())
                            .userId(item.getUserId())
                            .roleId(item.getRoleId())
                            .sendTime(param.getSendTime())
                            .sendGiftId(param.getGiftId())
                            .createBy(sysUserId)
                            .createTime(now)
                            .updateBy(sysUserId)
                            .updateTime(now)
                            .build()).collect(Collectors.toList());
            saveBatch(roleGiftRecordList);
            List<RoleOperate> roleOperateList = param.getRoleInfoList().stream()
                    .map(item -> {
                        RoleOperate roleOperate = RoleOperate.builder().build();
                        RoleOperate queryOne = roleOperateService.getOne(new LambdaQueryWrapper<RoleOperate>()
                                .eq(RoleOperate::getGameId, item.getGameId())
                                .eq(RoleOperate::getServerId, item.getServerId())
                                .eq(RoleOperate::getUserId, item.getUserId())
                                .eq(RoleOperate::getRoleId, item.getRoleId())
                                .eq(RoleOperate::getIsDelete, 0));
                        if (null == queryOne) {
                            roleOperate.setGameId(item.getGameId());
                            roleOperate.setServerId(item.getServerId());
                            roleOperate.setUserId(item.getUserId());
                            roleOperate.setRoleId(item.getRoleId());
                            roleOperate.setCreateBy(sysUserId);
                            roleOperate.setCreateTime(now);
                            RoleGiftRecord roleGiftRecord = latestGift(item.getGameId(), item.getServerId(), item.getUserId(), item.getRoleId());
                            roleOperate.setSendGiftId(null == roleGiftRecord ? null : roleGiftRecord.getSendGiftId());
                        } else {
                            roleOperate = queryOne;
                            roleOperate.setSendGiftId(param.getGiftId());
                        }
                        roleOperate.setUpdateBy(sysUserId);
                        roleOperate.setUpdateTime(now);
                        return roleOperate;
                    }).collect(Collectors.toList());
            return roleOperateService.saveOrUpdateBatch(roleOperateList);
        } else {
            RoleGiftRecord roleGiftRecord = listByIds(param.getIds()).get(0);
            update(new LambdaUpdateWrapper<RoleGiftRecord>()
                    .set(RoleGiftRecord::getSendTime, param.getSendTime())
                    .set(RoleGiftRecord::getSendGiftId, param.getGiftId())
                    .set(RoleGiftRecord::getUpdateBy, sysUserId)
                    .set(RoleGiftRecord::getUpdateTime, now)
                    .in(RoleGiftRecord::getId, param.getIds()));
            return sendLatestGift(roleGiftRecord.getGameId(), roleGiftRecord.getServerId(), roleGiftRecord.getUserId(), roleGiftRecord.getRoleId());
        }

    }

    @Override
    public IPage<RoleGiftRecordListVO> listOfPage(RoleGiftRecordListParam param) {
        GameDTO gameDTO = gameService.getById(param.getGameId());
        Long parentGameId = null == gameDTO.getParentId() ? param.getGameId():gameDTO.getParentId();
        List<Long> gameGiftIdList = gameGiftService.list(new LambdaQueryWrapper<GameGift>()
                        .eq(GameGift::getParentGameId, parentGameId)
                        .like(StringUtils.isNotBlank(param.getGiftName()), GameGift::getGiftName, param.getGiftName()))
                .stream()
                .map(GameGift::getId)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(gameGiftIdList)) {
            return new Page<>();
        }
        return page(param.toPage(), new LambdaQueryWrapper<RoleGiftRecord>()
                .eq(RoleGiftRecord::getGameId, param.getGameId())
                .eq(RoleGiftRecord::getServerId, param.getServerId())
                .eq(RoleGiftRecord::getUserId, param.getUserId())
                .eq(RoleGiftRecord::getRoleId, param.getRoleId())
                .in(CollectionUtils.isNotEmpty(gameGiftIdList), RoleGiftRecord::getSendGiftId, gameGiftIdList)
                .ge(null != param.getStartDateTime(), RoleGiftRecord::getSendTime, param.getStartDateTime())
                .le(null != param.getEndDateTime(), RoleGiftRecord::getSendTime, param.getEndDateTime())
                .eq(RoleGiftRecord::getIsDelete, 0)
                .orderByDesc(RoleGiftRecord::getSendTime))
                .convert(item -> RoleGiftRecordListVO.builder()
                        .id(item.getId())
                        .sendTime(item.getSendTime())
                        .giftId(item.getSendGiftId())
                        .giftName(null == item.getSendGiftId() ? null : gameGiftService.getById(item.getSendGiftId()).getGiftName())
                        .createBy(item.getCreateBy())
                        .createName(sysUserRpc.getById(item.getCreateBy()).getData().getNickname())
                        .createTime(item.getCreateTime())
                        .updateBy(item.getUpdateBy())
                        .updateName(sysUserRpc.getById(item.getUpdateBy()).getData().getNickname())
                        .updateTime(item.getUpdateTime())
                        .build());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> ids) {
                Long sysUserId = SecurityUtil.getUserId();
        RoleGiftRecord roleGiftRecord = listByIds(ids).get(0);
        update(new LambdaUpdateWrapper<RoleGiftRecord>()
                .set(RoleGiftRecord::getIsDelete, 1)
                .set(RoleGiftRecord::getUpdateBy, sysUserId)
                .set(RoleGiftRecord::getUpdateTime, LocalDateTime.now())
                .in(RoleGiftRecord::getId, ids));
        return sendLatestGift(roleGiftRecord.getGameId(), roleGiftRecord.getServerId(), roleGiftRecord.getUserId(), roleGiftRecord.getRoleId());
    }

    private boolean sendLatestGift(Long gameId, String serverId, Long userId, String roleId) {
        RoleGiftRecord roleGiftRecord = latestGift(gameId,serverId,userId,roleId);
        return roleOperateService.update(new LambdaUpdateWrapper<RoleOperate>()
                .set(RoleOperate::getSendGiftId, null == roleGiftRecord ? null : roleGiftRecord.getSendGiftId())
                .eq(RoleOperate::getGameId, gameId)
                .eq(RoleOperate::getServerId, serverId)
                .eq(RoleOperate::getUserId, userId)
                .eq(RoleOperate::getRoleId, roleId));
    }

    private RoleGiftRecord latestGift(Long gameId, String serverId, Long userId, String roleId) {
        return getOne(new LambdaQueryWrapper<RoleGiftRecord>()
                .eq(RoleGiftRecord::getGameId, gameId)
                .eq(RoleGiftRecord::getServerId, serverId)
                .eq(RoleGiftRecord::getUserId, userId)
                .eq(RoleGiftRecord::getRoleId, roleId)
                .eq(RoleGiftRecord::getIsDelete, 0)
                .orderByDesc(RoleGiftRecord::getSendTime)
                .last("LIMIT 1"));
    }
}
