package com.example.demo.admin.module.user;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.admin.common.ResponseDTO;
import com.example.demo.admin.common.ResponseTable;
import com.example.demo.admin.interceptor.AdminInterceptor;
import com.example.demo.common.GlobalRoot;
import com.example.demo.module.user.Player;
import com.example.demo.table.UserDayActive;
import com.example.demo.table.UserGameRecord;
import com.example.demo.table.user.UserInfo;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pers.jc.engine.JCEngine;
import pers.jc.sql.SQL;

import javax.servlet.http.HttpServletRequest;
import java.sql.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 后台控制器-玩家用户相关
 */
@CrossOrigin
@RestController
@RequestMapping("admin/user")
public class UserController {

    @GetMapping("getDayActiveUserCount")
    public ResponseDTO getDayActiveUserCount(HttpServletRequest request) {
        //拦截-预处理
        ResponseDTO responseDTO = AdminInterceptor.preHandle(request);
        if (responseDTO != null) return responseDTO;

        responseDTO = new ResponseDTO();
        int count = GlobalRoot.db.getRowCount(UserDayActive.class, new SQL(){{
            WHERE("date = " + PARAM(new Date(System.currentTimeMillis())));
        }});
        if (count < 0) {
            responseDTO.setCode(-1);
        } else {
            responseDTO.setData(count);
        }
        return responseDTO;
    }

    @GetMapping("getOnlineUserCount")
    public ResponseDTO getOnlineUserCount(HttpServletRequest request) throws InterruptedException {
        //拦截-预处理
        ResponseDTO responseDTO = AdminInterceptor.preHandle(request);
        if (responseDTO != null) return responseDTO;

        ResponseDTO responseDTO_1 = new ResponseDTO();
        AtomicBoolean checker = new AtomicBoolean(false);
        JCEngine.gameService.execute(() -> {
            responseDTO_1.setData(Player.playerMap.size());
            checker.set(true);
        });
        waitFor(checker, 10 * 1000);
        if (checker.get()) {
            return responseDTO_1;
        }
        return null;
    }

    @GetMapping("listUser")
    public ResponseDTO getUser(HttpServletRequest request, int page, int limit) throws InterruptedException {
        //拦截-预处理
        ResponseDTO responseDTO = AdminInterceptor.preHandle(request);
        if (responseDTO != null) return responseDTO;

        //搜索相关
        String searchParams = request.getParameter("searchParams");
        JSONObject searchParamJson = searchParams != null ?  JSONObject.parseObject(searchParams) : null;

        ResponseTable responseTable = new ResponseTable();
        responseTable.setCount(GlobalRoot.db.getRowCount(UserInfo.class));
        List<JSONObject> userInfoList = GlobalRoot.db.select(new SQL(){{
            SELECT("id");
            SELECT("nickname");
            SELECT("gender");
            SELECT("phone");
            SELECT("birthday");
            SELECT("integral");
            SELECT("coin");
            SELECT("diamond");
            SELECT("mac");
            SELECT("country");
            SELECT("state");
            SELECT("city");
            SELECT("offlineTime");
            SELECT("if(serverIndex=0, '中国区', '海外区') as srvID");
            FROM("user_info");
            JOIN("(SELECT id as id0, serverIndex FROM user_login) as table0 on id = id0");
            LIMIT((page - 1) * limit, limit);
            ORDER_BY("offlineTime DESC");
            if (searchParamJson != null) {
                Integer id = searchParamJson.getInteger("id");
                if (id != null) {
                    WHERE("id=" + id);
                }
                Integer serverIndex = searchParamJson.getInteger("serverIndex");
                if (serverIndex != null && serverIndex >= 0) {
                    WHERE("serverIndex=" + serverIndex);
                }
            }
        }});

        //统计游戏总时长和总次数
        if (userInfoList.size() > 0) {
            List<String> ids = new LinkedList<>();
            for (JSONObject jsonObject : userInfoList) {
                ids.add(jsonObject.getString("id"));
            }
            String sql_userID_in_set = "userID in (" + String.join(",", ids) + ")";
            String name_totalGameDuration = "totalGameDuration";
            String name_totalGameCount = "totalGameCount";
            List<JSONObject> list = GlobalRoot.db.select(new SQL(){{
                FROM("user_game_record");
                SELECT("userID");
                SELECT("sum(duration) as " + name_totalGameDuration);
                SELECT("count(*) as " + name_totalGameCount);
                WHERE(sql_userID_in_set);
                GROUP_BY("userID");
            }});
            for (JSONObject o : userInfoList) {
                boolean getSuccess = false;
                for (JSONObject rc : list) {
                    if (o.get("id").equals(rc.get("userID"))) {
                        o.put(name_totalGameDuration, rc.get(name_totalGameDuration));
                        o.put(name_totalGameCount, rc.get(name_totalGameCount));
                        getSuccess = true;
                        break;
                    }
                }
                if (!getSuccess) {
                    o.put(name_totalGameDuration, 0);
                    o.put(name_totalGameCount, 0);
                }
            }
        }

        //获取在线情况
        AtomicBoolean checkOnlineOK = new AtomicBoolean(false);
        JCEngine.gameService.execute(() -> {
            for (JSONObject jo: userInfoList) {
                int id = jo.getInteger("id");
                jo.put("online", Player.playerMap.get(id) == null ? false : true);
            }
            responseTable.setData(userInfoList);
            checkOnlineOK.set(true);
        });
        waitFor(checkOnlineOK, 10 * 1000);

        if (checkOnlineOK.get()) {
            return responseTable;
        } else {
            return null;
        }
    }

