package org.dromara.zjk.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.zjk.domain.*;
import org.dromara.zjk.domain.bo.ZjkProductBo;
import org.dromara.zjk.domain.dto.ProjectSummaryStatistics;
import org.dromara.zjk.domain.vo.*;
import org.dromara.zjk.enums.ApprovalStatusEnum;
import org.dromara.zjk.enums.BusinessTypeEnum;
import org.dromara.zjk.enums.ChangeTypeEnum;
import org.dromara.zjk.expert.expertPaper.domain.ZjkExpertPaper;
import org.dromara.zjk.expert.expertPaper.service.IZjkExpertPaperService;
import org.dromara.zjk.expert.expertPatent.domain.ZjkExpertPatent;
import org.dromara.zjk.expert.expertPatent.service.IZjkExpertPatentService;
import org.dromara.zjk.mapper.*;
import org.dromara.zjk.service.IZjkDataChangesLogsService;
import org.dromara.zjk.service.IZjkProductService;
import org.dromara.zjk.service.IZjkProductSummarizeService;
import org.dromara.zjk.utils.FieldChangeRecorderUtils;
import org.dromara.zjk.zwy.client.HmacClient;
import org.dromara.zjk.zwy.utils.ObjectHashGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目管理Service业务层处理
 *
 * @author ygh
 * @date 2024-11-01
 */
@RequiredArgsConstructor
@Service
public class ZjkProductServiceImpl implements IZjkProductService {

    private static final Logger log = LoggerFactory.getLogger(ZjkProductServiceImpl.class);
    private final ZjkProductMapper baseMapper;

    private final ZjkExpertItemMapper zjkExpertItemMapper;

    private final ZjkReviewPhaseMapper zjkReviewPhaseMapper;

    private final ZjkExpertMapper zjkExpertMapper;

    private final IZjkProductSummarizeService zjkProductSummarizeService;

    private final IZjkDataChangesLogsService zjkDataChangesLogsService;

    private final IZjkExpertPaperService zjkExpertPaperService;

    private final IZjkExpertPatentService zjkExpertPatentService;

    private final ZjkProductReviewsnMapper zjkProductReviewsnMapper;

    private final HmacClient hmacClient;
    /**
     * 查询项目管理
     *
     * @param id 主键
     * @return 项目管理
     */
    @Override
    public ZjkProductVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询项目管理列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 项目管理分页列表
     */
    @Override
    public TableDataInfo<ZjkProductVo> queryPageList(ZjkProductBo bo, PageQuery pageQuery) {
        //LambdaQueryWrapper<ZjkProduct> lqw = buildQueryWrapper(bo);
        Page<ZjkProductVo> result = baseMapper.selectProdoctPage(pageQuery.build(), bo);
        List<ZjkProductVo> records = result.getRecords();
        if (CollectionUtil.isEmpty(records)) {
            return TableDataInfo.build(result);
        }
        Set<Long> productIdSet = records.stream().map(ZjkProductVo::getId).collect(Collectors.toSet());

        List<ZjkReviewProductVo> byProductIds = zjkReviewPhaseMapper.getByProductIds(productIdSet);
        if (CollectionUtil.isEmpty(byProductIds)) {
            return TableDataInfo.build(result);
        }
        Map<Long, ZjkReviewProductVo> collect = byProductIds.stream().collect(Collectors.toMap(ZjkReviewProductVo::getProductId, v -> v, (k1, k2) -> k1));
        for (ZjkProductVo record : records) {
            Long productId = record.getId();
            if (collect.containsKey(productId)) {
                record.setIsItem(1);
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的项目管理列表
     *
     * @param bo 查询条件
     * @return 项目管理列表
     */
    @Override
    public List<ZjkProductVo> queryList(ZjkProductBo bo) {
        LambdaQueryWrapper<ZjkProduct> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ZjkProduct> buildQueryWrapper(ZjkProductBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ZjkProduct> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getProductSn()), ZjkProduct::getProductSn, bo.getProductSn());
        lqw.in(!CollectionUtil.isEmpty(bo.getIds()), ZjkProduct::getId, bo.getIds());
        lqw.like(StringUtils.isNotBlank(bo.getProductName()), ZjkProduct::getProductName, bo.getProductName());
        lqw.eq(StringUtils.isNotBlank(bo.getProductType()), ZjkProduct::getProductType, bo.getProductType());
        lqw.eq(StringUtils.isNotBlank(bo.getProductScale()), ZjkProduct::getProductScale, bo.getProductScale());
        lqw.eq(StringUtils.isNotBlank(bo.getProductUnit()), ZjkProduct::getProductUnit, bo.getProductUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitBy()), ZjkProduct::getUnitBy, bo.getUnitBy());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitConcat()), ZjkProduct::getUnitConcat, bo.getUnitConcat());
        lqw.eq(StringUtils.isNotBlank(bo.getProductBrief()), ZjkProduct::getProductBrief, bo.getProductBrief());
        lqw.eq(StringUtils.isNotBlank(bo.getProductDataUrl()), ZjkProduct::getProductDataUrl, bo.getProductDataUrl());
        lqw.like(StringUtils.isNotBlank(bo.getSearch()), ZjkProduct::getProductSn, bo.getSearch()).or().
            like(StringUtils.isNotBlank(bo.getSearch()), ZjkProduct::getProductSn, bo.getSearch());
        return lqw;
    }

    /**
     * 新增项目管理
     *
     * @param bo 项目管理
     * @return 是否新增成功
     */
