package com.ktg.iscs.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktg.common.core.redis.RedisCache;
import com.ktg.common.core.text.Convert;
import com.ktg.common.utils.DateUtils;
import com.ktg.iscs.domain.*;
import com.ktg.iscs.domain.dto.hardwareApi.UpdateSwitchStatusDTO;
import com.ktg.iscs.domain.dto.point.PagePointDTO;
import com.ktg.iscs.domain.vo.points.PointDetailVO;
import com.ktg.iscs.domain.vo.points.PointPageVO;
import com.ktg.iscs.mapper.IsIsolationPointMapper;
import com.ktg.iscs.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

import static com.ktg.common.constant.Constants.SYS_ATTR;

/**
 * 隔离点Service业务层处理
 *
 * @author cgj
 * @date 2024-10-18
 */
@Service
public class IsIsolationPointServiceImpl extends ServiceImpl<IsIsolationPointMapper, IsIsolationPoint> implements IIsIsolationPointService
{
    @Autowired
    private IsIsolationPointMapper isIsolationPointMapper;
    @Autowired
    private IIsSopPointsService iIsSopPointsService;
    @Autowired
    private IIsLotoStationService iIsLotoStationService;
    @Autowired
    private IIsLotoSwitchMapService isLotoSwitchMapService;
    @Autowired
    private IIsMapPointService iIsMapPointService;
    @Autowired
    private IIsMotorService isMotorService;
    @Autowired
    private RedisCache redisCache;

    /**
     * 查询隔离点
     *
     * @param pointId 隔离点主键
     * @return 隔离点
     */
    @Override
    public PointDetailVO selectIsIsolationPointByPointId(Long pointId)
    {
        return isIsolationPointMapper.selectIsIsolationPointByPointId(pointId);
    }

    /**
     * 查询隔离点列表
     *
     * @param isIsolationPoint 隔离点
     * @return 隔离点
     */
    @Override
    public List<IsIsolationPoint> selectIsIsolationPointList(IsIsolationPoint isIsolationPoint)
    {
        return isIsolationPointMapper.selectIsIsolationPointList(isIsolationPoint);
    }

