package com.cf.imes.module.system.service.lable;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.enums.DeletedCodeEnum;
import com.cf.imes.framework.common.enums.UserSettingTypeEnum;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.label.vo.LabelPageReqVO;
import com.cf.imes.module.system.controller.admin.label.vo.LabelRespVO;
import com.cf.imes.module.system.controller.admin.label.vo.LabelSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.labeltemplate.LabelTemplateDO;
import com.cf.imes.module.system.dal.dataobject.lable.LabelDO;
import com.cf.imes.module.system.dal.dataobject.machine.MachineDO;
import com.cf.imes.module.system.dal.dataobject.setting.PackageConfigDO;
import com.cf.imes.module.system.dal.mysql.label.LabelMapper;
import com.cf.imes.module.system.dal.mysql.labeltemplate.LabelTemplateMapper;
import com.cf.imes.module.system.dal.mysql.machine.MachineMapper;
import com.cf.imes.module.system.dal.mysql.setting.PackageConfigMapper;
import com.cf.imes.module.system.enums.label.LabelTemplateType;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

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

import static com.cf.imes.framework.common.util.json.JsonUtils.parseTree;
import static com.cf.imes.framework.common.util.json.JsonUtils.unzipString;
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;

/**
 * 标签模板 Service 实现类
 *
 * @author 晨丰科技
 */
@Service
@Validated
@Slf4j
public class LabelServiceImpl implements LabelService {

    @Resource
    private LabelMapper labelMapper;

    @Resource
    private LabelTemplateMapper labelTemplateMapper;

    @Resource
    private MachineMapper machineMapper;

    @Resource
    private PackageConfigMapper packageConfigMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createLabel(LabelSaveReqVO createReqVO) {
        // 插入
        LabelDO label = BeanUtils.toBean(createReqVO, LabelDO.class);
        label.setTemplate(JsonUtils.zipString(label.getTemplate()));
        labelMapper.insert(label);
        // 返回
        return label.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLabel(LabelSaveReqVO updateReqVO) {

        // 校验存在
        LabelDO labelDO = validateLabelExists(updateReqVO.getId());
        // 更新
        LabelDO updateObj = BeanUtils.toBean(updateReqVO, LabelDO.class);
        if(!updateReqVO.getTemplate().isEmpty()){
            updateObj.setTemplate(JsonUtils.zipString(updateObj.getTemplate()));
        }
        updateObj.setOrganId(labelDO.getOrganId());

        labelMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteLabel(Long id) {
        // 校验存在
        LabelDO labelDO = validateLabelExists(id);

        List<MachineDO> machineDOS = machineMapper.selectList(new LambdaQueryWrapperX<MachineDO>()
                        .select(MachineDO::getId)
                        .eq(MachineDO::getLabelId, id)
        );
        if(CollUtil.isNotEmpty(machineDOS)) {
            throw new ServiceException(MACHINE_USE_LABEL);
        }

        List<Long> labelId = new ArrayList<>();

        Long organId = labelDO.getOrganId();
        List<PackageConfigDO> packageConfigDOS = packageConfigMapper.selectSettingList(UserSettingTypeEnum.PACKAGED.getType(),organId);

        if(CollUtil.isNotEmpty(packageConfigDOS)) {
            packageConfigDOS.forEach(f -> {

                JsonNode packConfig = parseTree(unzipString(f.getSetting()));

                labelId.add(packConfig.get("partLabelId") == null ? null : packConfig.get("partLabelId").asLong());
                labelId.add(packConfig.get("orderLabelId") == null ? null : packConfig.get("orderLabelId").asLong());
                labelId.add(packConfig.get("plateLabelId") == null ? null : packConfig.get("plateLabelId").asLong());

            });

            if (CollUtil.isNotEmpty(labelId) && labelId.contains(id)) {
                throw new ServiceException(LABEL_IS_USE_ERROR);
            }
        }

        // 删除标签
        labelMapper.deleteById(id);

    }

    private LabelDO validateLabelExists(Long id) {
        LabelDO labelDO = labelMapper.selectById(id);
        if (labelDO == null) {
            throw new ServiceException(LABEL_NOT_EXISTS);
        }
        return labelDO;
    }

    @Override
    public LabelRespVO getLabel(Long id) {

        LabelDO labelDO = validateLabelExists(id);

        labelDO.setTemplate(unzipString(labelDO.getTemplate()));
        LabelRespVO LabelRespVO = BeanUtils.toBean(labelDO, LabelRespVO.class);
        return LabelRespVO;
    }

    @Override
    public PageResult<LabelDO> getLabelPage(LabelPageReqVO pageReqVO) {

        PageResult<LabelDO> labelDOPageResult = labelMapper.selectPage(pageReqVO);

        labelDOPageResult.setList(labelDOPageResult.getList().stream().map(m -> m.setTemplate(unzipString(m.getTemplate()))).toList());

        return labelDOPageResult;
    }



    @Override
    public Map<String, List<LabelRespVO>> getGroupList(Long organId) {
        List<LabelDO> LabelDOS = labelMapper.selectList(new LambdaQueryWrapperX<LabelDO>()
                                .eqIfPresent(LabelDO::getOrganId, organId)
                )
                .stream().map(m -> m.setTemplate(unzipString(m.getTemplate()))).toList();
        List<LabelRespVO> LabelRespVOS = BeanUtils.toBean(LabelDOS, LabelRespVO.class);
        return LabelRespVOS.stream().collect(Collectors.groupingBy(LabelRespVO::getType));
    }

    @Override
    public List<LabelDO> list(String type) {

        return labelMapper.selectList(new LambdaQueryWrapperX<LabelDO>()
                        .eqIfPresent(LabelDO::getType, type)
                        .eq(LabelDO::getOrganId,getUserOrganId()))
                .stream().map( m -> m.setTemplate(unzipString(m.getTemplate()))).toList();
    }

    @Override
    public void copyInitalLabel(Long organId) {
        List<LabelDO> addList = new ArrayList<>();

        LabelTemplateType[] values = LabelTemplateType.values();
        for (LabelTemplateType value : values) {
            String labelType = value.getType();

            // 获取标签类型的默认模板
            LabelTemplateDO labelTemplateDO = labelTemplateMapper.selectOne(new LambdaQueryWrapperX<LabelTemplateDO>()
                    .eq(LabelTemplateDO::getType, labelType)
                    .eq(LabelTemplateDO::getIsDefault, Boolean.TRUE)
                    .eq(LabelTemplateDO::getDeleted, DeletedCodeEnum.NOT_DELETED.getStatus())
                    .last("limit 1")
            );

            // 复制标签内容a
            if (ObjectUtil.isNotNull(labelTemplateDO)) {
                LabelDO labelDO = LabelDO.builder()
                        .type(labelType)
                        .name(labelTemplateDO.getName())
                        .remark(labelTemplateDO.getRemark())
                        .width(labelTemplateDO.getWidth())
                        .height(labelTemplateDO.getHeight())
                        .template(labelTemplateDO.getTemplate())
                        .build();
                labelDO.setOrganId(organId);
                addList.add(labelDO);
            }
        }

        labelMapper.insertBatch(addList);
    }
}