package com.yuchen.saas.park.service.service.pldoor.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuchen.saas.park.api.dto.pldoor.PlDoorPointGroupDTO;
import com.yuchen.saas.park.api.entity.pldoor.PlDoorPoint;
import com.yuchen.saas.park.api.entity.pldoor.PlDoorPointGroup;
import com.yuchen.saas.park.api.entity.pldoor.PlDoorPointGroupItem;
import com.yuchen.saas.park.api.vo.pldoor.PlDoorPointGroupLtVO;
import com.yuchen.saas.park.api.vo.pldoor.PlDoorPointGroupVO;
import com.yuchen.saas.park.api.vo.request.PlDoorPointGroupListReq;
import com.yuchen.saas.park.api.vo.request.PlDoorPointGroupReq;
import com.yuchen.saas.park.service.mapper.pldoor.PlDoorPointGroupMapper;
import com.yuchen.saas.park.service.service.pldoor.PlDoorPointGroupItemService;
import com.yuchen.saas.park.service.service.pldoor.PlDoorPointGroupService;
import com.yuchen.saas.park.service.service.pldoor.PlDoorPointService;
import org.apache.ibatis.annotations.Param;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.tool.utils.BeanUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 门禁组 服务实现类
 * </p>
 *
 * @author miaoqs
 * @since 2024-04-03
 */
@Service
public class PlDoorPointGroupServiceImpl extends BaseServiceImpl<PlDoorPointGroupMapper, PlDoorPointGroup> implements PlDoorPointGroupService {

    @Resource
    private PlDoorPointService plDoorPointService;
    @Resource
    private PlDoorPointGroupItemService plDoorPointGroupItemService;
    @Resource
    private PlDoorPointGroupMapper plDoorPointGroupMapper;

    @Override
    public boolean saveOrUpdateByParam(PlDoorPointGroupDTO plDoorPointGroupDTO) {

        PlDoorPointGroup pointGroup = new PlDoorPointGroup();
        BeanUtil.copyProperties(plDoorPointGroupDTO,pointGroup);
        Long id = pointGroup.getId();

        if(Func.isNotEmpty(plDoorPointGroupDTO.getPlDoorPointGroupItemList())){
            List<PlDoorPointGroupItem> plDoorPointGroupItemList = plDoorPointGroupDTO.getPlDoorPointGroupItemList();
            List<Long> pointList = plDoorPointGroupItemList.stream().map(PlDoorPointGroupItem::getPlDoorPointId).collect(Collectors.toList());
            Set<Long> pontSet = new HashSet<>(pointList);
            if(pontSet.size() != pointList.size()){
                throw new RuntimeException("所选门禁点重复");
            }
        }

        saveOrUpdate(pointGroup);
        //移除原有门禁点
        if(Func.isNotEmpty(id)){
            plDoorPointGroupItemService.remove(new LambdaQueryWrapper<PlDoorPointGroupItem>()
                    .eq(PlDoorPointGroupItem::getPlDoorPointGroupId, id));
        }
        //新增门禁点
        if(Func.isNotEmpty(plDoorPointGroupDTO.getPlDoorPointGroupItemList())){
            List<PlDoorPointGroupItem> plDoorPointGroupItemList = plDoorPointGroupDTO.getPlDoorPointGroupItemList();
            for (PlDoorPointGroupItem item : plDoorPointGroupItemList) {
                item.setId(null);
                item.setPlDoorPointGroupId(pointGroup.getId());
            }
            plDoorPointGroupItemService.saveBatch(plDoorPointGroupItemList);
        }
        return true;
    }

    @Override
    public PlDoorPointGroupVO detailById(Long id) {
        PlDoorPointGroupVO plDoorPointGroupVO = new PlDoorPointGroupVO();
        PlDoorPointGroup plDoorPointGroup = getById(id);
        BeanUtil.copyProperties(plDoorPointGroup,plDoorPointGroupVO);
        //门禁点列表
        List<PlDoorPointGroupItem> itemList = plDoorPointGroupItemService.list(new LambdaQueryWrapper<PlDoorPointGroupItem>()
                .eq(PlDoorPointGroupItem::getPlDoorPointGroupId, id));
        if(Func.isNotEmpty(itemList)){
            for (PlDoorPointGroupItem item : itemList) {
                PlDoorPoint point = plDoorPointService.getById(item.getPlDoorPointId());
                if(Func.isNotEmpty(point)) {
                    item.setDoorId(point.getDoorId());
                    item.setPlDoorPointNameStr(point.getDoorName());
                }
            }
            plDoorPointGroupVO.setPlDoorPointGroupItemList(itemList);
        }
        return plDoorPointGroupVO;
    }

    @Override
    public boolean deleteById(Long id) {
        removeById(id);
        plDoorPointGroupItemService.remove(new LambdaQueryWrapper<PlDoorPointGroupItem>()
                .eq(PlDoorPointGroupItem::getPlDoorPointGroupId, id));
        return true;
    }

