package cn.stylefeng.team.meta.modular.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.entity.BaseEntity;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.team.meta.modular.entity.BusinessDiagram;
import cn.stylefeng.team.meta.modular.enums.BusinessDiagramExceptionEnum;
import cn.stylefeng.team.meta.modular.mapper.BusinessDiagramMapper;
import cn.stylefeng.team.meta.modular.pojo.request.BusinessDiagramRequest;
import cn.stylefeng.team.meta.modular.service.BusinessDiagramService;
import cn.stylefeng.team.project.api.SystemCodeApi;
import cn.stylefeng.team.project.api.enums.SystemCodeTypeEnum;
import cn.stylefeng.team.project.api.pojo.SystemCodeInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class BusinessDiagramServiceImpl extends ServiceImpl<BusinessDiagramMapper, BusinessDiagram> implements BusinessDiagramService {

    @Resource
    private SystemCodeApi systemCodeApi;

    @Override
    public BusinessDiagram add(BusinessDiagramRequest businessDiagramRequest) {
        BusinessDiagram businessDiagram = new BusinessDiagram();
        BeanUtil.copyProperties(businessDiagramRequest, businessDiagram);

        SystemCodeInfo newSystemCode = systemCodeApi.createNewSystemCode(SystemCodeTypeEnum.BUSINESS_DIAGRAM);
        businessDiagram.setSystemCode(newSystemCode.getSystemCode());
        businessDiagram.setSystemCodeShow(newSystemCode.getSystemCodeShow());

        this.save(businessDiagram);

        return businessDiagram;
    }

    @Override
    public void del(BusinessDiagramRequest businessDiagramRequest) {
        BusinessDiagram businessDiagram = this.queryBusinessDiagram(businessDiagramRequest);
        this.removeById(businessDiagram.getDiagramId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(BusinessDiagramRequest businessDiagramRequest) {
        this.removeByIds(businessDiagramRequest.getBatchDeleteIdList());
    }

    @Override
    public void edit(BusinessDiagramRequest businessDiagramRequest) {
        BusinessDiagram businessDiagram = this.queryBusinessDiagram(businessDiagramRequest);
        BeanUtil.copyProperties(businessDiagramRequest, businessDiagram);
        this.updateById(businessDiagram);
    }

    @Override
    public BusinessDiagram detail(BusinessDiagramRequest businessDiagramRequest) {
        return this.queryBusinessDiagram(businessDiagramRequest);
    }

    @Override
    public PageResult<BusinessDiagram> findPage(BusinessDiagramRequest businessDiagramRequest) {
        LambdaQueryWrapper<BusinessDiagram> wrapper = createWrapper(businessDiagramRequest);

        wrapper.select(BusinessDiagram::getDiagramId, BusinessDiagram::getDiagramFileId, BusinessDiagram::getDiagramName, BaseEntity::getCreateTime);

        Page<BusinessDiagram> pageList = this.page(PageFactory.defaultPage(), wrapper);
        return PageResultFactory.createPageResult(pageList);
    }

    @Override
    public List<BusinessDiagram> findList(BusinessDiagramRequest businessDiagramRequest) {
        LambdaQueryWrapper<BusinessDiagram> wrapper = this.createWrapper(businessDiagramRequest);

        wrapper.select(BusinessDiagram::getDiagramId, BusinessDiagram::getDiagramFileId, BusinessDiagram::getDiagramName, BaseEntity::getCreateTime);

        return this.list(wrapper);
    }

    private BusinessDiagram queryBusinessDiagram(BusinessDiagramRequest businessDiagramRequest) {
        BusinessDiagram businessDiagram = this.getById(businessDiagramRequest.getDiagramId());
        if (ObjectUtil.isEmpty(businessDiagram)) {
            throw new ServiceException(BusinessDiagramExceptionEnum.BUSINESS_DIAGRAM_NOT_EXISTED);
        }
        return businessDiagram;
    }

    private LambdaQueryWrapper<BusinessDiagram> createWrapper(BusinessDiagramRequest businessDiagramRequest) {
        LambdaQueryWrapper<BusinessDiagram> queryWrapper = new LambdaQueryWrapper<>();

        String searchText = businessDiagramRequest.getSearchText();
        if (StrUtil.isNotBlank(searchText)) {
            queryWrapper.nested(i -> {
                i.like(BusinessDiagram::getDiagramName, searchText).or().like(BusinessDiagram::getSystemCodeShow, searchText);
            });
        }

        Long businessId = businessDiagramRequest.getBusinessId();
        if (ObjectUtil.isNotEmpty(businessId)) {
            queryWrapper.eq(BusinessDiagram::getBusinessId, businessId);
        }

        queryWrapper.orderByAsc(BusinessDiagram::getFldSort);
        queryWrapper.orderByDesc(BaseEntity::getCreateTime);

        return queryWrapper;
    }

    @Override
    public Map<Long, Integer> statBusinessDiagramNumber(Set<Long> businessIds) {
        HashMap<Long, Integer> resultMap = new HashMap<>();

        if (ObjectUtil.isEmpty(businessIds)) {
            return resultMap;
        }

        LambdaQueryWrapper<BusinessDiagram> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(BusinessDiagram::getBusinessId, businessIds);
        wrapper.select(BusinessDiagram::getBusinessId, BusinessDiagram::getDiagramId);
        List<BusinessDiagram> businessDiagrams = this.list(wrapper);
        if (ObjectUtil.isEmpty(businessDiagrams)) {
            return resultMap;
        }

        return businessDiagrams.stream().collect(Collectors.groupingBy(BusinessDiagram::getBusinessId, Collectors.summingInt(i -> 1)));
    }

}
