package com.microservices.pms.project.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.project.domain.PmsProjectSprint;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.mapper.PmsProjectSprintMapper;
import com.microservices.pms.project.service.IPmsProjectService;
import com.microservices.pms.project.service.IPmsProjectSprintService;
import com.microservices.pms.project.service.PmsProjectIssuesService;
import com.microservices.pms.utils.PmsGitLinkRequestUrl;
import com.microservices.pms.utils.PmsUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.net.URISyntaxException;
import java.util.List;
import java.util.stream.Collectors;

import static com.microservices.common.core.utils.JSONUtils.convertObjectToJSONObject;
import static com.microservices.common.core.utils.PageUtils.startPage;
import static com.microservices.common.core.utils.PageUtils.toPage;
import static com.microservices.common.httpClient.constant.GitLinkConstants.DATA_KEY;
import static com.microservices.pms.utils.PmsConstants.SPRINT_CLOSED_STATUS;

/**
 * 项目迭代Service业务层处理
 * 
 * @author wanjia
 * @date 2023-10-11
 */
@Service
public class PmsProjectSprintServiceImpl implements IPmsProjectSprintService 
{
    @Resource
    private PmsProjectSprintMapper pmsProjectSprintMapper;

    @Autowired
    private IPmsCommonService pmsCommonService;

    @Autowired
    private GitLinkRequestHelper gitLinkRequestHelper;

    @Autowired
    @Lazy
    private IPmsProjectService pmsProjectService;

    @Autowired
    @Lazy
    private PmsProjectIssuesService pmsProjectIssuesService;


    /**
     * 查询项目迭代
     * 
     * @param id 项目迭代主键
     * @return 项目迭代
     */
    @Override
    public PmsProjectSprintDetailVo selectPmsProjectSprint(Long id, PmsProjectSprintIssuesSearchVo pmsProjectSprintIssuesSearchVo)
    {
        PmsProjectSprint pmsProjectSprint = selectPmsProjectSprintById(id);
        PmsProjectSprintDetailVo pmsProjectSprintDetailVo = new PmsProjectSprintDetailVo();
        BeanUtils.copyProperties(pmsProjectSprint, pmsProjectSprintDetailVo);
        getSprintIssuesByGitLink(pmsProjectSprintDetailVo, pmsProjectSprintIssuesSearchVo);
        pmsProjectSprintDetailVo.setSprintAssignee(pmsCommonService.getSimpleSysUserByGitlinkUserId(pmsProjectSprint.getSprintAssigneeId()));
        return pmsProjectSprintDetailVo;
    }

    public PmsProjectSprint selectPmsProjectSprintById(Long id) {
        PmsProjectSprint pmsProjectSprint = pmsProjectSprintMapper.selectPmsProjectSprintById(id);
        if (pmsProjectSprint == null) {
            throw new ServiceException("该项目迭代不存在(项目迭代ID[%s])", id);
        }
        pmsProjectService.selectAndCheckPmsProjectById(pmsProjectSprint.getPmsProjectId());
        return pmsProjectSprint;
    }

    /**
     * 查询项目迭代列表
     * 
     * @param pmsProjectSprint 项目迭代
     * @return 项目迭代
     */
    @Override
    public List<PmsProjectSprint> selectPmsProjectSprintList(PmsProjectSprint pmsProjectSprint)
    {
        pmsProjectService.selectAndCheckPmsProjectById(pmsProjectSprint.getPmsProjectId());
        return pmsProjectSprintMapper.selectPmsProjectSprintList(pmsProjectSprint);
    }

    @Override
    public GenericsTableDataInfo<PmsProjectSprintDetailVo> selectPmsProjectSprintList(PmsProjectSprintSearchVo pmsProjectSprintSearchVo) {
        pmsProjectService.selectAndCheckPmsProjectById(pmsProjectSprintSearchVo.getPmsProjectId());
        startPage();
        List<PmsProjectSprint> pmsProjectSprintList = pmsProjectSprintMapper.selectPmsProjectSprintListBySearchInput(pmsProjectSprintSearchVo);
        String projectSprintIds = StringUtils.join(
                pmsProjectSprintList.stream()
                .map(PmsProjectSprint::getId)
                .collect(Collectors.toList()), ",");
        JSONObject sprintIssuesStatistics = new JSONObject();
        if (StringUtils.isNotEmpty(projectSprintIds)) {
            sprintIssuesStatistics = getSprintIssuesStatisticsByGitLink(projectSprintIds);
        }
        JSONObject finalSprintIssuesStatistics = sprintIssuesStatistics;
        return toPage(pmsProjectSprintList, pmsProjectSprint -> buildPmsProjectSprintDetailVoList(pmsProjectSprint, finalSprintIssuesStatistics));
    }

