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.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.enums.ExcludeTagsEnum;
import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
import com.zanxiang.game.module.manage.pojo.params.GamePolicyConfigAddOrUpdateParam;
import com.zanxiang.game.module.manage.pojo.params.GamePolicyConfigListParam;
import com.zanxiang.game.module.manage.pojo.vo.GamePolicyConfigInnerObjVO;
import com.zanxiang.game.module.manage.pojo.vo.GamePolicyConfigListVO;
import com.zanxiang.game.module.manage.service.IGamePolicyConfigService;
import com.zanxiang.game.module.manage.service.IGameService;
import com.zanxiang.game.module.manage.service.IGameSupperService;
import com.zanxiang.game.module.mybatis.entity.GamePolicyConfig;
import com.zanxiang.game.module.mybatis.entity.GameSupper;
import com.zanxiang.game.module.mybatis.mapper.GamePolicyConfigMapper;
import com.zanxiang.module.util.JsonUtil;
import com.zanxiang.module.util.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
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.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author tianhua
 * @version 1.0
 * @description: TODO
 * @date 2023/11/29 14:25
 */
@Service
@Slf4j
public class GamePolicyConfigServiceImpl extends ServiceImpl<GamePolicyConfigMapper, GamePolicyConfig> implements IGamePolicyConfigService {

    @Autowired
    private IGameSupperService gameSupperService;

    @Autowired
    private IGameService gameService;

    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
    private ISysUserRpc sysUserRpc;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrUpdate(GamePolicyConfigAddOrUpdateParam param) {
        //检查输入的查询参数
        checkParam(param);
        //当前操作人员
        Long sysUserId = SecurityUtil.getUserId();
        //当前操作时间
        LocalDateTime now = LocalDateTime.now();

        //生成配置json字符串
        String configParam = JsonUtil.toString(GamePolicyConfigInnerObjVO.builder()
                .amount(param.getAmount())
                .amountCondition(param.getAmountCondition())
                .time(param.getTime())
                .timeCondition(param.getTimeCondition())
                .build());

        long count = this.count(new LambdaQueryWrapper<GamePolicyConfig>()
                .ne(param.getId() != null, GamePolicyConfig::getId, param.getId())
                .eq(GamePolicyConfig::getSuperGameId, param.getSuperGameId())
                .eq(GamePolicyConfig::getType, param.getType())
                .eq(GamePolicyConfig::getConfigParam, configParam)
                .eq(GamePolicyConfig::getEnabled, true));

        if (count > 0) {
            throw new BaseException("该游戏策略配置已经设置过，请勿重复设置");
        }

        GamePolicyConfig gamePolicyConfig = GamePolicyConfig.builder()
                .superGameId(param.getSuperGameId())
                .type(param.getType())
                .configParam(configParam)
                .configExplain(param.getConfigExplain())
                .userIds(CollectionUtils.isEmpty(param.getUserIds()) ? null : StringUtils.join(param.getUserIds().toArray(), "-"))
                .tagIds(CollectionUtils.isEmpty(param.getTagIds()) ? null : StringUtils.join(param.getTagIds().toArray(), "-"))
                .updateBy(sysUserId)
                .updateTime(now)
                .build();

        if (param.getId() != null) {
            //id不为空，表示修改配置
            gamePolicyConfig.setId(param.getId());
            return updateById(gamePolicyConfig);
        }

        //id为空，表示新增配置
        gamePolicyConfig.setCreateBy(sysUserId);
        gamePolicyConfig.setCreateTime(now);
        return save(gamePolicyConfig);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id) {
        //当前操作人员
        Long sysUserId = SecurityUtil.getUserId();
        return update(new LambdaUpdateWrapper<GamePolicyConfig>()
                .set(GamePolicyConfig::getEnabled, false)
                .set(GamePolicyConfig::getUpdateBy, sysUserId)
                .set(GamePolicyConfig::getUpdateTime, LocalDateTime.now())
                .eq(GamePolicyConfig::getId, id));
    }

    @Override
    public IPage<GamePolicyConfigListVO> listOfPage(GamePolicyConfigListParam param) {
        return page(param.toPage(), new LambdaQueryWrapper<GamePolicyConfig>()
                .eq(param.getSuperGameId() != null, GamePolicyConfig::getSuperGameId, param.getSuperGameId())
                .eq(param.getType() != null , GamePolicyConfig::getType, param.getType())
                .eq(GamePolicyConfig::getEnabled, true))
                .convert(this::toVO);
    }

