package cn.iocoder.yudao.module.configure.service.inspectiontemplate;

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.enums.CodeEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.basic.api.businessinfo.BusinessInfoApi;
import cn.iocoder.yudao.module.basic.api.redis.dto.BusinessInfoDTO;
import cn.iocoder.yudao.module.configure.controller.admin.inspectiontemplate.vo.InspectionTemplateCreateReqVO;
import cn.iocoder.yudao.module.configure.controller.admin.inspectiontemplate.vo.InspectionTemplatePageReqVO;
import cn.iocoder.yudao.module.configure.controller.admin.inspectiontemplate.vo.InspectionTemplateRespVO;
import cn.iocoder.yudao.module.configure.controller.admin.inspectiontemplate.vo.InspectionTemplateUpdateReqVO;
import cn.iocoder.yudao.module.configure.convert.inspectionitem.InspectionItemConvert;
import cn.iocoder.yudao.module.configure.convert.inspectiontemplate.InspectionTemplateConvert;
import cn.iocoder.yudao.module.configure.dal.dataobject.inspectionitem.InspectionItemDO;
import cn.iocoder.yudao.module.configure.dal.dataobject.inspectiontemplate.InspectionTemplateDO;
import cn.iocoder.yudao.module.configure.dal.mysql.inspectionitem.InspectionItemMapper;
import cn.iocoder.yudao.module.configure.dal.mysql.inspectiontemplate.InspectionTemplateMapper;
import cn.iocoder.yudao.module.configure.enums.ErrorCodeConstants;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 检测报告模板 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class InspectionTemplateServiceImpl implements InspectionTemplateService {

    @Resource
    private InspectionTemplateMapper inspectionTemplateMapper;

    @Resource
    private InspectionItemMapper inspectionItemMapper;

    @Resource
    private BusinessInfoApi businessInfoApi;

    @Override
    @Transactional
    public Long createInspectionTemplate(InspectionTemplateCreateReqVO createReqVO) {
        // 校验商户是否存在
        BusinessInfoDTO businessInfo = businessInfoApi.getBusinessInfoById(createReqVO.getBelongBusinessId()).getData();
        if(businessInfo == null) {
            throw ServiceExceptionUtil.exception(cn.iocoder.yudao.module.basic.enums.ErrorCodeConstants.BUSINESS_INFO_NOT_EXISTS);
        }

        InspectionTemplateDO inspection = InspectionTemplateConvert.INSTANCE.convert(createReqVO);
        inspection.setBelongBusinessName(businessInfo.getBusinessName());
        inspection.setTemplateId(CodeEnum.INSPECTION_TEMPLATE_CODE.getCode());

        List<InspectionItemDO> inspectionItems = new ArrayList<>();
        createReqVO.getInspectionItems().forEach(item -> {
            InspectionItemDO inspectionItem = new InspectionItemDO();
            BeanUtil.copyProperties(item, inspectionItem);
            inspectionItem.setId(null);
            inspectionItem.setTemplateId(inspection.getTemplateId());
            inspectionItem.setTemplateName(inspection.getTemplateName());
            inspectionItem.setInspectionItemId(CodeEnum.INSPECTION_TEMPLATE_ITEM_CODE.getCode());
            inspectionItem.setBelongBusinessId(businessInfo.getId());
            inspectionItem.setBelongBusinessName(businessInfo.getBusinessName());

            inspectionItems.add(inspectionItem);
        });

        // 插入
        inspectionTemplateMapper.insert(inspection);

        inspectionItemMapper.insertBatch(inspectionItems, Integer.MAX_VALUE);

        // 返回
        return inspection.getId();
    }

    @Override
    @Transactional
    public void updateInspectionTemplate(InspectionTemplateUpdateReqVO updateReqVO) {
        // 校验存在
        InspectionTemplateDO inspectionTemplate = validateInspectionTemplateExists(updateReqVO.getId());
        // 主表不做更新， 只更新子表
        // 查询数据库里已有的item
        List<InspectionItemDO> inspectionItemsDB = inspectionItemMapper.selectList(new LambdaQueryWrapperX<InspectionItemDO>().eq(InspectionItemDO::getTemplateId, inspectionTemplate.getTemplateId()));
        List<Long> willUpdateItemIds = new ArrayList<>();
        List<Long> itemIdsDB = new ArrayList<>();
        Map<Long, InspectionItemDO> itemDBmAP = new HashMap<>();
        updateReqVO.getInspectionItems().forEach(item -> {
            if(item.getId() != null) {
                willUpdateItemIds.add(item.getId());
            }
        });
        inspectionItemsDB.forEach(item -> {
            itemIdsDB.add(item.getId());
            itemDBmAP.put(item.getId(), item);
        });

        // 需要删除的项目id集合
        List<Long> deleteItemIds = new ArrayList<>();
        if(willUpdateItemIds.isEmpty()) {
            deleteItemIds.addAll(itemIdsDB);
        } else {
            deleteItemIds.addAll(itemIdsDB.stream().filter(id -> !willUpdateItemIds.contains(id)).collect(Collectors.toList()));
        }

        List<InspectionItemDO> createInspectionItems = new ArrayList<>();
        List<InspectionItemDO> updateInspectionItems = new ArrayList<>();
        updateReqVO.getInspectionItems().forEach(item -> {
            InspectionItemDO inspectionItem = new InspectionItemDO();
            BeanUtil.copyProperties(item, inspectionItem);
            if(item.getId() != null) {
                if(itemDBmAP.get(item.getId()) == null) {
                    throw ServiceExceptionUtil.exception(ErrorCodeConstants.INSPECTION_ITEM_NOT_EXISTS);
                }

                updateInspectionItems.add(inspectionItem);
            } else {
                inspectionItem.setTemplateId(inspectionTemplate.getTemplateId());
                inspectionItem.setTemplateName(inspectionTemplate.getTemplateName());
                inspectionItem.setInspectionItemId(CodeEnum.INSPECTION_ITEM_CODE.getCode());
                inspectionItem.setBelongBusinessId(inspectionTemplate.getBelongBusinessId());
                inspectionItem.setBelongBusinessName(inspectionTemplate.getBelongBusinessName());
                createInspectionItems.add(inspectionItem);
            }
        });

        // 更新
        if(!createInspectionItems.isEmpty()) {
            inspectionItemMapper.insertBatch(createInspectionItems);
        }

        if(!updateInspectionItems.isEmpty()) {
            inspectionItemMapper.updateBatch(updateInspectionItems, Integer.MAX_VALUE);
        }

        if(!deleteItemIds.isEmpty()) {
            inspectionItemMapper.deleteBatchIds(deleteItemIds);
        }
    }

    @Override
    public void deleteInspectionTemplate(Long id) {
        // 校验存在
        validateInspectionTemplateExists(id);
        // 删除
        inspectionTemplateMapper.deleteById(id);
    }

    private InspectionTemplateDO validateInspectionTemplateExists(Long id) {
        InspectionTemplateDO inspectionTemplate = inspectionTemplateMapper.selectById(id);
        if (inspectionTemplate == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.INSPECTION_TEMPLATE_NOT_EXISTS);
        }
        return inspectionTemplate;
    }

    @Override
    public InspectionTemplateRespVO getInspectionTemplate(Long id) {
        InspectionTemplateRespVO inspectionTemplateResp = new InspectionTemplateRespVO();
        InspectionTemplateDO inspectionTemplate = inspectionTemplateMapper.selectById(id);
        BeanUtil.copyProperties(inspectionTemplate, inspectionTemplateResp);
        if(inspectionTemplate != null) {
            List<InspectionItemDO> inspectionItems = inspectionItemMapper.selectList(new LambdaQueryWrapperX<InspectionItemDO>()
                    .eq(InspectionItemDO::getTemplateId, inspectionTemplate.getTemplateId()));
            inspectionTemplateResp.setInspectionItems(InspectionItemConvert.INSTANCE.convertList(inspectionItems));
        }
        return inspectionTemplateResp;
    }

    @Override
    public PageResult<InspectionTemplateDO> getInspectionTemplatePage(InspectionTemplatePageReqVO pageReqVO) {
        return inspectionTemplateMapper.selectPage(pageReqVO);
    }

    @Override
    public List<InspectionTemplateRespVO> getInspectionTemplateByBusinessId(Long businessId) {
        return inspectionTemplateMapper.selectInspectionTemplates(businessId);
    }

}