    @Override
    public IPage<PlDoorPointGroupVO> pageByParam(Page<PlDoorPointGroupReq> page, @Param("req") PlDoorPointGroupReq req) {
        Page<PlDoorPointGroupVO> pointGroupVOPage = plDoorPointGroupMapper.listByParam(page, req);
        if(Func.isNotEmpty(pointGroupVOPage)){
            List<PlDoorPoint> pointList = plDoorPointService.list();
            Map<Long, String> pointMap = pointList.stream().collect(Collectors.toMap(PlDoorPoint::getId, PlDoorPoint::getDoorName));
            pointGroupVOPage.getRecords().forEach(groupItem -> {
                List<PlDoorPointGroupItem> itemList = plDoorPointGroupItemService.list(new LambdaQueryWrapper<PlDoorPointGroupItem>()
                        .eq(PlDoorPointGroupItem::getPlDoorPointGroupId, groupItem.getId()));
                if(Func.isNotEmpty(itemList)){
                    for (PlDoorPointGroupItem item : itemList) {
                        item.setPlDoorPointNameStr(pointMap.get(item.getPlDoorPointId()));
                    }
                    groupItem.setPlDoorPointGroupItemList(itemList);
                    String pointNames = itemList.stream().map(PlDoorPointGroupItem::getPlDoorPointId).map(pointMap::get).collect(Collectors.joining(","));
                    groupItem.setPlDoorPointNames(pointNames);
                }
            });
        }
        return pointGroupVOPage;
    }

    @Override
    public List<PlDoorPointGroupLtVO> listByParam(PlDoorPointGroupListReq req) {
        List<PlDoorPointGroupLtVO> groupLtVOList = new ArrayList<>();
        List<PlDoorPointGroup> groupList = list();
        if(Func.isNotEmpty(groupList)){
            for (PlDoorPointGroup group : groupList) {
                PlDoorPointGroupLtVO groupLtVO = new PlDoorPointGroupLtVO();
                BeanUtil.copyProperties(group,groupLtVO);
                groupLtVOList.add(groupLtVO);
            }
        }
        //获取门禁点
        List<PlDoorPoint> queryPointList = new ArrayList<>();
        if(Func.isNotEmpty(groupLtVOList)){
            if(Func.isEmpty(req.getBuildingId()) && Func.isEmpty(req.getElementId())){
                queryPointList = plDoorPointService.list();
            }else if(Func.isNotEmpty(req.getBuildingId()) && Func.isNotEmpty(req.getElementId())){
                queryPointList = plDoorPointService.list(new LambdaQueryWrapper<PlDoorPoint>()
                        .eq(PlDoorPoint::getBuildingId, req.getBuildingId())
                        .eq(PlDoorPoint::getElementId, req.getElementId()));
            }else if(Func.isNotEmpty(req.getBuildingId())){
                queryPointList = plDoorPointService.list(new LambdaQueryWrapper<PlDoorPoint>()
                        .eq(PlDoorPoint::getBuildingId, req.getBuildingId()));
            }else if(Func.isNotEmpty(req.getElementId())){
                queryPointList = plDoorPointService.list(new LambdaQueryWrapper<PlDoorPoint>()
                        .eq(PlDoorPoint::getElementId, req.getElementId()));
            }
            //获取门禁点名称和ids
            Map<Long, String> pointNameMap = new HashMap<>();
            List<Long> idList = new ArrayList<>();
            if(Func.isNotEmpty(queryPointList)){
                pointNameMap = queryPointList.stream().collect(Collectors.toMap(PlDoorPoint::getId, PlDoorPoint::getDoorName));
                idList = queryPointList.stream().map(PlDoorPoint::getId).collect(Collectors.toList());
            }
            //过滤掉不符合的门禁点
            for (PlDoorPointGroupLtVO pointGroupLtVO : groupLtVOList) {
                List<PlDoorPointGroupItem> itemList = plDoorPointGroupItemService.list(new LambdaQueryWrapper<PlDoorPointGroupItem>()
                        .eq(PlDoorPointGroupItem::getPlDoorPointGroupId, pointGroupLtVO.getId()));
                if(Func.isNotEmpty(itemList)){
                    List<PlDoorPointGroupItem> removeList = new ArrayList<>();
                    for (PlDoorPointGroupItem item : itemList) {
                        item.setPlDoorPointNameStr(pointNameMap.get(item.getPlDoorPointId()));
                        if(!idList.contains(item.getPlDoorPointId())){
                            removeList.add(item);
                        }
                    }
                    itemList.removeAll(removeList);
                }
                pointGroupLtVO.setPlDoorPointGroupItemList(itemList);
            }
        }
        return groupLtVOList;
    }

}