    private GamePolicyConfigListVO toVO(GamePolicyConfig vo) {
        //得到配置参数map
        Map<String, String> configParam = JsonUtil.toMap(vo.getConfigParam(), Map.class, String.class);
        String amount = configParam.get("amount");
        String amountCondition = configParam.get("amountCondition");
        String time = configParam.get("time");
        String timeCondition = configParam.get("timeCondition");
        GameSupper gameSupper = gameSupperService.getById(vo.getSuperGameId());
        GameDTO game = gameService.getById(vo.getSuperGameId());
        String superGameName = null == gameSupper ? (null == game ? null : game.getName()) : gameSupper.getName();
        List<Long> userIds = StringUtils.isNotBlank(vo.getUserIds()) ?
                Arrays.stream(vo.getUserIds().split("-")).map(Long::valueOf).collect(Collectors.toList()) : null;
        List<Long> tagIds = StringUtils.isNotBlank(vo.getTagIds()) ?
                Arrays.stream(vo.getTagIds().split("-")).map(Long::valueOf).collect(Collectors.toList()) : null;
        //告警人员名称
        StringBuilder userNameStr = new StringBuilder();
        if (StringUtils.isNotBlank(vo.getUserIds())) {
            String[] ids = vo.getUserIds().split("-");
            for (int i = 0; i < ids.length; i++) {
                userNameStr.append(sysUserRpc.getById(Long.valueOf(ids[i])).getData().getNickname());
                if (i != ids.length -1) {
                    userNameStr.append(",");
                }
            }
        }
        //排除标签名称
        StringBuilder tagNameStr = new StringBuilder();
        if (StringUtils.isNotBlank(vo.getTagIds())) {
            String[] tIds = vo.getTagIds().split("-");
            for (int i = 0; i < tIds.length; i++) {
                tagNameStr.append(ExcludeTagsEnum.getTagName(Integer.valueOf(tIds[i])));
                if (i != tIds.length -1) {
                    tagNameStr.append(",");
                }
            }
        }
        return GamePolicyConfigListVO.builder()
                .id(vo.getId())
                .superGameId(vo.getSuperGameId())
                .superGameName(superGameName)
                .type(vo.getType())
                .amount(StringUtils.isBlank(amount) ? null : Long.valueOf(amount))
                .amountCondition(StringUtils.isBlank(amountCondition) ? null : amountCondition)
                .time(StringUtils.isBlank(time) ? null : Long.valueOf(time))
                .timeCondition(StringUtils.isBlank(timeCondition) ? null : timeCondition)
                .configExplain(vo.getConfigExplain())
                .userNameStr(StringUtils.isBlank(userNameStr.toString()) ? null : userNameStr.toString())
                .userNameIds(userIds)
                .tagsNameStr(StringUtils.isBlank(tagNameStr.toString()) ? null : tagNameStr.toString())
                .tagsNameIds(tagIds)
                .createBy(vo.getCreateBy())
                .createName(sysUserRpc.getById(vo.getCreateBy()).getData().getNickname())
                .createTime(vo.getCreateTime())
                .updateBy(vo.getUpdateBy())
                .updateName(sysUserRpc.getById(vo.getUpdateBy()).getData().getNickname())
                .updateTime(vo.getUpdateTime())
                .build();
    }

    /**
     * 检查查询参数的合法性
     * @param param GamePolicyConfigAddOrUpdateParam
     */
    private void checkParam(GamePolicyConfigAddOrUpdateParam param) {
        if (param.getAmount() == null && param.getTime() == null) {
            throw new BaseException("策略配置的金额和时间不能同时为空，请重新输入。");
        }
        if (param.getAmount() != null && StringUtils.isBlank(param.getAmountCondition())) {
            throw new BaseException("输入金额后，对应的金额条件不能为空。");
        }
        if (param.getAmount() == null && StringUtils.isNotBlank(param.getAmountCondition())) {
            throw new BaseException("金额为空时，不能单独设置金额条件。");
        }
        if (param.getTime() != null && StringUtils.isBlank(param.getTimeCondition())) {
            throw new BaseException("输入时间后，对应的时间条件不能为空");
        }
        if (param.getTime() == null && StringUtils.isNotBlank(param.getTimeCondition())) {
            throw new BaseException("时间为空时，不能单独设置时间条件");
        }

    }

}
