package com.zanxiang.game.data.serve.service.impl;

import com.github.sd4324530.jtuple.Tuple2;
import com.google.common.base.CaseFormat;
import com.zanxiang.game.data.serve.component.DataPowerComponent;
import com.zanxiang.game.data.serve.pojo.dto.RechargeRankingDTO;
import com.zanxiang.game.data.serve.pojo.enums.OrderByEnum;
import com.zanxiang.game.data.serve.pojo.vo.GameRechargeRankingVO;
import com.zanxiang.game.data.serve.pojo.vo.PlayerRechargeRankingVO;
import com.zanxiang.game.data.serve.service.IRankingService;
import com.zanxiang.game.data.serve.utils.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos;
import org.nutz.dao.util.cri.SimpleCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;

@Service
@Slf4j
public class RankingServiceImpl implements IRankingService {
    @Autowired
    private Dao dao;
    @Autowired
    private DataPowerComponent dataPowerComponent;

    @Override
    public Page<GameRechargeRankingVO> gameRanking(RechargeRankingDTO dto) {
        Tuple2<List<Long>, List<Long>> poerInfo = dataPowerComponent.getPowerInfo();
        List<Long> gameIds = dto.getGameId() == null ? poerInfo.second : Collections.singletonList(dto.getGameId());
        if (StringUtils.isBlank(dto.getSortFiled())){
            dto.setSortFiled("totalAmount");
        }
        if (StringUtils.isBlank(dto.getSortType())){
            dto.setSortType(OrderByEnum.DESC.getOrderType());
        }
        Pager pager = dao.createPager(dto.getPageNum(), dto.getPageSize());
        // 创建一个 Criteria 接口实例
        SimpleCriteria cri = Cnd.cri();
        if (null != dto.getBeginDay() && null != dto.getEndDay()){
            cri.where().and("dt",">=",dto.getBeginDay()).and("dt","<=",dto.getEndDay());
        }
        if(gameIds != null) {
            cri.where().andInList("game_id", gameIds);
        }
        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
            cri.where().andEquals("source_system", dto.getSourceSystem());
        }
        cri.where().andNotEquals("today_amount",0);
        cri.groupBy("source_system, game_id");
        cri.orderBy(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, dto.getSortFiled()), dto.getSortType());
        Sql sql = Sqls.queryEntity(gameRankingSql() + "$condition");
        sql.setPager(pager);
        Entity<GameRechargeRankingVO> entity = dao.getEntity(GameRechargeRankingVO.class);
        sql.setEntity(entity).setCondition(cri);
        dao.execute(sql);

        Sql sqlCount = Sqls.queryEntity("select count(*) from ads_game_recharge_ranking " + "$condition");
        sqlCount.setCondition(cri);
        pager.setRecordCount((int) Daos.queryCount(dao,sqlCount));
        return new Page<>(sql.getList(GameRechargeRankingVO.class),pager);
    }

    private String gameRankingSql() {
        return """
                select
                source_system,
                max(game_id) as id,
                max(game_id) as game_id,
                max(game_name) as game_name,
                max(game_classify) as game_classify,
                sum(today_amount) as today_amount,
                sum(today_buy_amount) as today_buy_amount,
                sum(today_nature_amount) as today_nature_amount,
                max(total_amount) as total_amount,
                max(total_buy_amount) as total_buy_amount,
                max(total_nature_amount) as total_nature_amount,
                max(avg_amount) as avg_amount,
                sum(reg_user_count) as reg_user_count,
                max(total_recharge_user_count) as total_recharge_user_count,
                max(total_recharge_count) as total_recharge_count,
                max(total_cost) as total_cost,
                max(total_roi) as total_roi
                from ads_game_recharge_ranking
                """;
    }

    @Override
    public Page<PlayerRechargeRankingVO> playerRanking(RechargeRankingDTO dto) {
        Tuple2<List<Long>, List<Long>> poerInfo = dataPowerComponent.getPowerInfo();
        List<Long> gameIds = dto.getGameId() == null ? poerInfo.second : Collections.singletonList(dto.getGameId());
        if (StringUtils.isBlank(dto.getSortFiled())){
            dto.setSortFiled("totalAmount");
        }
        if (StringUtils.isBlank(dto.getSortType())){
            dto.setSortType(OrderByEnum.DESC.getOrderType());
        }
        Pager pager = dao.createPager(dto.getPageNum(), dto.getPageSize());
        // 创建一个 Criteria 接口实例
        SimpleCriteria cri = Cnd.cri();
        if (null != dto.getBeginDay() && null != dto.getEndDay()){
            cri.where().and("dt",">=",dto.getBeginDay()).and("dt","<=",dto.getEndDay());
        }
        if(gameIds != null) {
            cri.where().andInList("reg_game_id", gameIds);
        }
        if (StringUtils.isNotBlank(dto.getSourceSystem())) {
            cri.where().andEquals("source_system", dto.getSourceSystem());
        }
        if (dto.getLatestAmountUntilNowTimeMin() != null) {
            cri.where().andGTE("TIMESTAMPDIFF(MINUTE, last_amount_time, NOW())", dto.getLatestAmountUntilNowTimeMin());
        }
        if (dto.getLatestAmountUntilNowTimeMax() != null) {
            cri.where().andLTE("TIMESTAMPDIFF(MINUTE, last_amount_time, NOW())", dto.getLatestAmountUntilNowTimeMax());
        }

        cri.groupBy("source_system,player_id");
        cri.orderBy(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, dto.getSortFiled()), dto.getSortType());
        Sql sql = Sqls.queryEntity(playerRankingSql() + "$condition");
        sql.setPager(pager);
        Entity<PlayerRechargeRankingVO> entity = dao.getEntity(PlayerRechargeRankingVO.class);
        sql.setEntity(entity).setCondition(cri);
        dao.execute(sql);

        Sql sqlCount = Sqls.queryEntity("select count(*) from ads_player_recharge_ranking " + "$condition");
        sqlCount.setCondition(cri);
        pager.setRecordCount((int) Daos.queryCount(dao,sqlCount));
        return new Page<>(sql.getList(PlayerRechargeRankingVO.class),pager);
    }

    private String playerRankingSql() {
        return """
                select
                source_system,
                max(player_id) as id,
                max(player_id) as player_id,
                max(player_account_id) as player_account_id,
                max(reg_agent_id) as reg_agent_id,
                max(reg_agent_name) as reg_agent_name,
                max(reg_user_time) as reg_user_time,
                max(reg_game_id) as reg_game_id,
                max(reg_game_name) as reg_game_name,
                max(player_os) as player_os,
                sum(today_total_amount) as today_total_amount,
                max(first_amount) as first_amount,
                max(last_amount) as last_amount,
                max(total_amount) as total_amount,
                max(avg_amount) as avg_amount,
                max(total_amount_count) as total_amount_count,
                max(last_amount_game_id) as last_amount_game_id,
                max(last_amount_game_name) as last_amount_game_name,
                max(last_amount_time) as last_amount_time,
                max(role_name) as role_name,
                max(server_name) as server_name
                from ads_player_recharge_ranking
                """;
    }
}
