package com.ktg.iscs.service.impl;

import cn.hutool.core.convert.Convert;
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.utils.StringUtils;
import com.ktg.iscs.domain.IsIsolationPoint;
import com.ktg.iscs.domain.IsLotoStation;
import com.ktg.iscs.domain.IsMapPoint;
import com.ktg.iscs.domain.IsMotor;
import com.ktg.iscs.domain.dto.hardwareApi.UpdateSwitchStatusDTO;
import com.ktg.iscs.domain.dto.motor.MotorMoveDTO;
import com.ktg.iscs.domain.dto.motor.MotorMoveDetailDTO;
import com.ktg.iscs.mapper.IsMotorMapper;
import com.ktg.iscs.service.IIsIsolationPointService;
import com.ktg.iscs.service.IIsLotoStationService;
import com.ktg.iscs.service.IIsMapPointService;
import com.ktg.iscs.service.IIsMotorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

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

/**
 * 电机Service业务层处理
 *
 * @author cgj
 * @date 2025-09-04
 */
@Service
public class IsMotorServiceImpl extends ServiceImpl<IsMotorMapper, IsMotor> implements IIsMotorService {

    @Autowired
    private IsMotorMapper isMotorMapper;
    @Autowired
    private IIsLotoStationService isLotoStationService;
    @Autowired
    private IIsIsolationPointService iIsIsolationPointService;
    @Autowired
    private IIsMapPointService isMapPointService;
    @Autowired
    private RedisCache redisCache;

    @Override
    public Page<IsMotor> getIsMotorPage(Page<IsMotor> page, IsMotor isMotor) {
        Page<IsMotor> result = isMotorMapper.getIsMotorPage(page, isMotor);
        return result;
    }