/*    @Override
    public Boolean insertByBo(ZjkProductBo bo) {
        ZjkProduct add = MapstructUtils.convert(bo, ZjkProduct.class);
        validEntityBeforeSave(add);
        String productSn = bo.getProductSn();
        LambdaQueryWrapper<ZjkProduct> lqw = Wrappers.lambdaQuery();
        lqw.eq(ZjkProduct::getProductSn, productSn);
        lqw.eq(ZjkProduct::getUserId, LoginHelper.getUserId());
        List<ZjkProductVo> zjkProductVos = baseMapper.selectVoList(lqw);
        if (CollectionUtil.isNotEmpty(zjkProductVos)) {
            throw new ServiceException("项目编号已存在");
        }
        String productName = bo.getProductName();
        LambdaQueryWrapper<ZjkProduct> lqwProduct = Wrappers.lambdaQuery();
        lqwProduct.eq(ZjkProduct::getProductName, productName);
        lqwProduct.eq(ZjkProduct::getUserId, LoginHelper.getUserId());
        List<ZjkProductVo> zjkProductVos1 = baseMapper.selectVoList(lqwProduct);
        if (CollectionUtil.isNotEmpty(zjkProductVos1)) {
            throw new ServiceException("项目名称已存在");
        }
        add.setUserId(LoginHelper.getUserId());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }*/
    @Override
    public Boolean insertByBo(ZjkProductBo bo) {
        ZjkProduct add = MapstructUtils.convert(bo, ZjkProduct.class);
        validEntityBeforeSave(add);
        //新增时设置项目状态为待审批，机构管理员角色时审批状态为已审批
        boolean contains = LoginHelper.getLoginUser().getRolePermission().contains(TenantConstants.JG_ROLE_KEY);
        if (contains) {
            add.setApprovalStatus(ApprovalStatusEnum.SUCCESS.getCode());
        } else {
            add.setApprovalStatus(ApprovalStatusEnum.APPROVAL.getCode());
        }
        Long userId = LoginHelper.getUserId();

        // 唯一性校验：项目编号
        LambdaQueryWrapper<ZjkProduct> lqw = Wrappers.lambdaQuery();
        lqw.eq(ZjkProduct::getProductSn, bo.getProductSn());
        lqw.eq(ZjkProduct::getUserId, userId);
        if (CollectionUtil.isNotEmpty(baseMapper.selectVoList(lqw))) {
            throw new ServiceException("项目编号已存在");
        }

        // 唯一性校验：项目名称
        LambdaQueryWrapper<ZjkProduct> lqwProduct = Wrappers.lambdaQuery();
        lqwProduct.eq(ZjkProduct::getProductName, bo.getProductName());
        lqwProduct.eq(ZjkProduct::getUserId, userId);
        if (CollectionUtil.isNotEmpty(baseMapper.selectVoList(lqwProduct))) {
            throw new ServiceException("项目名称已存在");
        }

        // 插入前设置用户
        add.setUserId(userId);

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());

            try {
                // 再查一次，确保取到数据库生成的所有字段

                ZjkProduct dbProduct = baseMapper.selectById(add.getId());
                ZjkProductVo entity = MapstructUtils.convert(dbProduct, ZjkProductVo.class);

                // 生成 hash 和 hmac
                String hash = ObjectHashGenerator.generateHash(entity);
                String base64 = Base64.getEncoder().encodeToString(hash.getBytes(StandardCharsets.UTF_8));

                String hmac = hmacClient.calculateHmac(base64);
//                String hmac = base64;
                dbProduct.setHmac(hmac);

                baseMapper.updateById(dbProduct);
                log.info("ZjkProduct HMAC 生成成功，ID: {}, HMAC: {}", dbProduct.getId(), hmac);
            } catch (Exception e) {
                log.error("生成 ZjkProduct HMAC 失败", e);
            }
        }

        return flag;
    }

    /**
     * 修改项目管理
     *
     * @param bo 项目管理
     * @return 是否修改成功
     */
   /* @Override
    public Boolean updateByBo(ZjkProductBo bo) {
        ZjkProduct update = MapstructUtils.convert(bo, ZjkProduct.class);
        // 旧数据
        ZjkProduct exist = baseMapper.selectById(bo.getId());
        validEntityBeforeSave(update);

        String productSn = bo.getProductSn();
        LambdaQueryWrapper<ZjkProduct> lqw = Wrappers.lambdaQuery();
        lqw.eq(ZjkProduct::getProductSn, productSn);
        lqw.eq(ZjkProduct::getUserId, LoginHelper.getUserId());
        lqw.ne(ZjkProduct::getId, bo.getId());
        List<ZjkProductVo> zjkProductVos = baseMapper.selectVoList(lqw);
        if (CollectionUtil.isNotEmpty(zjkProductVos)) {
            throw new ServiceException("项目编号已存在");
        }
        String productName = bo.getProductName();
        LambdaQueryWrapper<ZjkProduct> lqw1 = Wrappers.lambdaQuery();
        lqw1.eq(ZjkProduct::getProductName, productName);
        lqw1.eq(ZjkProduct::getUserId, LoginHelper.getUserId());
        lqw1.ne(ZjkProduct::getId, bo.getId());
        List<ZjkProductVo> zjkProductVos1 = baseMapper.selectVoList(lqw1);
        if (CollectionUtil.isNotEmpty(zjkProductVos1)) {
            throw new ServiceException("项目名称已存在");
        }
        try {
            ZjkDataChangesLogs zjkDataChangesLogs = new ZjkDataChangesLogs();
            zjkDataChangesLogs.setBusinessType(BusinessTypeEnum.PROJECT_INFO_CHANGE.getCode());
            zjkDataChangesLogs.setChangeType(ChangeTypeEnum.UPDATE.getCode());
            Map<String, Map<String, Object>> compareAndRecordChanges = FieldChangeRecorderUtils.compareAndRecordChanges(exist, update);
            zjkDataChangesLogs.setBeforeOper(compareAndRecordChanges.get("beforeOper").isEmpty() ? null : JSON.toJSONString(compareAndRecordChanges.get("beforeOper")));
            zjkDataChangesLogs.setAfterOper(compareAndRecordChanges.get("afterOper").isEmpty() ? null : JSON.toJSONString(compareAndRecordChanges.get("afterOper")));
            zjkDataChangesLogsService.insertDataChangesLogs(zjkDataChangesLogs);
        } catch (Exception e) {
            log.error("修改项目 失败{}", e.getMessage());
        }
        return baseMapper.updateById(update) > 0;
    }*/
    @Override
    public Boolean updateByBo(ZjkProductBo bo) {
        ZjkProduct update = MapstructUtils.convert(bo, ZjkProduct.class);
        // 旧数据
        ZjkProduct exist = baseMapper.selectById(bo.getId());
        if(ApprovalStatusEnum.SUCCESS.getCode()==exist.getApprovalStatus()){
            //已通过审批的项目不允许修改删除
            throw new ServiceException("已通过审批的项目或待审核的项目不允许修改删除");
        }
        validEntityBeforeSave(update);

        Long userId = LoginHelper.getUserId();

        // 校验编号唯一
        LambdaQueryWrapper<ZjkProduct> lqw = Wrappers.lambdaQuery();
        lqw.eq(ZjkProduct::getProductSn, bo.getProductSn());
        lqw.eq(ZjkProduct::getUserId, userId);
        lqw.ne(ZjkProduct::getId, bo.getId());
        if (CollectionUtil.isNotEmpty(baseMapper.selectVoList(lqw))) {
            throw new ServiceException("项目编号已存在");
        }

        // 校验名称唯一
        LambdaQueryWrapper<ZjkProduct> lqw1 = Wrappers.lambdaQuery();
        lqw1.eq(ZjkProduct::getProductName, bo.getProductName());
        lqw1.eq(ZjkProduct::getUserId, userId);
        lqw1.ne(ZjkProduct::getId, bo.getId());
        if (CollectionUtil.isNotEmpty(baseMapper.selectVoList(lqw1))) {
            throw new ServiceException("项目名称已存在");
        }

        // 日志记录
        try {
            ZjkDataChangesLogs logEntry = new ZjkDataChangesLogs();
            logEntry.setBusinessType(BusinessTypeEnum.PROJECT_INFO_CHANGE.getCode());
            logEntry.setChangeType(ChangeTypeEnum.UPDATE.getCode());

            Map<String, Map<String, Object>> changeMap =
                FieldChangeRecorderUtils.compareAndRecordChanges(exist, update);
            logEntry.setBeforeOper(changeMap.get("beforeOper").isEmpty() ? null :
                JSON.toJSONString(changeMap.get("beforeOper")));
            logEntry.setAfterOper(changeMap.get("afterOper").isEmpty() ? null :
                JSON.toJSONString(changeMap.get("afterOper")));

            zjkDataChangesLogsService.insertDataChangesLogs(logEntry);
        } catch (Exception e) {
            log.error("修改项目时记录变更日志失败：{}", e.getMessage());
        }

        boolean success = baseMapper.updateById(update) > 0;

        // 重新生成 HMAC
        if (success) {

            try {
                // 再查一次，确保取到数据库生成的所有字段

                ZjkProduct dbProduct = baseMapper.selectById(update.getId());
                ZjkProductVo entity = MapstructUtils.convert(dbProduct, ZjkProductVo.class);

                // 生成 hash 和 hmac
                String hash = ObjectHashGenerator.generateHash(entity);
                String base64 = Base64.getEncoder().encodeToString(hash.getBytes(StandardCharsets.UTF_8));

                String hmac = hmacClient.calculateHmac(base64);
//                String hmac = base64;
                dbProduct.setHmac(hmac);

                baseMapper.updateById(dbProduct);
                log.info("ZjkProduct HMAC 生成成功，ID: {}, HMAC: {}", dbProduct.getId(), hmac);
            } catch (Exception e) {
                log.error("生成 ZjkProduct HMAC 失败", e);
            }
        }

        return success;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ZjkProduct entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除项目管理信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            QueryWrapper<ZjkProduct> wq = new QueryWrapper<>();
            wq.lambda().in(ZjkProduct::getId, ids)
                .in(ZjkProduct::getApprovalStatus, ApprovalStatusEnum.APPROVAL.getCode(), ApprovalStatusEnum.SUCCESS.getCode());
            List<ZjkProduct> zjkProducts = baseMapper.selectList(wq);
            if(!CollectionUtil.isEmpty(zjkProducts)){
                throw new ServiceException("只有已驳回的项目才能删除");
            }
            List<ZjkExpertItemVo> byProductIds = zjkExpertItemMapper.getByProductIds(ids);
            if (CollectionUtil.isNotEmpty(byProductIds)) {
                throw new ServiceException("项目无法删除");
            }
            //删除项目需为已驳回项目

        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public TableDataInfo<ZjkProductVo> getProduct(PageQuery pageQuery, Long userId) {
        if (userId == null) {
            userId = LoginHelper.getUserId();
        }
        Page<ZjkProductVo> result = baseMapper.getProduct(pageQuery.build());
        return TableDataInfo.build(result);
    }

    @Override
    public ItemVO getItemId(Long productId, Long reviewId) {
        return baseMapper.getItemId(productId, reviewId);
    }

    @Override
    public List<ZjkReviewProductVo> getProductReview(Long productId) {

        List<ZjkReviewProductVo> productReview = baseMapper.getProductReview(productId);
        return productReview;
    }

    @Override
    public TableDataInfo<ZjkProduct> queryByList() {
        LambdaQueryWrapper<ZjkProduct> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ZjkProduct::getCreateBy, LoginHelper.getUserId()).eq(ZjkProduct::getApprovalStatus, ApprovalStatusEnum.SUCCESS.getCode());
        List<ZjkProduct> zjkProducts = baseMapper.selectList(wrapper);
        return TableDataInfo.build(zjkProducts);
    }

    @Override
    public TableDataInfo<ProductPanoramaVo> productPanorama(ProductPanoramaVo vo, PageQuery pageQuery) {
        return TableDataInfo.build(baseMapper.productPanorama(vo, pageQuery.build()));
    }

    @Override
    public List<ProductPanoramaDetailVo> getProductPanoramaDetailVoById(Long productId) {
        //查询 项目阶段
        //List<Long> byProductId = zjkReviewPhaseMapper.getByProductId(productId);
        //if (CollectionUtil.isEmpty(byProductId)) {
        //    return new ArrayList<>();
        //}
        LambdaQueryWrapper<ZjkReviewPhase> phaseWrapper = new LambdaQueryWrapper<>();
        phaseWrapper.in(ZjkReviewPhase::getItemId, productId);
        phaseWrapper.eq(ZjkReviewPhase::getEffective, 1);
        List<ZjkReviewPhase> zjkReviewPhases = zjkReviewPhaseMapper.selectList(phaseWrapper);

        // 查询全部 专家
        List<ZjkExpertItemVo> byProductIds = zjkExpertItemMapper.getByProductIds(Arrays.asList(productId));
        if(CollectionUtil.isEmpty(byProductIds)){
            return new ArrayList<>();
        }
        //根据项目阶段 分专家
        Map<Long, List<ZjkExpertItemVo>> reviewMap = byProductIds.stream().collect(Collectors.groupingBy(ZjkExpertItemVo::getReviewId));
        // 查询专家信息
        Set<Long> expertIds = byProductIds.stream().map(ZjkExpertItemVo::getExpertId).collect(Collectors.toSet());
        List<ZjkExpert> zjkExperts = zjkExpertMapper.selectByIds(expertIds);
        Map<Long, ZjkExpert> expertMap = zjkExperts.stream().collect(Collectors.toMap(ZjkExpert::getExpertId, V -> V));

        //查询项目总结
        List<ZjkProductSummarizeVo> expertByProductId = zjkProductSummarizeService.getExpertByProductId(productId);

        Map<String, List<ZjkProductSummarizeVo>> zjkProductSummarizeVoMap = expertByProductId.stream().collect(Collectors.groupingBy(ZjkProductSummarizeVo::getReviewSn));


        List<ProductPanoramaDetailVo> productPanoramaDetailVos = new ArrayList<>();
        for (ZjkReviewPhase zjkReviewPhase : zjkReviewPhases) {
            ProductPanoramaDetailVo detailVo = new ProductPanoramaDetailVo();
            //每个阶段的专家
            List<ZjkExpert> zjkExpertList = new ArrayList<>();
            String reviewSn = zjkReviewPhase.getReviewSn();
            detailVo.setReviewSn(reviewSn);
            detailVo.setReviewTime(zjkReviewPhase.getReviewTime());
            Long reviewId = zjkReviewPhase.getId();
            if (!reviewMap.containsKey(reviewId)) {
                productPanoramaDetailVos.add(detailVo);
                continue;
            }
            List<ZjkExpertItemVo> zjkExpertItemVos = reviewMap.get(reviewId);
            for (ZjkExpertItemVo zjkExpertItemVo : zjkExpertItemVos) {
                ZjkExpert zjkExpert = expertMap.get(zjkExpertItemVo.getExpertId());
                zjkExpertList.add(zjkExpert);
            }
            detailVo.setZjkExpertList(zjkExpertList);
            if (!zjkProductSummarizeVoMap.containsKey(reviewSn)) {
                productPanoramaDetailVos.add(detailVo);
                continue;
            }
            List<ZjkProductSummarizeVo> zjkProductSummarizeVos = zjkProductSummarizeVoMap.get(reviewSn);
            detailVo.setZjkProductSummarizeVoList(zjkProductSummarizeVos);
            detailVo.setProductSummarizeTime(zjkProductSummarizeVos.get(0).getCreateTime());

            productPanoramaDetailVos.add(detailVo);
        }
        return productPanoramaDetailVos;
    }

    //@Override
    //public List<ProductPanoramaDetailVo> getProductPanoramaDetailVoById(Long productId) {
    //    //查询 项目阶段
    //    //List<Long> byProductId = zjkReviewPhaseMapper.getByProductId(productId);
    //    //if (CollectionUtil.isEmpty(byProductId)) {
    //    //    return new ArrayList<>();
    //    //}
    //    LambdaQueryWrapper<ZjkReviewPhase> phaseWrapper = new LambdaQueryWrapper<>();
    //    phaseWrapper.eq(ZjkReviewPhase::getItemId, productId);
    //    //  1 表示有效
    //    phaseWrapper.eq(ZjkReviewPhase::getEffective, 1);
    //    List<ZjkReviewPhaseVo> zjkReviewPhases = zjkReviewPhaseMapper.selectVoList(phaseWrapper);
    //
    //
    //    Map<String, List<ZjkReviewPhaseVo>> phaseMap = zjkReviewPhases.stream().collect(Collectors.groupingBy(ZjkReviewPhaseVo::getReviewSn));
    //
    //    // 查询全部 专家
    //    List<ZjkExpertItemVo> byProductIds = zjkExpertItemMapper.getByProductIds(Arrays.asList(productId));
    //    //根据项目阶段 分专家
    //    Map<Long, List<ZjkExpertItemVo>> reviewMap = byProductIds.stream().collect(Collectors.groupingBy(ZjkExpertItemVo::getReviewId));
    //
    //    // 查询专家信息
    //    Set<Long> expertIds = byProductIds.stream().map(ZjkExpertItemVo::getExpertId).collect(Collectors.toSet());
    //    List<ZjkExpertVo> zjkExperts = zjkExpertMapper.selectVoBatchIds(expertIds);
    //    Map<Long, ZjkExpertVo> expertMap = zjkExperts.stream().collect(Collectors.toMap(ZjkExpertVo::getExpertId, V -> V));
    //
    //    //查询项目总结
    //    List<ZjkProductSummarizeVo> expertByProductId = zjkProductSummarizeService.getExpertByProductId(productId);
    //
    //    Map<String, List<ZjkProductSummarizeVo>> zjkProductSummarizeVoMap = expertByProductId.stream().collect(Collectors.groupingBy(ZjkProductSummarizeVo::getReviewSn));
    //
    //
    //    List<ProductPanoramaDetailVo> productPanoramaDetailVos = new ArrayList<>();
    //
    //    for (String reviewSn : phaseMap.keySet()) {
    //        ProductPanoramaDetailVo detailVo = new ProductPanoramaDetailVo();
    //        List<ZjkReviewPhaseVo> zjkReviewPhaseVoList = new ArrayList<>();
    //        List<ZjkReviewPhaseVo> zjkReviewPhaseVos = phaseMap.get(reviewSn);
    //        if (CollectionUtil.isEmpty(zjkReviewPhaseVos)) {
    //            continue;
    //        }
    //        detailVo.setReviewSn(reviewSn);
    //        // 一个阶段可能多次抽取，循环每次抽取 ，获取到专家
    //        for (ZjkReviewPhaseVo zjkReviewPhaseVo : zjkReviewPhaseVos) {
    //            //每个阶段的专家
    //            List<ZjkExpertVo> zjkExpertVoList = new ArrayList<>();
    //            Long reviewId = zjkReviewPhaseVo.getId();
    //            if (!reviewMap.containsKey(reviewId)) {
    //                continue;
    //            }
    //            List<ZjkExpertItemVo> zjkExpertItemVos = reviewMap.get(reviewId);
    //            //渲染专家信息
    //            for (ZjkExpertItemVo zjkExpertItemVo : zjkExpertItemVos) {
    //                ZjkExpertVo zjkExpert = expertMap.get(zjkExpertItemVo.getExpertId());
    //                zjkExpertVoList.add(zjkExpert);
    //            }
    //            if (CollectionUtil.isEmpty(zjkExpertVoList)) {
    //                continue;
    //            }
    //            zjkReviewPhaseVo.setZjkExpertVoList(zjkExpertVoList);
    //            zjkReviewPhaseVoList.add(zjkReviewPhaseVo);
    //            if (CollectionUtil.isNotEmpty(detailVo.getZjkReviewPhaseVoList())) {
    //                detailVo.getZjkReviewPhaseVoList().addAll(zjkReviewPhaseVos);
    //            } else {
    //                detailVo.setZjkReviewPhaseVoList(zjkReviewPhaseVos);
    //            }
    //        }
    //        if (!zjkProductSummarizeVoMap.containsKey(reviewSn)) {
    //            productPanoramaDetailVos.add(detailVo);
    //            continue;
    //        }
    //        List<ZjkProductSummarizeVo> zjkProductSummarizeVos = zjkProductSummarizeVoMap.get(reviewSn);
    //        if (CollectionUtil.isNotEmpty(zjkProductSummarizeVos)) {
    //            detailVo.setZjkProductSummarizeVoList(zjkProductSummarizeVos);
    //            detailVo.setProductSummarizeTime(zjkProductSummarizeVos.get(0).getCreateTime());
    //        }
    //        productPanoramaDetailVos.add(detailVo);
    //    }
    //    return productPanoramaDetailVos;
    //}

    @Override
    public Long getProductPanoramaCount() {
        LambdaQueryWrapper<ZjkProduct> wrapper = Wrappers.lambdaQuery();
        return baseMapper.selectCount(wrapper);
    }

    @Override
    public List<ZjkProductVo> queryPageListByName(ZjkProductBo bo) {
        LambdaQueryWrapper<ZjkProduct> lambdaQueryWrapper = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lambdaQueryWrapper);
    }

    @Override
    public boolean addBo(ZjkProductBo bo) {
        Long id = bo.getId();
        String reviewSn = bo.getReviewSn();
        if (id == null) {
            throw new ServiceException("id不能为空");
        }
        ZjkProductVo zjkProductVo = baseMapper.selectVoById(id);
        if (zjkProductVo == null) {
            throw new ServiceException("无效项目id");
        }
        ZjkProductReviewsn zjkProductReviewsn = zjkProductReviewsnMapper.selectVoByProductIdReviewSn(id, reviewSn);
        if (zjkProductReviewsn == null) {
            zjkProductReviewsn = BeanUtil.copyProperties(bo, ZjkProductReviewsn.class);
            zjkProductReviewsn.setProductId(id);
            zjkProductReviewsn.setId(null);
            zjkProductReviewsnMapper.insert(zjkProductReviewsn);
        }
        List<ZjkExpertPaper> zjkExpertPaperList = bo.getZjkExpertPaperList();
        if (CollectionUtil.isNotEmpty(zjkExpertPaperList)) {
            for (ZjkExpertPaper zjkExpertPaper : zjkExpertPaperList) {
                zjkExpertPaper.setProductId(zjkProductReviewsn.getId());
                zjkExpertPaper.setReviewSn(reviewSn);
            }
        }
        List<ZjkExpertPatent> zjkExpertPatentsList = bo.getZjkExpertPatentsList();
        if (CollectionUtil.isNotEmpty(zjkExpertPatentsList)) {
            for (ZjkExpertPatent zjkExpertPatent : zjkExpertPatentsList) {
                zjkExpertPatent.setProductId(zjkProductReviewsn.getId());
                zjkExpertPatent.setReviewSn(reviewSn);
            }
        }
        zjkExpertPaperService.saveBatch(zjkExpertPaperList);
        zjkExpertPatentService.saveBatch(zjkExpertPatentsList);
        return true;
    }

    @Override
    public TableDataInfo<ZjkProductVo> selectList(ZjkProductBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ZjkProduct> lambdaQueryWrapper = buildQueryWrapper(bo);
        IPage<ZjkProductVo> zjkProductVoIPage = baseMapper.selectProductReview(pageQuery.build(), bo);
        return TableDataInfo.build(zjkProductVoIPage);
    }

    @Override
    public boolean removeByProductId(Long productReviewId) {
        ZjkProductReviewsnVo zjkProductReviewsnVo = zjkProductReviewsnMapper.selectVoById(productReviewId);
        if (zjkProductReviewsnVo == null) {
            throw new ServiceException("无效id");
        }
        zjkProductReviewsnMapper.deleteById(productReviewId);
        zjkExpertPaperService.deleteByProductId(productReviewId);
        zjkExpertPatentService.deleteByProductId(productReviewId);
        return true;
    }

    @Override
    public ZjkProductVo selectDocumentcByproductId(Long productReviewId) {
        ZjkProductReviewsnVo zjkProductReviewsnVo = zjkProductReviewsnMapper.selectVoById(productReviewId);
        if (zjkProductReviewsnVo == null) {
            throw new ServiceException("无效id");
        }
        Long productId = zjkProductReviewsnVo.getProductId();
        ZjkProductVo zjkProductVo = baseMapper.selectVoById(productId);
        if (zjkProductVo == null) {
            throw new ServiceException("无效项目");
        }
        String reviewSn = zjkProductReviewsnVo.getReviewSn();
        zjkProductVo.setProductId(productId);
        zjkProductVo.setReviewSn(reviewSn);
        zjkProductVo.setProductReviewId(zjkProductReviewsnVo.getId());
        zjkProductVo.setId(zjkProductReviewsnVo.getId());
        List<ZjkExpertPaper> zjkExpertPapers = zjkExpertPaperService.selectListByProductIds(productReviewId);
        zjkProductVo.setZjkExpertPaperList(zjkExpertPapers);

        List<ZjkExpertPatent> zjkExpertPatents = zjkExpertPatentService.selectListByProductIds(productReviewId);
        zjkProductVo.setZjkExpertPatentsList(zjkExpertPatents);
        return zjkProductVo;
    }

    @Override
    public boolean productReviewUpdate(ZjkProductBo bo) {
        Long productReviewId = bo.getProductReviewId();
        if (productReviewId == null) {
            throw new ServiceException("id不能为空");
        }
        ZjkProductReviewsnVo zjkProductReviewsnVo = zjkProductReviewsnMapper.selectVoById(productReviewId);
        if (zjkProductReviewsnVo == null) {
            throw new ServiceException("无效id");
        }
        String reviewSn = zjkProductReviewsnVo.getReviewSn();
        zjkExpertPaperService.deleteByProductId(productReviewId);
        zjkExpertPatentService.deleteByProductId(productReviewId);

        List<ZjkExpertPaper> zjkExpertPaperList = bo.getZjkExpertPaperList();
        if (CollectionUtil.isNotEmpty(zjkExpertPaperList)) {
            for (ZjkExpertPaper zjkExpertPaper : zjkExpertPaperList) {
                zjkExpertPaper.setProductId(productReviewId);
                zjkExpertPaper.setReviewSn(reviewSn);
            }
        }
        List<ZjkExpertPatent> zjkExpertPatentsList = bo.getZjkExpertPatentsList();
        if (CollectionUtil.isNotEmpty(zjkExpertPatentsList)) {
            for (ZjkExpertPatent zjkExpertPatent : zjkExpertPatentsList) {
                zjkExpertPatent.setProductId(productReviewId);
                zjkExpertPatent.setReviewSn(reviewSn);
            }
        }
        zjkExpertPaperService.saveBatch(zjkExpertPaperList);
        zjkExpertPatentService.saveBatch(zjkExpertPatentsList);
        return true;
    }

    @Override
    public ProjectSummaryStatistics projectSummaryStatistics() {
        return baseMapper.projectSummaryStatistics();
    }

    @Override
    public Set<ProductPanoramaDeptVo> productPanoramaDept() {
        return baseMapper.productPanoramaDept();
    }

    @Override
    public Boolean approval(ZjkProductBo bo) {
        baseMapper.updateProductByApproval( bo.getId(),bo.getApprovalStatus(),bo.getApprovalReason());
        return true;
    }

    @Override
    public List<ProductCountReport> getProductTypeCountReport() {
        return baseMapper.getProductTypeCountReport();
    }

    @Override
    public List<ProjectSummaryStatisticsVo> getReviewStageSummary() {
        return baseMapper.getReviewStageSummary();
    }


}
