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.pojo.dto.GameDTO;
import com.zanxiang.game.module.manage.pojo.params.GameAdPolicyAddOrUpdateParam;
import com.zanxiang.game.module.manage.pojo.params.GameAdPolicyBatchOperationParam;
import com.zanxiang.game.module.manage.pojo.params.GameAdPolicyBatchStartParam;
import com.zanxiang.game.module.manage.pojo.params.GameAdPolicyListParam;
import com.zanxiang.game.module.manage.pojo.vo.GameAdPolicyListVO;
import com.zanxiang.game.module.manage.pojo.vo.GameAdRuleConditionVO;
import com.zanxiang.game.module.manage.service.IGameAdMonitorService;
import com.zanxiang.game.module.manage.service.IGameService;
import com.zanxiang.game.module.mybatis.entity.GameAdMonitor;
import com.zanxiang.game.module.mybatis.mapper.GameAdMonitorMapper;
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.stream.Collectors;

/**
 * @author tianhua
 * @version 1.0
 * @description: TODO
 * @date 2023/12/28 15:42
 */
@Service
@Slf4j
public class GameAdMonitorServiceImpl extends ServiceImpl<GameAdMonitorMapper, GameAdMonitor>
        implements IGameAdMonitorService {

    @Autowired
    private IGameService gameService;

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrUpdate(GameAdPolicyAddOrUpdateParam param) {
        //当前操作人员
        Long sysUserId = SecurityUtil.getUserId();
        //当前操作的时间
        LocalDateTime now = LocalDateTime.now();

        //数据库找出是否含有相同的规则策略
        long count = this.count(new LambdaQueryWrapper<GameAdMonitor>()
                .ne(param.getId() != null, GameAdMonitor::getId, param.getId())
                .eq(GameAdMonitor::getRuleType, param.getRuleType())
                .eq(GameAdMonitor::getDepartment, param.getDepartment())
                .eq(GameAdMonitor::getGameId, param.getGameId())
                .eq(GameAdMonitor::getMediaType, param.getMediaType())
                .eq(GameAdMonitor::getRuleDimension, param.getRuleDimension())
                .eq(GameAdMonitor::getEffectiveScope, StringUtils.join(CollectionUtils.isEmpty(param.getEffectiveScope())
                        ? null : param.getEffectiveScope().toArray(), "-"))
                .eq(GameAdMonitor::getAlarmType, param.getAlarmType())
                .eq(GameAdMonitor::getAlarmFrequency, param.getAlarmFrequency())
                .eq(GameAdMonitor::getAlarmCount, param.getAlarmCount())
                .eq(GameAdMonitor::getOperateDimension, param.getOperateDimension())
                .eq(GameAdMonitor::getOperateType, param.getOperateType())
                .eq(GameAdMonitor::getExecuteScope, param.getExecuteScope())
                .eq(GameAdMonitor::getDataVisitsPeriod, param.getDataVisitsPeriod())
                .eq(GameAdMonitor::getRuleCondition, JsonUtil.toString(param.getRuleCondition()))
                .eq(GameAdMonitor::getEnabled, true)
        );
        if (count > 0) {
            throw new BaseException("该策略规则已经存在，不可重复设置。");
        }

        GameAdMonitor gameAdMonitor = GameAdMonitor.builder()
                .ruleName(param.getRuleName())
                .ruleType(param.getRuleType())
                .department(param.getDepartment())
                .gameId(param.getGameId())
                .mediaType(param.getMediaType())
                .ruleDimension(param.getRuleDimension())
                .effectiveScope(StringUtils.join(CollectionUtils.isEmpty(param.getEffectiveScope())
                        ? null : param.getEffectiveScope().toArray(), "-"))
                .isStart(param.getIsStart())
                .alarmType(param.getAlarmType())
                .alarmFrequency(param.getAlarmFrequency())
                .alarmCount(param.getAlarmCount())
                .operateDimension(param.getOperateDimension())
                .operateType(param.getOperateType())
                .executeScope(param.getExecuteScope())
                .dataVisitsPeriod(param.getDataVisitsPeriod())
                .ruleCondition(JsonUtil.toString(param.getRuleCondition()))
                .updateBy(sysUserId)
                .updateTime(now)
                .build();

        if (param.getId() != null) {
            //id不为空表示更新
            return update(new LambdaUpdateWrapper<GameAdMonitor>()
                    .set(GameAdMonitor::getRuleName, gameAdMonitor.getRuleName())
                    .set(GameAdMonitor::getRuleType, gameAdMonitor.getRuleType())
                    .set(GameAdMonitor::getDepartment, gameAdMonitor.getDepartment())
                    .set(GameAdMonitor::getGameId, gameAdMonitor.getGameId())
                    .set(GameAdMonitor::getMediaType, gameAdMonitor.getMediaType())
                    .set(GameAdMonitor::getRuleDimension, gameAdMonitor.getRuleDimension())
                    .set(GameAdMonitor::getEffectiveScope, gameAdMonitor.getEffectiveScope())
                    .set(GameAdMonitor::getIsStart, gameAdMonitor.getIsStart())
                    .set(GameAdMonitor::getAlarmType, gameAdMonitor.getAlarmType())
                    .set(GameAdMonitor::getAlarmFrequency, gameAdMonitor.getAlarmFrequency())
                    .set(GameAdMonitor::getAlarmCount, gameAdMonitor.getAlarmCount())
                    .set(GameAdMonitor::getOperateDimension, gameAdMonitor.getOperateDimension())
                    .set(GameAdMonitor::getOperateType, gameAdMonitor.getOperateType())
                    .set(GameAdMonitor::getExecuteScope, gameAdMonitor.getExecuteScope())
                    .set(GameAdMonitor::getDataVisitsPeriod, gameAdMonitor.getDataVisitsPeriod())
                    .set(GameAdMonitor::getRuleCondition, gameAdMonitor.getRuleCondition())
                    .set(GameAdMonitor::getUpdateBy, sysUserId)
                    .set(GameAdMonitor::getUpdateTime, now)
                    .eq(GameAdMonitor::getId, param.getId()));
        }
        //id为空表示要新建一条规则
        gameAdMonitor.setCreateBy(sysUserId);
        gameAdMonitor.setCreateTime(now);
        return save(gameAdMonitor);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> ids) {
        Long sysUserId = SecurityUtil.getUserId();
        return update(new LambdaUpdateWrapper<GameAdMonitor>()
                .set(GameAdMonitor::getEnabled, false)
                .set(GameAdMonitor::getUpdateBy, sysUserId)
                .set(GameAdMonitor::getUpdateTime, LocalDateTime.now())
                .in(GameAdMonitor::getId, ids));
    }

    @Override
    public IPage<GameAdPolicyListVO> listOfPage(GameAdPolicyListParam param) {
        return page(param.toPage(), new LambdaQueryWrapper<GameAdMonitor>()
                .eq(param.getGameId() != null , GameAdMonitor::getGameId, param.getGameId())
                .eq(param.getIsStart() != null, GameAdMonitor::getIsStart, param.getIsStart())
                .like(StringUtils.isNotBlank(param.getRuleName()), GameAdMonitor::getRuleName, param.getRuleName())
                .eq(param.getMediaType() != null, GameAdMonitor::getMediaType, param.getMediaType())
                .eq(GameAdMonitor::getEnabled, true))
                .convert(this::toVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchOperation(GameAdPolicyBatchOperationParam param) {
        //当前操作人员
        Long sysUserId = SecurityUtil.getUserId();
        return update(new LambdaUpdateWrapper<GameAdMonitor>()
                .set(GameAdMonitor::getAccountWhitelist, StringUtils.join(CollectionUtils.isEmpty(param.getAccountWhitelist()) ?
                        null : param.getAccountWhitelist().toArray(), "-"))
                .set(param.getAccountValidTime() != null, GameAdMonitor::getAccountValidTime, param.getAdValidTime())
                .set(GameAdMonitor::getAdWhitelist, StringUtils.join(CollectionUtils.isEmpty(param.getAdWhitelist()) ?
                        null : param.getAdWhitelist(), "-"))
                .set(param.getAdValidTime() != null, GameAdMonitor::getAdValidTime, param.getAdValidTime())
                .set(GameAdMonitor::getUpdateBy, sysUserId)
                .set(GameAdMonitor::getUpdateTime, LocalDateTime.now())
                .in(GameAdMonitor::getId, param.getIds())
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchStart(GameAdPolicyBatchStartParam param) {
        //当前操作人员
        Long sysUserId = SecurityUtil.getUserId();
        return update(new LambdaUpdateWrapper<GameAdMonitor>()
                .set(GameAdMonitor::getIsStart, param.getIsStart())
                .set(GameAdMonitor::getUpdateBy, sysUserId)
                .set(GameAdMonitor::getUpdateTime, LocalDateTime.now())
                .in(GameAdMonitor::getId, param.getIds())
        );
    }

    private GameAdPolicyListVO toVO(GameAdMonitor vo) {
        GameDTO game = gameService.getById(vo.getGameId());
        List<GameAdRuleConditionVO> ruleConditionVOList = JsonUtil.toObj(vo.getRuleCondition(), List.class);
        return GameAdPolicyListVO.builder()
                .id(vo.getId())
                .ruleName(vo.getRuleName())
                .ruleType(vo.getRuleType())
                .department(vo.getDepartment())
                .gameId(vo.getGameId())
                .gameName(game == null ? null : game.getName())
                .mediaType(vo.getMediaType())
                .ruleDimension(vo.getRuleDimension())
                .effectiveScope(StringUtils.isBlank(vo.getEffectiveScope()) ? null :
                        Arrays.stream(vo.getEffectiveScope().split("-"))
                        .map(Long::valueOf).collect(Collectors.toList()))
                .isStart(vo.getIsStart())
                .alarmType(vo.getAlarmType())
                .alarmFrequency(vo.getAlarmFrequency())
                .alarmCount(vo.getAlarmCount())
                .operateDimension(vo.getOperateDimension())
                .operateType(vo.getOperateType())
                .executeScope(vo.getExecuteScope())
                .dataVisitsPeriod(vo.getDataVisitsPeriod())
                .ruleCondition(ruleConditionVOList)
                .accountWhitelist(StringUtils.isBlank(vo.getAccountWhitelist()) ? null :
                        vo.getAccountWhitelist().replace("-", ","))
                .accountValidTime(vo.getAccountValidTime() == null ? null : vo.getAccountValidTime())
                .adWhitelist(StringUtils.isBlank(vo.getAdWhitelist()) ? null :
                        vo.getAdWhitelist().replace("-", ","))
                .adValidTime(vo.getAdValidTime() == null ? null : vo.getAdValidTime())
                .createTime(vo.getCreateTime())
                .createBy(vo.getCreateBy())
                .createByName(sysUserRpc.getById(vo.getCreateBy()).getData().getNickname())
                .updateTime(vo.getUpdateTime())
                .updateBy(vo.getUpdateBy())
                .updateByName(sysUserRpc.getById(vo.getUpdateBy()).getData().getNickname())
                .build();
    }

}
