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

import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.constant.UserConstants;
import com.microservices.common.core.enums.SystemRole;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.PageUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.enterprise.domain.PmsEnterprise;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
import com.microservices.pms.product.domain.PmsProduct;
import com.microservices.pms.product.domain.vo.PmsProductDataVo;
import com.microservices.pms.product.domain.vo.PmsProductSearchVo;
import com.microservices.pms.product.mapper.PmsProductMapper;
import com.microservices.pms.product.service.IPmsProductModuleService;
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.project.service.IPmsProjectService;
import com.microservices.pms.utils.PmsConstants;
import com.microservices.pms.utils.PmsUtils;
import com.microservices.system.api.RemoteDeptService;
import com.microservices.system.api.domain.SimpleSysUser;
import com.microservices.system.api.domain.SysUser;
import com.microservices.system.api.domain.SysUserDeptRole;
import com.microservices.system.api.utils.FeignUtils;
import org.apache.commons.collections4.ListUtils;
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 java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 产品Service业务层处理
 * 
 * @author otto
 * @date 2023-10-10
 */
@Service
public class PmsProductServiceImpl implements IPmsProductService 
{
    @Autowired
    private PmsProductMapper pmsProductMapper;
    @Autowired
    private IPmsEnterpriseService pmsEnterpriseService;
    @Autowired
    private IPmsCommonService pmsCommonService;
    @Autowired
    @Lazy
    private IPmsProductRequirementService pmsProductRequirementService;
    @Autowired
    @Lazy
    private IPmsProductPlanService pmsProductPlanService;
    @Autowired
    @Lazy
    private IPmsProductModuleService pmsProductModuleService;
    @Autowired
    private RemoteDeptService remoteDeptService;
    @Autowired
    @Lazy
    private IPmsProjectService pmsProjectService;

    /**
     * 查询产品
     * 
     * @param id 产品主键
     * @return 产品
     */
    @Override
    public PmsProduct selectPmsProductById(Long id)
    {
        PmsProduct pmsProduct= pmsProductMapper.selectPmsProductById(id);
        if(pmsProduct==null){
            throw new ServiceException("该产品不存在(产品ID[%s])",id);
        }
        pmsEnterpriseService.selectPmsEnterpriseById(pmsProduct.getPmsEnterpriseId());
        return pmsProduct;
    }

    /**
     * 查询产品列表
     * 
     * @param pmsProduct 产品
     * @return 产品
     */
    @Override
    public GenericsTableDataInfo<PmsProductDataVo> selectPmsProductPageList(PmsProductSearchVo pmsProduct)
    {
        HashMap<String, Object> selectCache = new HashMap<>();
        return PageUtils.toPage(pmsProductMapper.selectPmsProductList(pmsProduct), x -> toPmsProductDataVo(x, selectCache));
    }

    private PmsProductDataVo toPmsProductDataVo(PmsProduct pmsProduct, HashMap<String, Object> hashMap) {
        PmsProductDataVo pmsProductDataVo = pmsProduct.toPmsProductDataVo();
        // 设置需求负责人
        pmsProductDataVo.setProductAssigneeList(
                pmsCommonService.getSimpleSysUserListByGitlinkUserIdsAndCache(pmsProduct.getProductAssigneeGitlinkIds(), hashMap));
        return pmsProductDataVo;
    }

    /**
     * 新增产品
     * 
     * @param pmsProduct 产品
     * @return 结果
     */
    @Override
    public String insertPmsProduct(PmsProduct pmsProduct) {
        PmsEnterprise pmsEnterprise = pmsEnterpriseService.selectPmsEnterpriseByIdentifier(pmsProduct.getPmsEnterpriseIdentifier());
        checkNameDuplicates(pmsProduct.getProductName(), pmsProduct.getPmsEnterpriseIdentifier());
        Integer count = pmsProductMapper.selectPmsProductByIdentifierCount(pmsProduct.getProductIdentifier(), pmsEnterprise.getEnterpriseIdentifier());
        if (count > 0) {
            throw new ServiceException("该产品标识在当前企业下已存在(产品标识[%s])", pmsProduct.getProductIdentifier());
        }
        pmsProduct.setPmsEnterpriseId(pmsEnterprise.getId());
        String currentUsername=SecurityUtils.getUsername();
        Date now=DateUtils.getNowDate();
        pmsProduct.setCreateBy(currentUsername);
        pmsProduct.setCreateTime(now);
        pmsProduct.setUpdateBy(currentUsername);
        pmsProduct.setUpdateTime(now);
        //处理指派负责人逻辑(默认传递过来的是GitLink用户ID，需同步创建系统用户同时使用GitLink用户ID)
        checkProductAssigneeGitlinkId(pmsProduct.getProductAssigneeGitlinkIds(), pmsEnterprise);

        pmsProduct.setPmsEnterpriseId(pmsProduct.getPmsEnterpriseId());
        pmsProduct.setDeptId(pmsEnterprise.getDeptId());

        pmsProductMapper.insertPmsProduct(pmsProduct);
        return pmsProduct.getProductIdentifier();
    }