    @Override
    public List<IsMotor> getIsMotorListByLotoId(Long lotoId) {
        Assert.notNull(lotoId, "锁控柜id不能为空！");
        IsLotoStation lotoStation = isLotoStationService.getById(lotoId);
        Assert.notNull(lotoStation, "物资柜存在！");
        List<IsMotor> motorList = null;
        if (lotoStation.getMotorMapId() != null) {
            List<IsIsolationPoint> points = iIsIsolationPointService.list(Wrappers.<IsIsolationPoint>lambdaQuery()
                    .eq(IsIsolationPoint::getLotoId, lotoId));
            if (!points.isEmpty()) {
                motorList = list(Wrappers.<IsMotor>lambdaQuery()
                        .in(IsMotor::getPointId, points.stream().map(IsIsolationPoint::getPointId).collect(Collectors.toList())));
                if (!motorList.isEmpty()) {
                    // 查询这些电机有没有坐标数据
                    List<IsMapPoint> mapPoints = isMapPointService.list(Wrappers.<IsMapPoint>lambdaQuery()
                            .eq(IsMapPoint::getMapType, "4")
                            .eq(IsMapPoint::getMapId, lotoStation.getMotorMapId())
                            .in(IsMapPoint::getEntityId, motorList.stream().map(IsMotor::getMotorId).collect(Collectors.toList())));
                    for (IsMotor isMotor : motorList) {
                        List<IsIsolationPoint> collect = points.stream().filter(o -> o.getPointId().equals(isMotor.getPointId())).collect(Collectors.toList());
                        for (IsMapPoint mapPoint : mapPoints) {
                            if (isMotor.getMotorId().equals(mapPoint.getEntityId())) {
                                isMotor.setX(mapPoint.getX());
                                isMotor.setY(mapPoint.getY());
                                isMotor.setMapPointId(mapPoint.getId());
                                isMotor.setPointName(collect.isEmpty() ? null : collect.get(0).getPointName());
                                isMotor.setPointSerialNumber(collect.isEmpty() ? null : collect.get(0).getPointSerialNumber());
                            }
                        }
                    }
                    // 通过柜子的序列号去找缓存信息，然后给点位控制的开关设置状态
                    if (StringUtils.isNotBlank(lotoStation.getLotoSerialNumber())) {
                        List<UpdateSwitchStatusDTO> pointList = redisCache.getCacheList(SYS_ATTR + lotoStation.getLotoSerialNumber() + ":sys.points.switch.records");
                        if (!pointList.isEmpty()) {
                            for (IsMotor isMotor : motorList) {
                                for (UpdateSwitchStatusDTO updateSwitchStatusDTO : pointList) {
                                    if (StringUtils.isNotBlank(isMotor.getPointSerialNumber()) && isMotor.getPointSerialNumber().equals(updateSwitchStatusDTO.getPointSerialNumber())) {
                                        isMotor.setStatus(updateSwitchStatusDTO.getSwitchStatus());
                                        isMotor.setSwitchLastUpdateTime(updateSwitchStatusDTO.getSwitchLastUpdateTime());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return motorList;
    }

    @Transactional
    @Override
    public Boolean updateIsMotorMove(MotorMoveDTO dto) {
        if (!dto.getMoveList().isEmpty()) {
            Date date = new Date();
            for (MotorMoveDetailDTO motorMoveDetailDTO : dto.getMoveList()) {
                Assert.notNull(motorMoveDetailDTO.getMapId(), "地图主键不能为空");
                if (motorMoveDetailDTO.getMapPointId() != null) {
                    isMapPointService.update(Wrappers.<IsMapPoint>lambdaUpdate()
                            .eq(IsMapPoint::getId, motorMoveDetailDTO.getMapPointId())
                            .set(IsMapPoint::getX, motorMoveDetailDTO.getX())
                            .set(IsMapPoint::getY, motorMoveDetailDTO.getY())
                            .set(IsMapPoint::getUpdateTime, date));
                } else {
                    IsMapPoint isMapPoint = new IsMapPoint();
                    isMapPoint.setMapId(motorMoveDetailDTO.getMapId());
                    isMapPoint.setMapType("4");
                    isMapPoint.setEntityId(motorMoveDetailDTO.getEntityId());
                    isMapPoint.setX(motorMoveDetailDTO.getX());
                    isMapPoint.setY(motorMoveDetailDTO.getY());
                    isMapPointService.save(isMapPoint);
                }
            }
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean deleteIsMotorByMotorIds(String motorIds) {
        Assert.notBlank(motorIds, "请选择需要删除的数据!");
        Long[] longIds = Convert.toLongArray(motorIds);
        removeBatchByIds(Arrays.asList(longIds));
        // 需要删除is_map_point中的相关数据
        isMapPointService.remove(Wrappers.<IsMapPoint>lambdaQuery()
                .eq(IsMapPoint::getMapType, "4")
                .in(IsMapPoint::getEntityId, Arrays.asList(longIds)));
        return true;
    }

    @Transactional
    @Override
    public Boolean updateIsMotor(IsMotor isMotor) {
        IsMotor byId = getById(isMotor.getMotorId());
        Assert.isTrue(byId != null, "该电机数据不存在！");
        update(Wrappers.<IsMotor>lambdaUpdate()
                .eq(IsMotor::getMotorId, isMotor.getMotorId())
                .set(IsMotor::getMotorName, isMotor.getMotorName())
                .set(IsMotor::getMotorType, isMotor.getMotorType())
                .set(IsMotor::getMotorCode, isMotor.getMotorCode())
                .set(IsMotor::getPointId, isMotor.getPointId() != null ? isMotor.getPointId() : null));
        // 开始执行删除is_map_point数据
        if (isMotor.getPointId() == null || !byId.getPointId().equals(isMotor.getPointId())) {
            isMapPointService.remove(Wrappers.<IsMapPoint>lambdaQuery()
                    .eq(IsMapPoint::getMapType, "4")
                    .eq(IsMapPoint::getEntityId, byId.getMotorId()));
        }
        return true;
    }

    @Override
    public IsMotor selectIsMotorById(Long motorId) {
        IsMotor byId = getById(motorId);
        if (byId != null && byId.getPointId() != null) {
            IsIsolationPoint point = iIsIsolationPointService.getById(motorId);
            if (point != null) {
                byId.setPointName(point.getPointName());
            }
        }
        return byId;
    }

}

