package com.zksy.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zksy.base.constant.GasEquipmentTypeEnum;
import com.zksy.base.domain.*;
import com.zksy.base.domain.vo.EquipmentFullVO;
import com.zksy.base.mapper.*;
import com.zksy.base.service.GasEquipmentService;
import com.zksy.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class GasEquipmentServiceImpl implements GasEquipmentService {

    @Autowired
    private EquipmentBaseMapper equipmentBaseMapper;

    @Autowired
    private EquipmentTypeMapper equipmentTypeMapper;

    @Autowired
    private EquipmentMaintainMapper equipmentMaintainMapper;

    @Autowired
    private EquipmentStatusMapper equipmentStatusMapper;

    @Autowired
    private EquipmentPointRelMapper equipmentPointRelMapper;

    @Autowired
    private EquipmentTestMapper equipmentTestMapper;

    @Autowired
    private GasPipePointDeviceRelMapper gasPipePointDeviceRelMapper;

    @Autowired
    private GasPipePointMapper gasPipePointMapper;

    @Autowired
    private PipeNetworkBaseMapper pipeNetworkBaseMapper;

    @Override
    public boolean saveWithCheck(EquipmentBase entity) {
        String equipmentTypeId = entity.getEquipmentTypeId();
        EquipmentType equipmentType = equipmentTypeMapper.selectById(equipmentTypeId);
        if (equipmentType == null) {
            throw new ServiceException("设备类型不存在，请检查 equipment_type_id");
        }
            
        // ========== 新增：根据片区自动生成设备编码 ==========
        String district = entity.getDistrict();
        if (district != null && !district.trim().isEmpty() && 
            (entity.getEquipmentCode() == null || entity.getEquipmentCode().trim().isEmpty())) {
            String prefix = getDistrictPrefix(district);
                
            // 查询该片区已存在的设备数量
            LambdaQueryWrapper<EquipmentBase> codeWrapper = new LambdaQueryWrapper<>();
            codeWrapper.likeRight(EquipmentBase::getEquipmentCode, prefix + "-GAS-");
            Long count = equipmentBaseMapper.selectCount(codeWrapper);
                
            // 生成下一个序列号
            String seq = String.format("%03d", count + 1);
            entity.setEquipmentCode(prefix + "-GAS-" + seq);
        }
        // ===============================================
            
        // 检查唯一性
        LambdaQueryWrapper<EquipmentBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EquipmentBase::getEquipmentCode, entity.getEquipmentCode());
        long totalCount = equipmentBaseMapper.selectCount(queryWrapper);
        if (totalCount > 0) {
            throw new ServiceException("设备编码已存在，请更换：" + entity.getEquipmentCode());
        }
            
        try {
            return equipmentBaseMapper.insert(entity) > 0;
        } catch (org.springframework.dao.DataIntegrityViolationException e) {
            if (e.getMessage() != null && e.getMessage().contains("uk_equipment_code")) {
                throw new ServiceException("设备编码已存在，请更换：" + entity.getEquipmentCode());
            }
            throw e;
        }
    }
        
    /**
     * 获取片区前缀映射
     */
    private String getDistrictPrefix(String district) {
        if ("城南".equals(district)) {
            return "CN";
        } else if ("城北".equals(district)) {
            return "CB";
        } else if ("太常".equals(district)) {
            return "TC";
        }
        return "QT"; // 其他区域默认前缀
    }

    @Override
    @Transactional
    public boolean updateWithCheck(EquipmentBase entity) {
        String equipmentId = entity.getEquipmentId();
        if (equipmentBaseMapper.selectById(equipmentId) == null) {
            throw new ServiceException("设备不存在，无法修改：" + equipmentId);
        }

        String newTypeId = entity.getEquipmentTypeId();
        if (newTypeId != null && equipmentTypeMapper.selectById(newTypeId) == null) {
            throw new ServiceException("设备类型不存在：" + newTypeId);
        }

        String newCode = entity.getEquipmentCode();
        if (newCode != null) {
            LambdaQueryWrapper<EquipmentBase> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(EquipmentBase::getEquipmentCode, newCode)
                    .ne(EquipmentBase::getEquipmentId, equipmentId);
            if (equipmentBaseMapper.selectCount(wrapper) > 0) {
                throw new ServiceException("设备编码已被使用：" + newCode);
            }
        }
        return equipmentBaseMapper.updateById(entity) > 0;
    }

    @Override
    @Transactional
    public boolean removeWithCheck(String equipmentId) {
        EquipmentBase equipment = equipmentBaseMapper.selectById(equipmentId);
        if (equipment == null) {
            throw new ServiceException("设备不存在：" + equipmentId);
        }

        LambdaQueryWrapper<EquipmentMaintain> maintainWrapper = new LambdaQueryWrapper<>();
        maintainWrapper.eq(EquipmentMaintain::getEquipmentId, equipmentId);
        equipmentMaintainMapper.delete(maintainWrapper);
        log.info("已删除设备[{}]的维护记录", equipmentId);

        LambdaQueryWrapper<EquipmentStatus> statusWrapper = new LambdaQueryWrapper<>();
        statusWrapper.eq(EquipmentStatus::getEquipmentId, equipmentId);
        equipmentStatusMapper.delete(statusWrapper);
        log.info("已删除设备[{}]的状态记录", equipmentId);

        LambdaQueryWrapper<EquipmentPointRel> relWrapper = new LambdaQueryWrapper<>();
        relWrapper.eq(EquipmentPointRel::getEquipmentId, equipmentId);
        equipmentPointRelMapper.delete(relWrapper);
        log.info("已删除设备[{}]的监测点关联", equipmentId);

        LambdaQueryWrapper<EquipmentTest> testWrapper = new LambdaQueryWrapper<>();
        testWrapper.eq(EquipmentTest::getEquipmentId, equipmentId);
        equipmentTestMapper.delete(testWrapper);
        log.info("已删除设备[{}]的测试记录", equipmentId);

        return equipmentBaseMapper.deleteById(equipmentId) > 0;
    }

    @Override
    public Page<EquipmentFullVO> findFullByPage(long pageNum, long pageSize,
                                                 String equipmentCode, String equipmentName,
                                                 String equipmentModel, String manufacturer,String district) {
        // 只查燃气类型设备: parent_type_id = "3"
        List<String> gasTypeIds = equipmentTypeMapper.selectList(
                new LambdaQueryWrapper<EquipmentType>().eq(EquipmentType::getParentTypeId, GasEquipmentTypeEnum.PARENT_TYPE_ID)
        ).stream().map(EquipmentType::getId).collect(Collectors.toList());

        Page<EquipmentBase> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<EquipmentBase> qw = new LambdaQueryWrapper<>();
        if (!gasTypeIds.isEmpty()) {
            qw.in(EquipmentBase::getEquipmentTypeId, gasTypeIds);
        }
        if (equipmentCode != null && !equipmentCode.isEmpty()) {
            qw.like(EquipmentBase::getEquipmentCode, equipmentCode);
        }
        if (equipmentName != null && !equipmentName.isEmpty()) {
            qw.like(EquipmentBase::getEquipmentName, equipmentName);
        }
        if (equipmentModel != null && !equipmentModel.isEmpty()) {
            qw.like(EquipmentBase::getEquipmentModel, equipmentModel);
        }
        if (manufacturer != null && !manufacturer.isEmpty()) {
            qw.like(EquipmentBase::getManufacturer, manufacturer);
        }
        // 添加片区筛选条件
        if (district != null && !district.isEmpty()) {
            qw.eq(EquipmentBase::getDistrict, district);
        }
        qw.orderByDesc(EquipmentBase::getCreateTime);
        Page<EquipmentBase> basePage = equipmentBaseMapper.selectPage(page, qw);
        List<EquipmentBase> equipmentList = basePage.getRecords();
        if (CollUtil.isEmpty(equipmentList)) {
            Page<EquipmentFullVO> emptyPage = new Page<>(pageNum, pageSize, 0);
            emptyPage.setRecords(new ArrayList<>());
            return emptyPage;
        }

        List<String> equipmentIds = equipmentList.stream()
                .map(EquipmentBase::getEquipmentId).collect(Collectors.toList());

        // 2. 批量查设备状态
        List<EquipmentStatus> statusList = equipmentStatusMapper.selectList(
                new LambdaQueryWrapper<EquipmentStatus>().in(EquipmentStatus::getEquipmentId, equipmentIds));
        Map<String, EquipmentStatus> statusMap = statusList.stream()
                .collect(Collectors.toMap(EquipmentStatus::getEquipmentId, Function.identity(), (a, b) -> a));

        // 3. 批量查管点-设备关联
        List<GasPipePointDeviceRel> allRels = gasPipePointDeviceRelMapper.selectList(
                new LambdaQueryWrapper<GasPipePointDeviceRel>().in(GasPipePointDeviceRel::getEquipmentId, equipmentIds));
        Map<String, GasPipePointDeviceRel> relMap = allRels.stream()
                .collect(Collectors.toMap(GasPipePointDeviceRel::getEquipmentId, Function.identity(), (a, b) -> a));

        // 4. 批量查管点
        List<Long> pointIds = allRels.stream().map(GasPipePointDeviceRel::getPointId).distinct().collect(Collectors.toList());
        Map<Long, GasPipePoint> pointMap = new HashMap<>();
        if (CollUtil.isNotEmpty(pointIds)) {
            List<GasPipePoint> pointList = gasPipePointMapper.selectBatchIds(pointIds);
            pointMap = pointList.stream()
                    .collect(Collectors.toMap(GasPipePoint::getPointId, Function.identity(), (a, b) -> a));
        }

        // 5. 批量查管线
        List<String> networkIds = pointMap.values().stream()
                .map(GasPipePoint::getNetworkId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<String, PipeNetworkBase> networkMap = new HashMap<>();
        if (CollUtil.isNotEmpty(networkIds)) {
            List<PipeNetworkBase> networkList = pipeNetworkBaseMapper.selectBatchIds(networkIds);
            networkMap = networkList.stream()
                    .collect(Collectors.toMap(PipeNetworkBase::getNetworkId, Function.identity(), (a, b) -> a));
        }

        // 6. 组装VO
        List<EquipmentFullVO> voList = new ArrayList<>();
        for (EquipmentBase equip : equipmentList) {
            EquipmentFullVO vo = new EquipmentFullVO();
            BeanUtil.copyProperties(equip, vo);

            EquipmentStatus status = statusMap.get(equip.getEquipmentId());
            if (status != null) {
                vo.setCurrentStatus(status.getCurrentStatus());
                vo.setAlarmStatus(status.getAlarmStatus());
                vo.setOnlineStatus(status.getOnlineStatus());
                vo.setLastMaintainDate(status.getLastMaintainDate());
                vo.setNextMaintainDate(status.getNextMaintainDate());
            } else {
                vo.setCurrentStatus(1);
                vo.setAlarmStatus(0);
                vo.setOnlineStatus(0);
            }

            GasPipePointDeviceRel rel = relMap.get(equip.getEquipmentId());
            if (rel != null) {
                GasPipePoint point = pointMap.get(rel.getPointId());
                if (point != null) {
                    vo.setPointId(point.getPointId());
                    vo.setPointCode(point.getPointCode());
                    vo.setPointName(point.getPointName());
                    vo.setPointType(point.getPointType());
                    vo.setPointAddress(point.getAddress());

                    PipeNetworkBase network = networkMap.get(point.getNetworkId());
                    if (network != null) {
                        vo.setNetworkId(network.getNetworkId());
                        vo.setNetworkCode(network.getNetworkCode());
                        vo.setNetworkName(network.getNetworkName());
                        vo.setNetworkType(network.getNetworkType());
                        vo.setNetworkLevel(network.getNetworkLevel());
                    }
                }
            }

            voList.add(vo);
        }

        Page<EquipmentFullVO> resultPage = new Page<>(pageNum, pageSize, basePage.getTotal());
        resultPage.setRecords(voList);
        return resultPage;
    }
}