    public GenericsTableDataInfo<PmsProjectSprintDetailVo> selectAllPmsProjectSprintList(PmsProjectSprintSearchVo pmsProjectSprintSearchVo) {
        for (String id : pmsProjectSprintSearchVo.getPmsProjectIds().split(",")) {
            pmsProjectService.selectAndCheckPmsProjectById(id);
        }
        startPage();
        List<PmsProjectSprint> pmsProjectSprintList = pmsProjectSprintMapper.selectPmsProjectSprintListBySearchInput(pmsProjectSprintSearchVo);
        String projectSprintIds = StringUtils.join(
                pmsProjectSprintList.stream()
                        .map(PmsProjectSprint::getId)
                        .collect(Collectors.toList()), ",");
        JSONObject sprintIssuesStatistics = new JSONObject();
        if (StringUtils.isNotEmpty(projectSprintIds)) {
            sprintIssuesStatistics = getSprintIssuesStatisticsByGitLink(projectSprintIds);
        }
        JSONObject finalSprintIssuesStatistics = sprintIssuesStatistics;
        return toPage(pmsProjectSprintList, pmsProjectSprint -> buildPmsProjectSprintDetailVoList(pmsProjectSprint, finalSprintIssuesStatistics));
    }

    private PmsProjectSprintDetailVo buildPmsProjectSprintDetailVoList(PmsProjectSprint pmsProjectSprint, JSONObject sprintIssuesStatistics) {
        PmsProjectSprintDetailVo pmsProjectSprintDetailVo = new PmsProjectSprintDetailVo();
        BeanUtils.copyProperties(pmsProjectSprint, pmsProjectSprintDetailVo);
        pmsProjectSprintDetailVo.setSprintAssignee(pmsCommonService.getSimpleSysUserByGitlinkUserId(pmsProjectSprint.getSprintAssigneeId()));
        pmsProjectSprintDetailVo.setSprintIssuesStatistics(sprintIssuesStatistics.getJSONObject(String.valueOf(pmsProjectSprint.getId())));
        return pmsProjectSprintDetailVo;
    }


    /**
     * 新增项目迭代
     * 
     * @param pmsProjectSprint 项目迭代
     * @return 结果
     */
    @Override
    public int insertPmsProjectSprint(PmsProjectSprint pmsProjectSprint)
    {
        pmsProjectService.selectAndCheckPmsProjectById(pmsProjectSprint.getPmsProjectId());
        PmsUtils.validStartTimeAndEndTime(pmsProjectSprint.getStartTime(), pmsProjectSprint.getEndTime());
        return pmsProjectSprintMapper.insertPmsProjectSprint(pmsProjectSprint);
    }

    @Override
    public PmsProjectSprintSimpleVo findOrCreatePmsProjectSprint(PmsProjectSprint pmsProjectSprint) {
        pmsProjectService.selectAndCheckPmsProjectById(pmsProjectSprint.getPmsProjectId());
        PmsProjectSprint existingSprint = pmsProjectSprintMapper.selectLatestSprintByProjectIdAndNameAndAssigneeId(pmsProjectSprint.getPmsProjectId(), pmsProjectSprint.getSprintName(), pmsProjectSprint.getSprintAssigneeId());
        PmsProjectSprintSimpleVo sprintSimpleVo = new PmsProjectSprintSimpleVo();
        if (existingSprint == null) {
            insertPmsProjectSprint(pmsProjectSprint);
            sprintSimpleVo.setSprintName(pmsProjectSprint.getSprintName());
            sprintSimpleVo.setId(pmsProjectSprint.getId());
        } else {
            sprintSimpleVo.setSprintName(existingSprint.getSprintName());
            sprintSimpleVo.setId(existingSprint.getId());
        }
        return sprintSimpleVo;
    }

    /**
     * 修改项目迭代
     * 
     * @param pmsProjectSprint 项目迭代
     * @return 结果
     */
    @Override
    public int updatePmsProjectSprint(PmsProjectSprint pmsProjectSprint)
    {
        selectPmsProjectSprintById(pmsProjectSprint.getId());
        PmsUtils.validStartTimeAndEndTime(pmsProjectSprint.getStartTime(), pmsProjectSprint.getEndTime());
        return pmsProjectSprintMapper.updatePmsProjectSprint(pmsProjectSprint);
    }

