package com.microservices.pms.dashboard.controller;

import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.bean.BeanUtils;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.dashboard.domain.vo.MyDashboardVo;
import com.microservices.pms.dashboard.domain.vo.MyProjectIssuesSearchVo;
import com.microservices.pms.dashboard.domain.vo.MyTodoProjectIssuesSearchVo;
import com.microservices.pms.product.domain.PmsProduct;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.PmsProductStatus;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.product.domain.vo.*;
import com.microservices.pms.product.service.IPmsProductPlanService;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.product.service.IPmsProductService;
import com.microservices.pms.product.service.IPmsProductStatusService;
import com.microservices.pms.project.domain.PmsProject;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.service.IPmsProjectService;
import com.microservices.pms.project.service.IPmsProjectSprintService;
import com.microservices.pms.project.service.PmsProjectIssuesService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.microservices.pms.utils.PmsConstants.PRODUCT_PLAN_CLOSED_STATUS_NAME;

@RestController
@RequestMapping("/{enterpriseIdentifier}/dashboard")
@Api(tags = "项目管理-工作台")
@ApiImplicitParams({@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")})
public class PmsDashboardController extends BaseController {

    @Autowired
    private IPmsProjectService pmsProjectService;

    @Autowired
    private PmsProjectIssuesService pmsProjectIssuesService;

    @Autowired
    private IPmsProjectSprintService pmsProjectSprintService;

    @Autowired
    private IPmsProductRequirementService pmsProductRequirementService;

    @Autowired
    private IPmsProductService pmsProductService;

    @Autowired
    private IPmsProductPlanService pmsProductPlanService;

    @Autowired
    private IPmsProductStatusService pmsProductStatusService;


    /**
     * 我的工作台统计信息
     */
    @ApiOperation(value = "我的工作台统计信息")
    @GetMapping("/statistics")
    public AjaxResult statistics(@PathVariable String enterpriseIdentifier) {
        List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
        PmsProductSearchVo pmsProductSearchVo = new PmsProductSearchVo();
        pmsProductSearchVo.setPmsEnterpriseIdentifier(enterpriseIdentifier);
        List<PmsProduct> pmsProductList = pmsProductService.selectPmsProductList(pmsProductSearchVo);
        MyDashboardVo myDashboardVo = new MyDashboardVo();
        if (!projectList.isEmpty()) {
            IssueTypeTotalCountVo issueTypeTotalCountVo = pmsProjectService.getIssueTypeProjectIssuesTotalCount(projectList.stream().map(PmsProject::getId).map(String::valueOf).collect(Collectors.toList()));
            BeanUtils.copyProperties(issueTypeTotalCountVo, myDashboardVo);
        }
        if (!pmsProductList.isEmpty()) {
            PmsProductRequirement pmsProductRequirement = new PmsProductRequirement();
            pmsProductRequirement.setProductIdentifierList(pmsProductList.stream().map(PmsProduct::getProductIdentifier).collect(Collectors.toList()));
            pmsProductRequirement.setCreateBy(SecurityUtils.getUsername());
            Integer requirementCount = pmsProductRequirementService.selectProductReqSpecsCount(pmsProductRequirement);
            myDashboardVo.setProductRequirementCount(requirementCount);

            long assignedMeProductCount = pmsProductList.stream()
                    .filter(pmsProduct -> pmsProduct.getProductAssigneeGitlinkIds().contains(String.valueOf(SecurityUtils.getGitlinkUserId())))
                    .count();
            myDashboardVo.setAssignedMeProductCount((int) assignedMeProductCount);
        }
        return success(myDashboardVo);
    }

    /**
     * 我的工作项
     */
    @GetMapping("/myProjectIssues")
    @ApiOperation(value = "我的工作项")
    public AjaxResult myProjectIssues(MyProjectIssuesSearchVo myProjectIssuesSearchVo) {

        List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
        if(projectList.isEmpty()){
            return success();
        }
        myProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
        JSONObject result = pmsProjectIssuesService.selectMyPmsProjectIssuesList(myProjectIssuesSearchVo);
        return success(result);
    }

    /**
     * 我的项目
     */
    @ApiOperation(value = "我的项目")
    @GetMapping("/myProjects")
    @ApiImplicitParams({@ApiImplicitParam(name = "pageNum", value = "当前记录起始索引", paramType = "query", dataType = "Integer"), @ApiImplicitParam(name = "pageSize", value = "每页显示记录数", paramType = "query", dataType = "Integer"), @ApiImplicitParam(name = "orderByColumn", value = "排序列（更新时间：updateTime，创建时间：createTime）", paramType = "query", dataType = "String"), @ApiImplicitParam(name = "isAsc", value = "排序的方向desc或者asc,默认asc", paramType = "query", dataType = "String")})
    public GenericsTableDataInfo<PmsProjectDetailVo> myProjects(PmsProjectSearchVo pmsProjectSearchVo) {
        return pmsProjectService.selectPmsProjectList(pmsProjectSearchVo);
    }

    /**
     * 我的项目-项目情况统计
     */
    @ApiOperation(value = "我的项目-项目统计")
    @GetMapping("/myProjects/statistics")
    public AjaxResult myProjectStatistics(@ApiParam("项目id") @RequestParam Long pmProjectId) {
        return success(pmsProjectService.getMyProjectStatistics(pmProjectId));
    }

    /**
     * 我的仓库-仓库情况统计
     */
    @ApiOperation(value = "我的仓库-仓库情况统计")
    @GetMapping("/myRepositories/statistics")
    public AjaxResult myRepositoriesStatistics(@ApiParam("仓库id") @RequestParam Long repositoryId) {
        return success(pmsProjectService.getMyRepositoriesStatistics(repositoryId));
    }


    /**
     * 我的迭代
     */
    @ApiOperation(value = "我的迭代")
    @GetMapping("/myProjectSprints")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前记录起始索引", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "pageSize", value = "每页显示记录数", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "orderByColumn", value = "排序列（更新时间：updateTime，创建时间：createTime）", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "isAsc", value = "排序的方向desc或者asc,默认asc", paramType = "query", dataType = "String")
    })
    public GenericsTableDataInfo<PmsProjectSprintDetailVo> myProjectSprints(PmsProjectSprintSearchVo pmsProjectSprintSearchVo) {
        List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
        if(projectList.isEmpty()){
            return new GenericsTableDataInfo<>();
        }
        pmsProjectSprintSearchVo.setPmsProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
        return pmsProjectSprintService.selectAllPmsProjectSprintList(pmsProjectSprintSearchVo);
    }

    /**
     * 我的待办
     */
    @GetMapping("/todo")
    @ApiOperation(value = "我的待办")
    public AjaxResult todoProjectIssues(MyTodoProjectIssuesSearchVo todoProjectIssuesSearchVo) {
        List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
        if(projectList.isEmpty()){
            return success();
        }
        todoProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
        JSONObject result = pmsProjectIssuesService.selectMyTodoPmsProjectIssuesList(todoProjectIssuesSearchVo);

        // 判断projectList中是否存在projectAssigneeId和当前用户id相等
        Long currentUserId = SecurityUtils.getGitlinkUserId();
        boolean isProjectAssigner = projectList.stream()
                .anyMatch(project -> currentUserId != null && currentUserId.equals(project.getProjectAssigneeId()));
        result.put("isProjectAssigner", isProjectAssigner);
        return success(result);
    }

    /**
     * 我的产品
     */
    @ApiOperation(value = "我的产品")
    @GetMapping("/myProduct")
    public GenericsTableDataInfo<PmsProductStatVo> myProduct(@PathVariable String enterpriseIdentifier,
                                                             @Validated PmsProductSearchVo pmsProductSearchVo) {
        startPage();
        pmsProductSearchVo.setPmsEnterpriseIdentifier(enterpriseIdentifier);
        //获取组织下所有的产品信息
        GenericsTableDataInfo<PmsProductDataVo> productsInfo = pmsProductService.selectPmsProductPageList(pmsProductSearchVo);
        List<PmsProductDataVo> rows = productsInfo.getRows();

        // 统计需求数量
        List<PmsProductStatVo> statVos = rows.stream().map(e -> {
            PmsProductStatVo statVo = new PmsProductStatVo();
            String pmsProductIdentifier = e.getProductIdentifier();
            Integer requirementCount = pmsProductRequirementService.countByIdentifierAndStatus(pmsProductIdentifier, getUserReqList());
            Integer reqSpecsCount = pmsProductRequirementService.countByIdentifierAndStatus(pmsProductIdentifier, getTotalReqSpecsList());
            BeanUtils.copyProperties(e, statVo);
            statVo.setReqSpecsCount(reqSpecsCount);
            statVo.setUserReqCount(requirementCount);
            return statVo;
        }).collect(Collectors.toList());

        GenericsTableDataInfo<PmsProductStatVo> result = new GenericsTableDataInfo<>();
        result.setRows(statVos);
        result.setTotal(productsInfo.getTotal());
        return result;
    }

    @ApiOperation(value = "我的产品数据统计-原始需求统计")
    @ApiImplicitParam(name = "productIdentifier", value = "产品标识", paramType = "query", dataType = "String")
    @GetMapping("/userRequirementStat")
    public R<PmsRequirementStatResVo> UserRequirementStat(String productIdentifier){
        PmsRequirementStatResVo pmsRequirementStatResVo = buildPmsRequirementStatResVo(
                productIdentifier,
                getUserReqList(),
                ProductReqStatus.REVIEWED_USER_REQ);

        return R.ok(pmsRequirementStatResVo);
    }


    @ApiOperation(value = "我的产品数据统计-需求统计")
    @ApiImplicitParam(name = "productIdentifier", value = "产品标识", paramType = "query", dataType = "String")
    @GetMapping("/productRequirementSpecsStat")
    public R<PmsRequirementStatResVo> ProductRequirementSpecsStat(String productIdentifier){
        PmsRequirementStatResVo pmsRequirementStatResVo = buildPmsRequirementStatResVo(
                productIdentifier,
                getReqSpecsList(),
                ProductReqStatus.COMPLETED_REQ_SPECS);
        return R.ok(pmsRequirementStatResVo);
    }

    @ApiOperation(value = "我的产品数据统计-里程碑状态分布统计")
    @ApiImplicitParam(name = "productIdentifier", value = "产品标识", paramType = "query", dataType = "String")
    @GetMapping("/milestoneStatusStat")
    public R<PmsRequirementStatResVo> milestoneStatusStat(String productIdentifier){
        Map<String, Integer> status2NumMap = pmsProductPlanService.countPmsProductPlanGroupByStatus(productIdentifier)
                .stream().collect(Collectors.toMap(EnumCommonVo::getKey, ReqStatusStatVo::getNum));
        PmsProductStatus pmsProductStatus = new PmsProductStatus();
        pmsProductStatus.setType(1);
        List<PmsTypeDataVo> pmsTypeDataVos = pmsProductStatusService.selectPmsProductStatusList(pmsProductStatus);
        List<ReqStatusStatVo> statusStatVos = pmsTypeDataVos.stream().filter(e -> !PRODUCT_PLAN_CLOSED_STATUS_NAME.equals(e.getName())).map(e -> {
            ReqStatusStatVo vo = new ReqStatusStatVo();
            vo.setKey(String.valueOf(e.getId()));
            vo.setNum(status2NumMap.getOrDefault(String.valueOf(e.getId()), 0));
            vo.setName(e.getName());
            return vo;
        }).collect(Collectors.toList());
        PmsRequirementStatResVo resVo = new PmsRequirementStatResVo();
        resVo.setPmsProductStatVos(statusStatVos);
        resVo.setRatio(0);
        return R.ok(resVo);
    }


    /**
     * 获取 统计饼图所需的需求状态list
     * @return 需求状态list
     */
    private List<String> getReqSpecsList() {
      return Stream.of(ProductReqStatus.PENDING_REVIEW_REQ_SPECS.getKey(),
                      ProductReqStatus.PLANNED_REQ_SPECS.getKey(),
                      ProductReqStatus.REJECTED_REQ_SPECS.getKey(),
                      ProductReqStatus.REVIEWED_REQ_SPECS.getKey(),
                      ProductReqStatus.COMPLETED_REQ_SPECS.getKey())
              .collect(Collectors.toList());
    }

    /**
     * 获取Count总数时，需求的状态list
     * @return 需求状态list
     */
    private List<String> getTotalReqSpecsList() {
        return Stream.of(ProductReqStatus.PENDING_REVIEW_REQ_SPECS.getKey(),
                        ProductReqStatus.PLANNED_REQ_SPECS.getKey(),
                        ProductReqStatus.REJECTED_REQ_SPECS.getKey(),
                        ProductReqStatus.REVIEWED_REQ_SPECS.getKey(),
                        ProductReqStatus.COMPLETED_REQ_SPECS.getKey(),
                        ProductReqStatus.CHANGING_REQ_SPECS.getKey())
                .collect(Collectors.toList());
    }

    /**
     * 获取 原始需求状态list
     * @return 原始需求状态list
     */
    private List<String> getUserReqList() {
       return Stream.of(ProductReqStatus.PENDING_REVIEW_USER_REQ.getKey(),
                        ProductReqStatus.REJECTED_USER_REQ.getKey(),
                        ProductReqStatus.REVIEWED_USER_REQ.getKey())
                .collect(Collectors.toList());
    }

    /**
     * 拼接统计返回结果
     * @param productIdentifier 产品标识
     * @param statusList 状态列表
     * @param productReqStatus x
     * @return
     */
    private PmsRequirementStatResVo buildPmsRequirementStatResVo(String productIdentifier,List<String> statusList, ProductReqStatus productReqStatus) {
        Map<String, Integer> status2NumMap = pmsProductRequirementService
                .selectReqCountGroupByStatus(productIdentifier, statusList)
                .stream().collect(Collectors.toMap(EnumCommonVo::getKey, ReqStatusStatVo::getNum));

        //组装各个状态的数量
        List<ReqStatusStatVo> statusStatVos = statusList.stream().map(e -> {
            ReqStatusStatVo vo = new ReqStatusStatVo();
            vo.setKey(e);
            vo.setNum(status2NumMap.getOrDefault(e, 0));
            vo.setName(ProductReqStatus.getByKey(e).getName());
            return vo;
        }).collect(Collectors.toList());

        PmsRequirementStatResVo resVo = new PmsRequirementStatResVo();
        resVo.setPmsProductStatVos(statusStatVos);
        resVo.setRatio(0);
        //计算 各自的比率
        int sum = statusStatVos.stream().mapToInt(ReqStatusStatVo::getNum).sum();
        if (sum > 0) {
            Integer completedReqSpecsCount = status2NumMap.getOrDefault(productReqStatus.getKey(), 0);
            double ratioDouble = (double) completedReqSpecsCount / sum * 100;
            int ratio = (int) Math.round(ratioDouble);
            resVo.setRatio(ratio);
        }
        return resVo;
    }
}
