package com.css.simulation.resource.server.app.service;

import api.common.pojo.common.PageVO;
import api.common.pojo.common.ResponseBodyVO;
import api.common.pojo.po.home.SystemServerPO;
import api.common.pojo.vo.home.HardwareVO;
import api.common.pojo.vo.home.LineChartVO;
import api.common.pojo.vo.home.ServiceVO;
import api.common.pojo.vo.home.SystemServerVO;
import api.common.util.NumberUtil;
import api.common.util.ObjectUtil;
import api.common.util.TimeUtil;
import com.css.simulation.resource.server.infra.util.AuthUtil;
import com.css.simulation.resource.server.infra.util.PageUtil;
import com.css.simulation.resource.server.infra.feign.service.OauthClientService;
import com.css.simulation.resource.server.infra.db.mysql.mapper.HomePageMapper;
import com.css.simulation.resource.server.infra.db.mysql.mapper.LogMapper;
import com.css.simulation.resource.server.infra.db.mysql.mapper.SimulationManualProjectTaskMapper;
import com.css.simulation.resource.server.infra.db.mysql.mapper.SystemUserMapper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class HomePageService {

    @Resource
    private HomePageMapper homePageMapper;
    @Resource
    private SimulationManualProjectTaskMapper simulationManualProjectTaskMapper;
    @Resource
    private SystemUserMapper systemUserMapper;

    @Resource
    private LogMapper logMapper;

    @Resource
    private OauthClientService oauthClientService;


    public ResponseBodyVO<HardwareVO> selectHardware() {
        List<SystemServerPO> systemServerPOList = homePageMapper.selectAll();
        log.info("selectHardware() 服务器列表为：" + systemServerPOList);
        long memoryTotalSum = systemServerPOList.stream().mapToLong(SystemServerPO::getMemoryTotal).sum();  // 内存之和
        long diskTotalSum = systemServerPOList.stream().mapToLong(SystemServerPO::getDiskTotal).sum();  // 磁盘之和
        long cpuTotalSum = systemServerPOList.stream().mapToLong(SystemServerPO::getCpuTotal).sum();  // cpu线程数 之和
        long gpuTotalSum = systemServerPOList.stream().mapToLong(SystemServerPO::getGpuTotal).sum();  // 显存之和
        log.info("selectHardware() 内存之和：" + memoryTotalSum);
        log.info("selectHardware() 磁盘之和：" + diskTotalSum);
        log.info("selectHardware() cpu线程数 之和：" + cpuTotalSum);
        log.info("selectHardware() 显存之和 之和：" + gpuTotalSum);
        long memoryUsedSum = systemServerPOList.stream().mapToLong(SystemServerPO::getMemoryAvailable).sum();  // 内存之和
        long diskUsedSum = systemServerPOList.stream().mapToLong(SystemServerPO::getDiskAvailable).sum();  // 磁盘之和
        long cpuUsedSum = systemServerPOList.stream().mapToLong(systemServer -> (long) (systemServer.getCpuTotal() * systemServer.getCpuUsage())).sum();  // cpu线程数 之和
        long gpuUsedSum = systemServerPOList.stream().mapToLong(systemServer -> (long) (systemServer.getGpuTotal() * systemServer.getGpuUsage())).sum();  // cpu线程数 之和

        HardwareVO build = HardwareVO.builder()
                .serverNumber(systemServerPOList.size())
                .memoryUsage(NumberUtil.cut(memoryUsedSum * 1.0 / memoryTotalSum, 2) + "%")
                .diskUsage(NumberUtil.cut(diskUsedSum * 1.0 / diskTotalSum, 2) + "%")
                .cpuUsage(NumberUtil.cut(cpuUsedSum * 1.0 / cpuTotalSum, 2) + "%")
                .gpuUsage(NumberUtil.cut(gpuUsedSum * 1.0 / gpuTotalSum, 2) + "%")
                .build();
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, build);
    }


    public ResponseBodyVO<ServiceVO> selectService() {
        List<SystemServerPO> systemServerPOList = homePageMapper.selectAll();
        long count = systemServerPOList.stream().filter(system -> "gpu".equals(system.getServerType())).count();
        int onlineNumber = oauthClientService.online().getInfo();
        if (onlineNumber == 0) {
            onlineNumber = 1;
        }

        //* -------------------------------- 求动力学软件占用数量 --------------------------------
        //1 查询手动运行任务 -> 项目 -> 车辆配置 -> 车辆模型 -> 模型类型
        //2 查询自动运行任务 -> 子项目 -> 父项目 -> 车辆配置 -> 车辆模型 -> 模型类型
        int dynamicsLicenseNumber = simulationManualProjectTaskMapper.selectTaskNumberOfCarsim();
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, ServiceVO.builder()
                .userNumber(systemUserMapper.selectCount())
                .onlineNumber(onlineNumber)
                .simulationNodeNumber((int) count)
                .simulationLicenseNumber(homePageMapper.selectSimulationLicenseNumber())
                .dynamicsLicenseNumber(dynamicsLicenseNumber)   // 待定
                .build());
    }

    public ResponseBodyVO<PageInfo<SystemServerVO>> selectServer(PageVO pageVO) {
        PageUtil.setPageInfo(pageVO);
        List<SystemServerPO> systemServerPOList = homePageMapper.selectAll();
        List<SystemServerVO> systemServerVOList = new ArrayList<>();
        systemServerPOList.forEach(po -> {
            SystemServerVO vo = SystemServerVO.builder()
                    .id(po.getId())
                    .serverId(po.getServerId())
                    .serverAddress(po.getServerAddress())
                    .serverType(po.getServerType())
                    .cpuUsage((int) (po.getCpuUsage() * 100))
                    .memoryUsage((int) (po.getMemoryUsage() * 100))
                    .memoryAvailable((double) (int) (po.getMemoryAvailable() * 1.0 / 1024.0 / 1024.0 * 100) / 100)
                    .diskUsage((int) (po.getDiskUsage() * 100))
                    .diskAvailable((double) (int) (po.getDiskAvailable() * 1.0 / 1024.0 / 1024.0 * 100) / 100)
                    .taskNumber(po.getTaskNumber())
                    .build();
            systemServerVOList.add(vo);
        });
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, new PageInfo<>(systemServerVOList));
    }

    public List<LineChartVO> selectAccess() {
        String dateBegin = TimeUtil.getMinusDaysStr(6);
        List<LineChartVO> listVo = logMapper.getAccessCount(dateBegin);
        return makeLineChartDate(listVo, 6);
    }

    public List<LineChartVO> selectRunTaskChart() {
        Map<String, String> param = new HashMap<>();
        param.put("dateBegin", TimeUtil.getMinusDaysStr(6));
        param.put("createUserId", AuthUtil.getCurrentUserId());
        List<LineChartVO> listVo = homePageMapper.selectRunTaskChart(param);
        return makeLineChartDate(listVo, 6);
    }

    public List<LineChartVO> selectRunProjectChart() {
        Map<String, String> param = new HashMap<>();
        param.put("dateBegin", TimeUtil.getMinusDaysStr(6));
        param.put("createUserId", AuthUtil.getCurrentUserId());
        List<LineChartVO> listVo = homePageMapper.selectRunProjectChart(param);
        return makeLineChartDate(listVo, 6);
    }

    /**
     * 构建图标基础数据
     */
    private List<LineChartVO> makeLineChartDate(List<LineChartVO> listVo, int j) {
        List<LineChartVO> list = new ArrayList<>();
        boolean notNull = ObjectUtil.isNotNull(listVo);
        for (int i = j; i >= 0; i--) {
            String date = TimeUtil.getMinusDaysStr(i);
            if (notNull) {
                List<LineChartVO> collect = listVo.stream().filter(v -> date.equals(v.getToDate())).collect(Collectors.toList());
                if (ObjectUtil.isNotNull(collect)) {
                    LineChartVO vo = collect.get(0);
                    list.add(vo);
                    continue;
                }
            }
            //创建新数据
            LineChartVO vo = new LineChartVO();
            vo.setToDate(date);
            vo.setNum(0);
            list.add(vo);
        }
        return list;
    }

    public int getRunningTask() {
        return homePageMapper.selectRunningTask(AuthUtil.getCurrentUserId());
    }
}
