package cn.iocoder.yudao.module.system.service.positionmap;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.mqtt.api.path.dto.PositionAllChangePointBindingDTO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.PositionChangePointBindingDTO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionChangePointBindingPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionChangePointBindingSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionChangePointBindingDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO;
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionChangePointBindingMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import static cn.hutool.core.collection.CollUtil.isNotEmpty;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;

/**
 * 区域变更点绑定 Service 实现类
 *
 * @author 陈宾顺
 */
@Service
@Validated
public class PositionChangePointBindingServiceImpl extends ServiceImpl<PositionChangePointBindingMapper, PositionChangePointBindingDO> implements PositionChangePointBindingService {

    @Resource
    private PositionChangePointBindingMapper positionChangePointBindingMapper;

    @Resource
    private PositionMapItemService positionMapItemService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createPositionChangePointBinding(PositionChangePointBindingSaveReqVO createReqVO) {
        // 插入
        PositionChangePointBindingDO positionChangePointBinding = BeanUtils.toBean(createReqVO, PositionChangePointBindingDO.class);
        positionChangePointBindingMapper.insert(positionChangePointBinding);

        PositionMapItemDO startPositionMapItem = positionMapItemService.getPositionMapItem(createReqVO.getStartingPointId());
        PositionMapItemDO endPositionMapItem = positionMapItemService.getPositionMapItem(createReqVO.getEndPointId());
        if (startPositionMapItem.getPositionMapId().equals(endPositionMapItem.getPositionMapId())) {
            throw exception(POSITION_CHANGE_POINT_SAME_MAP);
        }

        PositionChangePointBindingDO startPosition = positionChangePointBindingMapper.selectOne(new LambdaQueryWrapperX<PositionChangePointBindingDO>()
                .eq(PositionChangePointBindingDO::getStartingPointId, createReqVO.getStartingPointId()).last("limit 1"));
        if (ObjectUtil.isNotEmpty(startPosition)) {
            throw exception(POSITION_CHANGE_POINT_ALREADY_BINDING);
        }

        PositionChangePointBindingDO endPosition = positionChangePointBindingMapper.selectOne(new LambdaQueryWrapperX<PositionChangePointBindingDO>()
                .eq(PositionChangePointBindingDO::getStartingPointId, createReqVO.getEndPointId()).last("limit 1"));
        if (ObjectUtil.isNotEmpty(endPosition)) {
            throw exception(POSITION_CHANGE_POINT_ALREADY_BINDING);
        }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePositionChangePointBinding(PositionChangePointBindingSaveReqVO updateReqVO) {
        // 校验存在
        validatePositionChangePointBindingExists(updateReqVO.getId());
        // 更新
        PositionChangePointBindingDO updateObj = BeanUtils.toBean(updateReqVO, PositionChangePointBindingDO.class);
        positionChangePointBindingMapper.updateById(updateObj);
    }

    @Override
    public void deletePositionChangePointBinding(Long id) {
        // 校验存在
        validatePositionChangePointBindingExists(id);
        // 删除
        positionChangePointBindingMapper.deleteById(id);
    }

    private void validatePositionChangePointBindingExists(Long id) {
        if (positionChangePointBindingMapper.selectById(id) == null) {
            throw exception(POSITION_CHANGE_POINT_BINDING_NOT_EXISTS);
        }
    }

    @Override
    public PositionChangePointBindingDTO getPositionChangePointBinding(Long mapItemId) {
        PositionChangePointBindingDTO positionChangePointBinding = new PositionChangePointBindingDTO();
        PositionChangePointBindingDO position = positionChangePointBindingMapper.selectOne(new LambdaQueryWrapperX<PositionChangePointBindingDO>()
                .eq(PositionChangePointBindingDO::getStartingPointId, mapItemId).last("limit 1"));
        if (ObjectUtil.isNotEmpty(position)) {
            positionChangePointBinding.setId(position.getId());
            positionChangePointBinding.setSortNum(position.getEndPointSortNum());
            positionChangePointBinding.setPointId(position.getEndPointId());
            return positionChangePointBinding;
        }

        PositionChangePointBindingDO startPosition = positionChangePointBindingMapper.selectOne(new LambdaQueryWrapperX<PositionChangePointBindingDO>()
                .eq(PositionChangePointBindingDO::getEndPointId, mapItemId).last("limit 1"));
        if (ObjectUtil.isNotEmpty(startPosition)) {
            positionChangePointBinding.setId(startPosition.getId());
            positionChangePointBinding.setSortNum(startPosition.getStartingPointSortNum());
            positionChangePointBinding.setPointId(startPosition.getStartingPointId());
        }

        return positionChangePointBinding;
    }

    @Override
    public PageResult<PositionChangePointBindingDO> getPositionChangePointBindingPage(PositionChangePointBindingPageReqVO pageReqVO) {
        return positionChangePointBindingMapper.selectPage(pageReqVO);
    }

    @Override
    public List<PositionAllChangePointBindingDTO> getAllPositionChangePointBinding() {
        return positionChangePointBindingMapper.getAllPositionChangePointBinding();
    }

    @Override
    public List<PositionChangePointBindingDO> getPositionChangePointBindingByMapId(Long positionMapId) {
        return  positionChangePointBindingMapper.selectList(new LambdaQueryWrapperX<PositionChangePointBindingDO>()
                .eq(PositionChangePointBindingDO::getPositionMapId, positionMapId));
    }

    @Override
    public void batchEditOrDel(List<List<PositionChangePointBindingDO>> list) {
        //批量添加、修改、删除
        //批量添加、修改、删除
        if (isNotEmpty(list.get(0))) {
            positionChangePointBindingMapper.insertBatch(list.get(0));
        }
        if (isNotEmpty(list.get(1))) {
            positionChangePointBindingMapper.updateBatch(list.get(1));
        }
        if (isNotEmpty(list.get(2))) {
            positionChangePointBindingMapper.deleteByIds(convertList(list.get(2), PositionChangePointBindingDO::getId));
        }
    }

    @Override
    public List<PositionChangePointBindingDO> getByMapIdAndEndPointIds(Long positionMapId, List<Long> endPointIds) {
        return positionChangePointBindingMapper.selectList(new LambdaQueryWrapperX<PositionChangePointBindingDO>()
                .ne(PositionChangePointBindingDO::getPositionMapId, positionMapId)
                .in(PositionChangePointBindingDO::getEndPointId,endPointIds));
    }

    @Override
    public List<PositionChangePointBindingDO> getByMapIdAndStartPointIds(Long positionMapId, List<Long> endPointIds, List<Long> startPointIds) {
        return positionChangePointBindingMapper.selectList(new LambdaQueryWrapperX<PositionChangePointBindingDO>()
                .ne(PositionChangePointBindingDO::getPositionMapId, positionMapId)
                .in(PositionChangePointBindingDO::getStartingPointId,endPointIds)
                .notIn(PositionChangePointBindingDO::getEndPointId,startPointIds));
    }

    @Override
    public void deleteBindingByMapId(Long mapId) {
        positionChangePointBindingMapper.deleteBindIngByMapId(mapId);
    }


}