    /**
     * 新增隔离点
     *
     * @param isIsolationPoint 隔离点
     * @return 结果
     */
    @Transactional
    @Override
    public int insertIsIsolationPoint(IsIsolationPoint isIsolationPoint)
    {
        // 断言校验
        Assert.isTrue(StringUtils.isNotBlank(isIsolationPoint.getPointName()), "隔离点名称不可为空!");
        Assert.isTrue(StringUtils.isNotBlank(isIsolationPoint.getPointCode()), "隔离点编号名称不可为空!");
        List<IsIsolationPoint> list = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getPointName, isIsolationPoint.getPointName()));
        Assert.isTrue(list.isEmpty(), "该隔离点名称已被使用!");
        List<IsIsolationPoint> list2 = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getRfidId, isIsolationPoint.getRfidId()));
        Assert.isTrue(list2.isEmpty(), "该NFC已被使用!");
        List<IsIsolationPoint> list3 = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getPointCode, isIsolationPoint.getPointCode()));
        Assert.isTrue(list3.isEmpty(), "该编号已被使用!");
        List<IsIsolationPoint> list4 = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getLotoId, isIsolationPoint.getLotoId())
                .eq(IsIsolationPoint::getPointSerialNumber, isIsolationPoint.getPointSerialNumber()));
        Assert.isTrue(list4.isEmpty(), "该序列号已被使用!");
        int i = isIsolationPointMapper.insertIsIsolationPoint(isIsolationPoint);
        // 如果绑定的loto站已经绑定了mapId,则需要往is_map_point插入数据
        if (isIsolationPoint.getLotoId() != null) {
            IsLotoStation lotoStation = iIsLotoStationService.getById(isIsolationPoint.getLotoId());
            if (lotoStation.getMapId() != null) {
                IsMapPoint point = new IsMapPoint();
                point.setMapId(lotoStation.getMapId());
                point.setMapType("2");
                point.setEntityId(isIsolationPoint.getPointId());
                iIsMapPointService.save(point);
            }
        }
        // 如果绑定的lotoSwitchMap站已经绑定了mapId,则需要往is_map_point插入数据
        if (isIsolationPoint.getSwitchMapId() != null) {
            IsLotoSwitchMap lotoSwitchMap = isLotoSwitchMapService.getById(isIsolationPoint.getSwitchMapId());
            if (lotoSwitchMap.getMapId() != null) {
                IsMapPoint point = new IsMapPoint();
                point.setMapId(lotoSwitchMap.getMapId());
                point.setMapType("3");
                point.setEntityId(isIsolationPoint.getPointId());
                iIsMapPointService.save(point);
            }
        }
        return i;
    }

    /**
     * 修改隔离点
     *
     * @param isIsolationPoint 隔离点
     * @return 结果
     */
    @Override
    public int updateIsIsolationPoint(IsIsolationPoint isIsolationPoint)
    {
        // 断言校验
        Assert.notNull(isIsolationPoint.getPointId(), "隔离点ID不可为空!");
        Assert.isTrue(StringUtils.isNotBlank(isIsolationPoint.getPointName()), "隔离点名称不可为空!");
        // Assert.isTrue(StringUtils.isNotBlank(isIsolationPoint.getPointCode()), "隔离点编号名称不可为空!");
        // Assert.notNull(isIsolationPoint.getWorkareaId(), "所属区域不可为空!");
        List<IsIsolationPoint> list = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getPointName, isIsolationPoint.getPointName())
                .ne(IsIsolationPoint::getPointId, isIsolationPoint.getPointId()));
        Assert.isTrue(list.isEmpty(), "该隔离点名称已被使用!");
        List<IsIsolationPoint> list2 = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getRfidId, isIsolationPoint.getRfidId())
                .ne(IsIsolationPoint::getPointId, isIsolationPoint.getPointId()));
        Assert.isTrue(list2.isEmpty(), "该NFC已被使用!");
        List<IsIsolationPoint> list3 = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getPointCode, isIsolationPoint.getPointCode())
                .ne(IsIsolationPoint::getPointId, isIsolationPoint.getPointId()));
        Assert.isTrue(list3.isEmpty(), "该编号已被使用!");
        List<IsIsolationPoint> list4 = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(IsIsolationPoint::getPointSerialNumber, isIsolationPoint.getPointSerialNumber())
                .eq(IsIsolationPoint::getLotoId, isIsolationPoint.getLotoId())
                .ne(IsIsolationPoint::getPointId, isIsolationPoint.getPointId()));
        Assert.isTrue(list4.isEmpty(), "该序列号已被使用!");
        isIsolationPoint.setUpdateTime(DateUtils.getNowDate());
        return isIsolationPointMapper.updateIsIsolationPoint(isIsolationPoint);
    }

    /**
     * 批量删除隔离点
     *
     * @param pointIds 需要删除的隔离点主键
     * @return 结果
     */
    @Override
    public int deleteIsIsolationPointByPointIds(String pointIds)
    {
        Assert.notBlank(pointIds, "请选择需要删除的数据!");
        Long[] longIds = Convert.toLongArray(pointIds);
        // 查询有没有sop使用改隔离点，有的话不允许删除
        checkPointUsed(longIds);
        return isIsolationPointMapper.deleteIsIsolationPointByPointIds(longIds);
    }

    private void checkPointUsed(Long[] longIds) {
        List<IsSopPoints> sopPoints = iIsSopPointsService.list(Wrappers.<IsSopPoints>lambdaQuery()
                .in(IsSopPoints::getPointId, longIds));
        if (!sopPoints.isEmpty()) {
            List<Long> usedPointIds = sopPoints.stream().map(IsSopPoints::getPointId).collect(Collectors.toList());
            List<IsIsolationPoint> isIsolationPoints = listByIds(usedPointIds);
            List<String> usedPointNames = isIsolationPoints.stream().map(IsIsolationPoint::getPointName).collect(Collectors.toList());
            Assert.isTrue(false, usedPointNames + "点位正在被sop使用，无法删除！");
        }
        // 检查电柜有没有配置该隔离点，如果还在配置中，需要先从电柜解除绑定
        for (Long longId : longIds) {
            /*String usePoint = '"' + "pointId" + '"' + ": " + '"' + longId + '"' + ",";
            List<IsLotoStation> list = iIsLotoStationService.list(Wrappers.<IsLotoStation>lambdaQuery()
                    .like(IsLotoStation::getMap, usePoint));
            if (!list.isEmpty()) {
                IsIsolationPoint isolationPoint = getById(longId);
                Assert.isTrue(false, isolationPoint.getPointName() + "正在被" + list.get(0).getLotoName() + "锁定站使用，请先从锁定站解除绑定！");
            }*/
            // 清理is_map_point
            iIsMapPointService.remove(Wrappers.<IsMapPoint>lambdaQuery()
                    .and(item -> item.eq(IsMapPoint::getMapType, "2")
                            .or().eq(IsMapPoint::getMapType, "3"))
                    .eq(IsMapPoint::getEntityId, longId));
            // 先查询隔离点关联的电机数据，在删除
            List<IsMotor> list = isMotorService.list(Wrappers.<IsMotor>lambdaQuery()
                    .eq(IsMotor::getPointId, longId));
            if (!list.isEmpty()) {
                iIsMapPointService.remove(Wrappers.<IsMapPoint>lambdaQuery()
                        .eq(IsMapPoint::getMapType, "4")
                        .in(IsMapPoint::getEntityId, list.stream().map(IsMotor::getMotorId).collect(Collectors.toList())));
            }
        }

    }

    /**
     * 删除隔离点信息
     *
     * @param pointId 隔离点主键
     * @return 结果
     */
    @Override
    public int deleteIsIsolationPointByPointId(Long pointId)
    {
        return isIsolationPointMapper.deleteIsIsolationPointByPointId(pointId);
    }

    @Override
    public List<PointDetailVO> getPointDetailList(List<Long> pointIds) {
        Assert.isTrue(!pointIds.isEmpty(), "查询隔离点信息出错！");
        List<PointDetailVO> isIsolationPoints = isIsolationPointMapper.getPointDetailList(pointIds);
        return isIsolationPoints;
    }

    @Override
    public Page<PointPageVO> getIsIsolationPointPage(Page<IsIsolationPoint> page, PagePointDTO dto) {
        Page<PointPageVO> isIsolationPointPage = isIsolationPointMapper.getIsIsolationPointPage(page, dto);
        List<UpdateSwitchStatusDTO> switchStatusList = redisCache.getCacheList(SYS_ATTR + "sys.points.switch.records");
        if (!switchStatusList.isEmpty() && !isIsolationPointPage.getRecords().isEmpty()) {
            for (PointPageVO pointPageVO : isIsolationPointPage.getRecords()) {
                for (UpdateSwitchStatusDTO updateSwitchStatusDTO : switchStatusList) {
                    if (StringUtils.isNotBlank(pointPageVO.getPointSerialNumber())
                            && StringUtils.isNotBlank(updateSwitchStatusDTO.getPointSerialNumber())
                            && pointPageVO.getPointSerialNumber().equals(updateSwitchStatusDTO.getPointSerialNumber())) {
                        pointPageVO.setSwitchStatus(updateSwitchStatusDTO.getSwitchStatus());
                        pointPageVO.setSwitchLastUpdateTime(updateSwitchStatusDTO.getSwitchLastUpdateTime());
                    }
                }
            }
        }
        return isIsolationPointPage;
    }

    @Override
    public List<IsIsolationPoint> getIsIsolationPointList(Long workshopId, Long workareaId) {
        /*List<IsIsolationPoint> result = list(Wrappers.<IsIsolationPoint>lambdaQuery()
                .eq(workshopId != null, IsIsolationPoint::getWorkshopId, workshopId)
                .eq(workshopId != null, IsIsolationPoint::getWorkareaId, workareaId)
                .orderByDesc(IsIsolationPoint::getPointId));*/
        return isIsolationPointMapper.getIsIsolationPointList(workshopId, workareaId);
    }

    @Override
    public IsIsolationPoint getOneByNfc(String nfc) {
        return isIsolationPointMapper.getOneByNfc(nfc);
    }
}