    void waitFor(AtomicBoolean checker, long timeMillisMax) throws InterruptedException {
        long waitTime = 0;
        while (true) {
            Thread.sleep(10);
            if (checker.get()) {
                break;
            }
            waitTime += 10;
            if (waitTime > timeMillisMax) {
                break;
            }
        }
    }

    @GetMapping("listGameRecords")
    public ResponseDTO listGameRecords(HttpServletRequest request, int page, int limit) throws InterruptedException {
        //拦截-预处理
        ResponseDTO responseDTO = AdminInterceptor.preHandle(request);
        if (responseDTO != null) return responseDTO;

        ResponseTable responseTable = new ResponseTable();
        Integer userID = Integer.valueOf(request.getParameter("userID"));
        responseTable.setCount(GlobalRoot.db.getRowCount(
                "(select date_format(dateTime, '%Y-%m-%d') as date FROM user_game_record WHERE userID = " + userID
                        + " GROUP BY date) as tb"
        ));
        responseTable.setData(GlobalRoot.db.select(new SQL(){{
            String gameTypeSet1 = "(1)"; //限时游戏
            String gameTypeSet2 = "(3,4,5)"; //闯关游戏
            String gameTypeSet3 = "(2,6,7,8,9,10,11,12)"; //PK游戏
            FROM("user_game_record");
            SELECT("userID");
            SELECT("date_format(dateTime, '%Y-%m-%d') as date");
            SELECT("sum(duration) as totalGameDuration");
            SELECT("count(*) as totalGameCount");
            SELECT("sum(if(gameType in " + gameTypeSet1 + ", duration, 0)) as game1_duration");
            SELECT("count(if(gameType in " + gameTypeSet1 + ", TRUE, null)) as game1_count");
            SELECT("sum(if(gameType in " + gameTypeSet2 + ", duration, 0)) as game2_duration");
            SELECT("count(if(gameType in " + gameTypeSet2 + ", TRUE, null)) as game2_count");
            SELECT("sum(if(gameType in " + gameTypeSet3 + ", duration, 0)) as game3_duration");
            SELECT("count(if(gameType in " + gameTypeSet3 + ", TRUE, null)) as game3_count");
            WHERE("userID=" + PARAM(userID));
            GROUP_BY("date");
            ORDER_BY("date DESC");
            LIMIT((page - 1) * limit, limit);
        }}));

        return responseTable;
    }

    @GetMapping("listGameRecordsThisDay")
    public ResponseDTO listGameRecordsThisDay(HttpServletRequest request, int page, int limit) throws InterruptedException {
        //拦截-预处理
        ResponseDTO responseDTO = AdminInterceptor.preHandle(request);
        if (responseDTO != null) return responseDTO;

        ResponseTable responseTable = new ResponseTable();
        Integer userID = Integer.valueOf(request.getParameter("userID"));
        String dateStr = request.getParameter("dateStr");
        responseTable.setCount(GlobalRoot.db.getRowCount(UserGameRecord.class, new SQL(){{
            WHERE("userID=" + PARAM(userID));
            WHERE("date_format(dateTime, '%Y-%m-%d')=" + PARAM(dateStr));
        }}));
        responseTable.setData(GlobalRoot.db.select(new SQL(){{
            FROM("user_game_record");
            SELECT("dateTime");
            SELECT("gameType");
            SELECT("duration");
            WHERE("userID=" + PARAM(userID));
            WHERE("date_format(dateTime, '%Y-%m-%d')=" + PARAM(dateStr));
            ORDER_BY("dateTime DESC");
            LIMIT((page - 1) * limit, limit);
        }}));

        return responseTable;
    }
}