    /**
     * 批量删除项目迭代
     * 
     * @param ids 需要删除的项目迭代主键
     * @return 结果
     */
    @Override
    public int deletePmsProjectSprintByIds(Long[] ids)
    {
        int success = 0;
        for (Long id : ids) {
            selectPmsProjectSprintById(id);
            success += pmsProjectSprintMapper.deletePmsProjectSprintById(id);
        }
        return success;
    }

    @Override
    public JSONObject getPmsProjectSprintStatistics(String pmSprintIds) {
        return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_SPRINT_ISSUES_STATISTICS(pmSprintIds));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeSprint(PmsProjectSprintCompleteVo pmsProjectSprintCompleteVo) {
        selectPmsProjectSprintById(pmsProjectSprintCompleteVo.getPmProjectSprintId());
        JSONObject sprintCompleteInput = new JSONObject();
        convertObjectToJSONObject(pmsProjectSprintCompleteVo, sprintCompleteInput, null);
        gitLinkRequestHelper.doPost(PmsGitLinkRequestUrl.COMPLETE_SPRINT(), sprintCompleteInput);
        PmsProjectSprint pmsProjectSprint = new PmsProjectSprint();
        pmsProjectSprint.setId(pmsProjectSprintCompleteVo.getPmProjectSprintId());
        pmsProjectSprint.setStatus(SPRINT_CLOSED_STATUS); //设置为已关闭状态
        pmsProjectSprintMapper.updatePmsProjectSprint(pmsProjectSprint);
        return true;
    }

    @Override
    public List<PmsProjectSprintSimpleVo> selectPmsProjectSimpleSprintByIds(Long[] testSheetLinkSprintIds) {
        List<PmsProjectSprint> pmsProjectSprintList = pmsProjectSprintMapper.selectPmsProjectSprintBYIds(testSheetLinkSprintIds);
        return pmsProjectSprintList.stream()
                .map(pmsProjectSprint -> {
                    PmsProjectSprintSimpleVo sprintSimpleVo = new PmsProjectSprintSimpleVo();
                    BeanUtils.copyProperties(pmsProjectSprint, sprintSimpleVo);
                    return sprintSimpleVo;
                })
                .collect(Collectors.toList());
    }

    @Override
    public JSONArray getPmsProjectSprintBurnDownChart(Long pmSprintId) {
        PmsProjectSprint pmsProjectSprint = pmsProjectSprintMapper.selectPmsProjectSprintById(pmSprintId);
        if (pmsProjectSprint == null) {
            throw new ServiceException("该迭代不存在(迭代ID[%s])", pmSprintId);
        }
        if (pmsProjectSprint.getStartTime() == null || pmsProjectSprint.getEndTime() == null) {
            return null;
        }
        JSONObject result = gitLinkRequestHelper.doGet(
                PmsGitLinkRequestUrl.GET_SPRINT_BURN_DOWN_CHART(pmSprintId,
                        pmsProjectSprint.getStartTime(),
                        pmsProjectSprint.getEndTime())
        );
        return result.getJSONArray(DATA_KEY);
    }

    private void getSprintIssuesByGitLink(PmsProjectSprintDetailVo pmsProjectSprintDetailVo, PmsProjectSprintIssuesSearchVo pmsProjectSprintIssuesSearchVo) {
        JSONObject searchObj = new JSONObject();
        convertObjectToJSONObject(pmsProjectSprintIssuesSearchVo, searchObj, null);
        searchObj.put("pm_sprint_id", pmsProjectSprintDetailVo.getId());
        searchObj.keySet().stream()
                .filter(key -> searchObj.get(key) != null)
                .forEach(key -> searchObj.put(key, String.valueOf(searchObj.get(key))));
        JSONObject issues = null;
        try {
            issues = pmsProjectIssuesService.setProjectIssueListUserState(gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_ISSUE_LIST(searchObj)));
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        pmsProjectSprintDetailVo.setIssues(issues);
    }

    private JSONObject getSprintIssuesStatisticsByGitLink(String projectSprintIds) {
        JSONObject result = gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_SPRINT_ISSUES_STATISTICS(projectSprintIds));
        return result.getJSONObject(DATA_KEY);
    }
}