    private void checkNameDuplicates(String name, String pmsEnterpriseIdentifier) {
        Integer count = pmsProductMapper.selectPmsProductByNameCount(name, pmsEnterpriseIdentifier);
        if(count>0){
            throw new ServiceException("该产品名称在当前企业下已存在(产品名称[%s])",name);
        }
    }

    private void checkProductAssigneeGitlinkId(String gitlinkUserIdsStr, PmsEnterprise pmsEnterprise) {
        if (StringUtils.isEmpty(gitlinkUserIdsStr)) {
            return;
        }
        try {
            String[] gitlinkUserIds = gitlinkUserIdsStr.split(",");
            for (String gitlinkUserIdStr : gitlinkUserIds) {
                Long gitlinkUserId = Long.valueOf(gitlinkUserIdStr);
                SysUser productAssigneeUser = pmsCommonService.getSysUserByGitlinkId(gitlinkUserId);
                Boolean hasPerms = FeignUtils.getReturnData(
                        remoteDeptService.checkUserInDeptHasPerms(pmsEnterprise.getDeptId(), productAssigneeUser.getUserId(), UserConstants.PMS_PERMS_PRODUCT_EDIT, SecurityConstants.INNER)
                );
                if (hasPerms == null || !hasPerms) {
                    throw new ServiceException("该用户没有产品编辑权限，无法被选定为产品负责人(用户名[%s])", productAssigneeUser.getUserName());
                }
                boolean isExist = pmsEnterpriseService.checkUserInEnterprise(pmsEnterprise.getId(), productAssigneeUser.getUserId());
                if (!isExist) {
                    throw new ServiceException("该产品的负责人不在当前企业中(企业名称[%s],用户名[%s])", pmsEnterprise.getEnterpriseName(), productAssigneeUser.getUserName());
                }
            }
        } catch (NumberFormatException e) {
            throw new ServiceException("指派的产品负责人Id格式异常(产品负责人Id列表[%s])", gitlinkUserIdsStr);
        }
    }

    private String genProductIdentifier(){
        String identifier=PmsUtils.generateRandomProductIdentifier();
        PmsProduct pmsProduct=pmsProductMapper.selectPmsProductByIdentifier(identifier);
        while (pmsProduct!=null){
            identifier=PmsUtils.generateRandomProductIdentifier();
            pmsProduct=pmsProductMapper.selectPmsProductByIdentifier(identifier);
        }
        return identifier;
    }

    /**
     * 修改产品
     * 
     * @param pmsProduct 产品
     * @return 结果
     */
    @Override
    public int updatePmsProduct(PmsProduct pmsProduct)
    {
        PmsProduct oldPmsProduct = selectPmsProductByIdentifier(pmsProduct.getProductIdentifier());
        checkManageRole(oldPmsProduct);
        PmsEnterprise pmsEnterprise = pmsEnterpriseService.selectPmsEnterpriseById(oldPmsProduct.getPmsEnterpriseId());
        if(StringUtils.isNotEmpty(pmsProduct.getProductName())
        &&!pmsProduct.getProductName().equals(oldPmsProduct.getProductName())){
            checkNameDuplicates(pmsProduct.getProductName(), pmsEnterprise.getEnterpriseIdentifier());
        }
        // 考虑到用户有可能已离职，所以仅对新增的用户进行权限校验
        checkProductAssigneeGitlinkId(
                getNewAssigneeGitlinkIds(oldPmsProduct.getProductAssigneeGitlinkIds(), pmsProduct.getProductAssigneeGitlinkIds()), pmsEnterprise);
        pmsProduct.setUpdateBy(SecurityUtils.getUsername());
        pmsProduct.setUpdateTime(DateUtils.getNowDate());
        pmsProduct.setId(oldPmsProduct.getId());
        return pmsProductMapper.updatePmsProduct(pmsProduct);
    }

    private String getNewAssigneeGitlinkIds(String oldAssigneeGitlinkIds, String newAssigneeGitlinkIds) {
        List<String> oldGitlinkUserIds = Arrays.asList(oldAssigneeGitlinkIds.split(","));
        List<String> newGitlinkUserIds = Arrays.asList(newAssigneeGitlinkIds.split(","));
        return String.join(",", ListUtils.subtract(newGitlinkUserIds, oldGitlinkUserIds));
    }

    @Override
    public int updatePmsProductChange(String productIdentifier) {
        PmsProduct pmsProduct = selectPmsProductByIdentifier(productIdentifier);
        pmsProduct.setUpdateBy(SecurityUtils.getUsername());
        pmsProduct.setUpdateTime(DateUtils.getNowDate());
        return pmsProductMapper.updatePmsProduct(pmsProduct);
    }

