package com.microservices.dss.projects.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microservices.common.core.constant.CacheConstants;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.dss.projects.domain.vo.GlobalResourcesDataVo;
import com.microservices.dss.projects.mapper.*;
import com.microservices.dss.projects.service.IProjectGlobalResourcesService;
import com.microservices.dss.utils.DateUtil;
import com.microservices.dss.utils.DssGitLinkRequestUrl;
import org.springframework.beans.factory.annotation.Autowired;
import com.microservices.common.redis.service.RedisService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.microservices.dss.utils.DataStructureConvertUtil.MapInitByMonth;
import static com.microservices.dss.utils.DataStructureConvertUtil.dbResult2Array;
import static com.microservices.dss.utils.DateUtil.*;

@Service
public class ProjectGlobalResourcesServiceImpl implements IProjectGlobalResourcesService {
    @Autowired
    private RedisService redisService;

    @Resource
    private ProjectsMapper projectsMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private CommitsMapper commitsMapper;

    @Resource
    private PullRequestsMapper pullRequestsMapper;

    @Resource
    private IssuesMapper issuesMapper;

    @Resource
    private JournalsMapper journalsMapper;

    @Autowired
    private GitLinkRequestHelper gitLinkRequestHelper;

    @Override
    public GlobalResourcesDataVo getProjectGlobalResourcesData() throws ParseException, JsonProcessingException {
        String currentYearMonth = currentYearMonth();
        String previousYearMonth = DateUtil.DateAddByYear(currentYearMonth, -1);
        GlobalResourcesDataVo globalResourcesDataVo = new GlobalResourcesDataVo();
        String cacheKey = CacheConstants.getGlobalResourcesDataKey(previousYearMonth, currentYearMonth);
        if (redisService.hasKey(cacheKey)) {
            globalResourcesDataVo = redisService.getCacheObject(cacheKey);
            return globalResourcesDataVo;
        }

        String startTime = getFormattedPreviousYearSameMonth();
        String endTime = getFormattedCurrentDateTime();
        globalResourcesDataVo.setTotalProjects(this.getTotalProjects());
        globalResourcesDataVo.setTotalMembers(userMapper.selectUserCount());
        globalResourcesDataVo.setTotalCommits(commitsMapper.selectTotalCommitCount());
        globalResourcesDataVo.setTotalPullRequest(pullRequestsMapper.selectTotalPullRequestCount());
        globalResourcesDataVo.setNewAddedProjects(this.getNewAddedProjectsByMonth(startTime, endTime));
        globalResourcesDataVo.setNewAddedMembers(this.getNewAddedMembersByMonth(startTime, endTime));
        globalResourcesDataVo.setNewPullRequestTimes(this.getNewPrNumByMonth(startTime, endTime));
        globalResourcesDataVo.setNewCommentTimes(this.getNewCommentNumByMonth(startTime, endTime));
        globalResourcesDataVo.setActiveUsers(this.getActiveMembersByMonth(startTime, endTime));
        globalResourcesDataVo.setActiveProjects(this.getActiveProjectsByMonth(startTime, endTime));
        globalResourcesDataVo.setNewCodeSubmissionTimes(this.getNewCodeSubmissionTimesByMonth(startTime, endTime));
        globalResourcesDataVo.setTaskCompletion(this.getNewAddedIssuesCompletionByMonth(startTime,endTime));
        globalResourcesDataVo.setProgramLanguagePieChart(projectsMapper.getProjectNumOfDiffProgramLanguage(6));
        globalResourcesDataVo.setProjectCategoryPieChart(projectsMapper.getProjectNumOfProjectCategory(6));
        return globalResourcesDataVo;
    }

    @Override
    public JSONObject getLatestActivitiesData(int page, int limit) {
        JSONObject result = gitLinkRequestHelper.doGet(DssGitLinkRequestUrl.GET_LATEST_ACTIVITIES(page, limit));
        JSONObject latestActivities = new JSONObject();
        latestActivities.put("total_count", result.get("total_count"));
        latestActivities.put("project_trends", result.getJSONArray("project_trends"));
        return latestActivities;
    }

    @Override
    public JSONObject getProjectRankData(int time, int limit) {
        JSONObject result = gitLinkRequestHelper.doGet(DssGitLinkRequestUrl.GET_PROJECT_RANK(time, limit));
        JSONObject projectRank = new JSONObject();
        projectRank.put("projects", result.getJSONArray("projects"));
        return projectRank;
    }

    @Override
    public JSONObject getUserRankData(int time, int limit) {
        JSONObject result = gitLinkRequestHelper.doGet(DssGitLinkRequestUrl.GET_USER_RANK(time, limit));
        JSONObject userRank = new JSONObject();
        userRank.put("users", result.getJSONArray("users"));
        return userRank;
    }

    private int getTotalProjects() {
        return projectsMapper.selectProjectCount();
    }

    private int[] getNewAddedProjectsByMonth(String startTime, String endTime) throws ParseException, JsonProcessingException {
        int monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = projectsMapper.getNewAddedProjectsByMonth(startTime, endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }

    private int[] getNewAddedMembersByMonth(String startTime, String endTime) throws ParseException, JsonProcessingException {
        int monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = userMapper.getNewAddedMembersByMonth(startTime,endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }

    private int[] getNewPrNumByMonth(String startTime, String endTime) throws JsonProcessingException, ParseException{
        int monthDiff;
        monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = pullRequestsMapper.getNewPullRequestNumByMonth(startTime,endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }

    private int[] getNewCommentNumByMonth(String startTime, String endTime) throws JsonProcessingException, ParseException {
        int monthDiff;
        monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = journalsMapper.getNewJournalsNumByMonth(startTime,endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }

    private int[] getActiveMembersByMonth(String startTime, String endTime) throws ParseException, JsonProcessingException {
        int monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = userMapper.getActiveMembersByMonth(startTime,endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }

    private int[] getActiveProjectsByMonth(String startTime, String endTime) throws ParseException, JsonProcessingException {
        int monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = projectsMapper.getActiveProjectsByMonth(startTime, endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }

    private int[] getNewCodeSubmissionTimesByMonth(String startTime, String endTime) throws JsonProcessingException, ParseException {
        int monthDiff;
        monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = commitsMapper.getNewCodeSubmissionTimesByMonth(startTime,endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }

    private int[] getNewAddedIssuesCompletionByMonth(String startTime, String endTime) throws JsonProcessingException, ParseException {
        int monthDiff;
        monthDiff = 12;
        Map<Object, Object> map_init = MapInitByMonth(monthDiff,endTime);
        List<Object> Db_result = issuesMapper.getNewAddedIssuesCompletionByMonth(startTime,endTime);
        int[] resultArray = new int[monthDiff+1];
        int[] result = dbResult2Array(Db_result,"createTime","num",map_init,resultArray);
        return result;
    }
}