    /**
     * 批量删除产品
     * 
     * @param ids 需要删除的产品主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePmsProductByIds(Long[] ids)
    {
        int success = 0;
        for (Long id : ids) {
            success += deletePmsProductById(id);
        }
        return success;
    }

    /**
     * 删除产品信息
     * 
     * @param id 产品主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePmsProductById(Long id)
    {
        PmsProduct pmsProduct = selectPmsProductById(id);
        // 删除产品下所有需求
        pmsProductRequirementService.deletePmsProductRequirementByProductIdentifier(pmsProduct.getProductIdentifier());
        // 删除产品下所有计划
        pmsProductPlanService.deletePmsProductPlanByProductIdentifier(pmsProduct.getProductIdentifier());
        // 删除产品下所有模块
        pmsProductModuleService.deletePmsProductModuleByProductIdentifier(pmsProduct.getProductIdentifier());
        // 清理项目管理关联的产品信息
        pmsProjectService.clearPmsProjectAndProductAssociations(pmsProduct.getId());
        return pmsProductMapper.deletePmsProductById(id);
    }

    @Override
    public PmsProduct selectPmsProductByIdentifier(String identifier) {
        PmsProduct pmsProduct= pmsProductMapper.selectPmsProductByIdentifier(identifier);
        if(pmsProduct==null){
            throw new ServiceException("该产品不存在(产品标识[%s])",identifier);
        }
        pmsEnterpriseService.selectPmsEnterpriseById(pmsProduct.getPmsEnterpriseId());
        return pmsProduct;
    }

    @Override
    public int updatePmsProductTop(String identifier) {
        PmsProduct pmsProduct=selectPmsProductByIdentifier(identifier);
        checkManageRole(pmsProduct);
        if(PmsConstants.TRUE.equals(pmsProduct.getIsTop())){
            pmsProduct.setIsTop(PmsConstants.FALSE);
        }else{
            pmsProduct.setIsTop(PmsConstants.TRUE);
        }
        return pmsProductMapper.updatePmsProduct(pmsProduct);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePmsProductByIdentifier(String identifier) {
        PmsProduct pmsProduct = selectPmsProductByIdentifier(identifier);
        checkManageRole(pmsProduct);
        return deletePmsProductById(pmsProduct.getId());
    }

    @Override
    public Integer selectPmsProductCount(PmsProductSearchVo pmsProductSearchVo) {
        return pmsProductMapper.selectPmsProductCount(pmsProductSearchVo);
    }

    @Override
    public PmsProductDataVo selectPmsProductDataVoByIdentifier(String identifier) {
        return toPmsProductDataVo(selectPmsProductByIdentifier(identifier), null);
    }

    @Override
    public PmsProductDataVo selectPmsProductDataVoById(Long id) {
        return toPmsProductDataVo(selectPmsProductById(id), null);
    }

    @Override
    public List<PmsProduct> selectPmsProductList(PmsProductSearchVo pmsProductSearch) {
        return pmsProductMapper.selectPmsProductList(pmsProductSearch);
    }

    public void checkManageRole(PmsProduct pmsProduct) {
        // 仅允许组织管理员和产品负责人操作当前产品
        SysUserDeptRole userIdentify = SecurityUtils.getUserIdentity();
        if (userIdentify != null
                && userIdentify.getSysRole() != null) {
            if (SystemRole.PMS_ORG_ADMIN.getRoleKey().equals(userIdentify.getSysRole().getRoleKey())) {
                return;
            }
        }

        if (SecurityUtils.getGitlinkUserId() != null && StringUtils.isNotEmpty(pmsProduct.getProductAssigneeGitlinkIds())) {
            String currentGitlinkUserIdStr = SecurityUtils.getGitlinkUserId().toString();
            String[] gitlinkUserIdsStr = pmsProduct.getProductAssigneeGitlinkIds().split(",");
            for (String gitlinkUserIdStr : gitlinkUserIdsStr) {
                if (currentGitlinkUserIdStr.equals(gitlinkUserIdStr)) {
                    return;
                }
            }
        }
        throw new ServiceException("您不是产品负责人，暂无操作权限");
    }

    @Override
    public GenericsTableDataInfo<SimpleSysUser> getUserList(String enterpriseIdentifier, String search) {
        return pmsEnterpriseService.getUserListByPerms(enterpriseIdentifier, search, UserConstants.PMS_PERMS_PRODUCT_EDIT);
    }

    @Override
    public PmsProductDataVo selectPmsProductDataByIdentifier(String identifier) {
        PmsProduct pmsProduct = selectPmsProductByIdentifier(identifier);
        return toPmsProductDataVo(pmsProduct, null);
    }
}
