package com.yeejoin.equipmanage.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.amos.component.robot.BadRequest;
import com.yeejoin.equipmanage.common.entity.*;
import com.yeejoin.equipmanage.common.entity.dto.CoreEquipmentsDto;
import com.yeejoin.equipmanage.common.entity.dto.FireFightingSystemGroupModalDto;
import com.yeejoin.equipmanage.common.entity.dto.SystemEquipmentsDto;
import com.yeejoin.equipmanage.mapper.EquipmentSpecificAlarmMapper;
import com.yeejoin.equipmanage.mapper.EquipmentSpecificMapper;
import com.yeejoin.equipmanage.mapper.FireFightingSystemGroupMapper;
import com.yeejoin.equipmanage.mapper.FireFightingSystemMapper;
import com.yeejoin.equipmanage.service.FireFightingSystemGroupService;
import com.yeejoin.equipmanage.service.IEquipmentService;
import com.yeejoin.equipmanage.service.IFireFightingSystemService;
import com.yeejoin.equipmanage.service.SystemEquipmentRelationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FireFightingSystemGroupServiceImpl extends ServiceImpl<FireFightingSystemGroupMapper, FireFightingSystemGroupEntity> implements FireFightingSystemGroupService {
    @Autowired
    private FireFightingSystemGroupMapper fireFightingSystemGroupMapper;
    @Autowired
    private SystemEquipmentRelationService systemEquipmentRelationService;
    @Autowired
    private FireFightingSystemMapper fireFightingSystemMapper;
    @Autowired
    private EquipmentSpecificMapper equipmentSpecificMapper;
    @Autowired
    private IFireFightingSystemService fireFightingSystemService;
    @Autowired
    private IEquipmentService equipmentService;
    @Autowired
    EquipmentSpecificAlarmMapper equipmentSpecificAlarmMapper;

    /**
     * 获取消防系统列表
     *
     * @param bizOrgCode bizOrgCode
     */
    @Override
    public JSONArray selectUnboundSystems(String bizOrgCode) {
        Wrapper<FireFightingSystemEntity> wrapper = Wrappers.<FireFightingSystemEntity>lambdaQuery()
                .likeRight(FireFightingSystemEntity::getBizOrgCode, bizOrgCode)
                .isNotNull(FireFightingSystemEntity::getName)
                .isNotNull(FireFightingSystemEntity::getSystemType);
        List<FireFightingSystemEntity> systems = fireFightingSystemService.list(wrapper);
        List<Long> systemIds = systems.stream().map(FireFightingSystemEntity::getId).collect(Collectors.toList());
        if (!systemIds.isEmpty()) {
            List<FireFightingSystemGroupEntity> entities = this.list();
            List<String> list = entities.stream().map(FireFightingSystemGroupEntity::getSystemIds).collect(Collectors.toList());
            List<Long> boundedSystemIds = list.stream().flatMap(s -> Arrays.stream(s.split(","))).map(Long::parseLong).collect(Collectors.toList());
            systemIds.removeAll(boundedSystemIds);
        }
        JSONArray result = new JSONArray();
        for (FireFightingSystemEntity system : systems) {
            Map<String, Object> jsonObject = new HashMap<>();
            jsonObject.put("id", system.getId());
            jsonObject.put("name", system.getName());
            if (!systemIds.contains(system.getId())) {
                // isBound: 是否已绑定分组
                jsonObject.put("isBound", true);
            } else {
                jsonObject.put("isBound", false);
            }
            result.add(jsonObject);
        }

        return result;
    }

    /**
     * 保存分组
     *
     * @param fireFightingSystemGroupModalDto 分组信息
     * @return 分组信息
     */
    @Override
    @Transactional
    public Boolean saveOrUpdate(FireFightingSystemGroupModalDto fireFightingSystemGroupModalDto) {
        if (!(Objects.nonNull(fireFightingSystemGroupModalDto.getGroupName()) && Objects.nonNull(fireFightingSystemGroupModalDto.getDisplayType()) && Objects.nonNull(fireFightingSystemGroupModalDto.getSystems()))) {
            throw new BadRequest("无效参数!");
        }

        // 分组名称唯一性校验
        if (Objects.isNull(fireFightingSystemGroupModalDto.getId())) {
            Integer count = fireFightingSystemGroupMapper.selectCount(
                    Wrappers.<FireFightingSystemGroupEntity>lambdaQuery()
                            .eq(FireFightingSystemGroupEntity::getGroupName, fireFightingSystemGroupModalDto.getGroupName())
            );
            if (count > 0) {
                throw new BadRequest("当前分组已存在!");
            }
        }

        List<SystemEquipmentsDto> systems = fireFightingSystemGroupModalDto.getSystems();

        // 更新数据前先清理解绑的系统与相关关系表的数据
        if (Objects.nonNull(fireFightingSystemGroupModalDto.getId())) {
            FireFightingSystemGroupEntity entity = fireFightingSystemGroupMapper.selectById(fireFightingSystemGroupModalDto.getId());
            List<String> systemIds = Arrays.asList(entity.getSystemIds().split(","));
            systemEquipmentRelationService.remove(
                    Wrappers.<SystemEquipmentRelationEntity>lambdaQuery()
                            .in(SystemEquipmentRelationEntity::getSystemId, systemIds)
            );
        }

        String[] sortedSystemIds = new String[systems.size()];
        for (SystemEquipmentsDto system : systems) {
            // 系统重排序
            sortedSystemIds[system.getSort()] = system.getId();
            // 构建系统与装备关系
            List<CoreEquipmentsDto> equipments = system.getEquipments();
            List<SystemEquipmentRelationEntity> relationEntities = equipments.stream()
                    .map(equipment -> SystemEquipmentRelationEntity.builder()
                            .systemId(Long.valueOf(system.getId()))
                            .equipmentId(Long.valueOf(equipment.getId()))
                            .type(equipment.getType())
                            .sort(equipment.getSort())
                            .build()
                    ).collect(Collectors.toList());
            if (!systemEquipmentRelationService.saveBatch(relationEntities)) {
                throw new BadRequest("保存分组关系失败!");
            }
        }

        // 分组信息入库
        FireFightingSystemGroupEntity fireFightingSystemGroupEntity = FireFightingSystemGroupEntity.builder()
                .groupName(fireFightingSystemGroupModalDto.getGroupName())
                .groupCode(new StringBuilder(String.valueOf(System.currentTimeMillis())).reverse().toString())
                .displayType(fireFightingSystemGroupModalDto.getDisplayType())
                .systemIds(String.join(",", sortedSystemIds))
                .remarks("")
                .sort(Objects.nonNull(fireFightingSystemGroupModalDto.getSort()) ? fireFightingSystemGroupModalDto.getSort() : 0)
                .bizOrgName(fireFightingSystemGroupModalDto.getBizOrgName())
                .bizOrgCode(fireFightingSystemGroupModalDto.getBizOrgCode())
                .build();
        if (Objects.nonNull(fireFightingSystemGroupModalDto.getId())) {
            fireFightingSystemGroupEntity.setId(Long.valueOf(fireFightingSystemGroupModalDto.getId()));
        }
        return this.saveOrUpdate(fireFightingSystemGroupEntity);
    }

    /**
     * 更新分组排序
     *
     * @param groupIds 分组ID
     */
    @Override
    @Transactional
    public void updateGroupSort(List<Long> groupIds) {
        if (Objects.isNull(groupIds) || groupIds.isEmpty()) {
            throw new BadRequest("无效参数!");
        }
        Collection<FireFightingSystemGroupEntity> entities = this.listByIds(groupIds);
        for (int i = 0; i < groupIds.size(); i++) {
            final int sort = i;
            entities.stream().filter(entity -> entity.getId().equals(groupIds.get(sort))).findFirst().ifPresent(entity -> entity.setSort(sort));
        }
        this.updateBatchById(entities);
    }

    /**
     * 更新系统排序
     *
     * @param groupId   分组ID
     * @param systemIds 系统ID
     */
    @Override
    public void updateSystemSort(Long groupId, List<Long> systemIds) {
        if (Objects.isNull(groupId) || Objects.isNull(systemIds)) {
            throw new BadRequest("无效参数!");
        }
        FireFightingSystemGroupEntity entity = this.getById(groupId);
        if (Objects.isNull(entity)) {
            throw new BadRequest("分组不存在!");
        }
        String systemIdsStr = systemIds.stream().map(String::valueOf).collect(Collectors.joining(","));
        entity.setSystemIds(systemIdsStr);
        this.updateById(entity);
    }

    /**
     * 获取分组
     *
     * @param bizOrgCode 业务组织编码
     * @return 分组列表
     */
    @Override
    @SuppressWarnings("unchecked")
    public JSONArray listGroup(String bizOrgCode) {
        List<FireFightingSystemGroupEntity> groupEntities = fireFightingSystemGroupMapper.selectList(
                Wrappers.<FireFightingSystemGroupEntity>lambdaQuery()
                        .likeRight(FireFightingSystemGroupEntity::getBizOrgCode, bizOrgCode)
                        .orderByAsc(FireFightingSystemGroupEntity::getSort, FireFightingSystemGroupEntity::getCreateDate)
        );
        List<Long> systemIds = groupEntities.stream().map(FireFightingSystemGroupEntity::getSystemIds).map(s -> s.split(",")).flatMap(Arrays::stream).map(Long::parseLong).collect(Collectors.toList());
        if (systemIds.isEmpty()) {
            return new JSONArray();
        }

        // List to Map -> key: systemId, value: FireFightingSystemEntity
        Map<Long, FireFightingSystemEntity> systemMap = fireFightingSystemMapper.selectList(
                Wrappers.<FireFightingSystemEntity>lambdaQuery()
                        .in(FireFightingSystemEntity::getId, systemIds)
        ).stream().map(fireFightingSystemEntity -> new HashMap<Long, FireFightingSystemEntity>() {{
            put(fireFightingSystemEntity.getId(), fireFightingSystemEntity);
        }}).collect(Collectors.toMap(map -> map.keySet().iterator().next(), map -> map.values().iterator().next()));

        // List to Map -> key: equipmentId, value: List<SystemEquipmentRelationEntity>
        Map<Long, List<SystemEquipmentRelationEntity>> systemEquipmentMap = new HashMap<>();
        List<SystemEquipmentRelationEntity> systemEquipmentRelationEntities = systemEquipmentRelationService.list(
                Wrappers.<SystemEquipmentRelationEntity>lambdaQuery()
                        .in(SystemEquipmentRelationEntity::getSystemId, systemIds)
        );
        for (SystemEquipmentRelationEntity systemEquipmentRelation : systemEquipmentRelationEntities) {
            if (systemEquipmentMap.containsKey(systemEquipmentRelation.getSystemId())) {
                systemEquipmentMap.get(systemEquipmentRelation.getSystemId()).add(systemEquipmentRelation);
            } else {
                List<SystemEquipmentRelationEntity> list = new ArrayList<>();
                list.add(systemEquipmentRelation);
                systemEquipmentMap.put(systemEquipmentRelation.getSystemId(), list);
            }
        }

        // 查询装备定义的图片 List to Map -> key: equipmentId, value: equipmentEntity
        Set<Long> equipmentIds = systemEquipmentMap.values().stream().flatMap(list -> list.stream().map(SystemEquipmentRelationEntity::getEquipmentId)).collect(Collectors.toSet());
        Map<Long, Equipment> equipmentImageMap = equipmentService.list(
                Wrappers.<Equipment>lambdaQuery()
                        .select(Equipment::getId, Equipment::getShbzImg, Equipment::getImg)
                        .in(!equipmentIds.isEmpty(), Equipment::getId, equipmentIds)
        ).stream().map(equipmentEntity -> new HashMap<Long, Equipment>() {{
            put(equipmentEntity.getId(), equipmentEntity);
        }}).collect(Collectors.toMap(map -> map.keySet().iterator().next(), map -> map.values().iterator().next()));

        // List to Map -> key: systemId@equipmentId, value: 装备定义数量Map
        List<Map<String, Object>> equipmentCountList = equipmentSpecificMapper.getEquipmentCount(bizOrgCode);
        Map<String, Map<String, Object>> equipmentCountMap = new HashMap<>();
        for (Map<String, Object> map : equipmentCountList) {
            String equipmentId = map.getOrDefault("equipmentId", "").toString();
            String systemId = map.getOrDefault("systemId", "").toString();
            String[] ids = systemId.split(",");
            for (String id : ids) {
                String uniqueKey = id + "@" + equipmentId;
                if (equipmentCountMap.containsKey(uniqueKey)) {
                    Map<String, Object> objectMap = equipmentCountMap.get(uniqueKey);
                    long count = Long.parseLong(map.getOrDefault("count", "0").toString()) + Long.parseLong(objectMap.getOrDefault("count", 0).toString());
                    objectMap.put("count", count);
                } else {
                    Map<String, Object> newMap = new HashMap<>();
                    Set<Map.Entry<String, Object>> entries = map.entrySet();
                    for (Map.Entry<String, Object> entry : entries) {
                        newMap.put(entry.getKey(), entry.getValue());
                    }
                    equipmentCountMap.put(uniqueKey, newMap);
                }
            }
        }
        List<Map<String, Long>> systemEquipCountMaps = equipmentSpecificMapper.getEquipmentCountBySystemId(bizOrgCode, systemIds);

        // 构建分组对象
        JSONArray groups = new JSONArray();
        for (FireFightingSystemGroupEntity groupEntity : groupEntities) {
            JSONObject group = new JSONObject();
            JSONArray systems = new JSONArray();
            group.put("id", groupEntity.getId());
            group.put("groupName", groupEntity.getGroupName());
            group.put("displayType", groupEntity.getDisplayType());
            group.put("sort", groupEntity.getSort());
            group.put("systems", systems);
            List<Long> entitySystemIds = Arrays.stream(groupEntity.getSystemIds().split(",")).map(Long::parseLong).collect(Collectors.toList());
            int size = entitySystemIds.size();
            for (int i = 0; i < size; i++) {
                Long systemId = entitySystemIds.get(i);
                JSONObject system = new JSONObject();
                FireFightingSystemEntity systemEntity = systemMap.get(systemId);
                int equipmentSpeCount = equipmentSpecificMapper.getSystemAlarmNum(systemId);
                Integer count = equipmentSpecificAlarmMapper.selectCount(
                        Wrappers.<EquipmentSpecificAlarm>lambdaQuery()
                                .like(EquipmentSpecificAlarm::getSystemIds, systemId)
                                .eq(EquipmentSpecificAlarm::getStatus, "1")
                                .likeRight(StringUtils.hasText(bizOrgCode), EquipmentSpecificAlarm::getBizOrgCode, bizOrgCode)
                );
                List<SystemEquipmentRelationEntity> relationEntities = Objects.nonNull(systemEquipmentMap.get(systemId)) ? systemEquipmentMap.get(systemId) : new ArrayList<>();
                system.put("id", systemId);
                system.put("alarmCount", count);
                system.put("code", systemEntity.getCode());
                system.put("typeCode", systemEntity.getSystemTypeCode());
                system.put("name", systemEntity.getName());
                system.put("systemState", equipmentSpeCount);
                system.put("systemRunState", systemEntity.getSystemRunState());
                system.put("protectObject", systemEntity.getProObject());
                system.put("systemDesc", systemEntity.getSystemDescribe());
                system.put("sort", i);

                List<Map<String, Object>> equipments = new ArrayList<>();
                for (SystemEquipmentRelationEntity relationEntity : relationEntities) {
                    Long equipmentId = relationEntity.getEquipmentId();
                    if (equipmentCountMap.containsKey(systemId + "@" + equipmentId)) {
                        Map<String, Object> equipmentMap = equipmentCountMap.get(systemId + "@" + equipmentId);
                        Equipment imageEquipment = equipmentImageMap.get(equipmentId);
                        Map<String, Object> equipment = new HashMap<>();
                        equipment.put("id", equipmentMap.get("equipmentId"));
                        equipment.put("name", equipmentMap.get("equipmentName"));
                        equipment.put("num", Integer.valueOf(equipmentMap.getOrDefault("count", "0").toString()));
                        equipment.put("unit", equipmentMap.get("unit"));
                        if (Objects.nonNull(imageEquipment)) {
//                            equipment.put("img", StringUtils.hasText(imageEquipment.getShbzImg()) ? imageEquipment.getShbzImg() : imageEquipment.getImg());
                            equipment.put("img", imageEquipment.getImg());
                        }
                        equipment.put("sort", relationEntity.getSort());
                        equipment.put("type", relationEntity.getType());
                        equipments.add(equipment);
                    }
                }
                system.put("equipments", equipments);
                AtomicLong equipmentCount = new AtomicLong(0);
                systemEquipCountMaps.forEach(map -> {
                    if (String.valueOf(map.get("systemId")).matches(".*" + systemId + ".*")) {
                        equipmentCount.addAndGet(Long.parseLong(map.getOrDefault("count", 0L).toString()));
                    }
                });
                system.put("equipmentCount", equipmentCount.get());
                systems.add(system);
            }
            groups.add(group);
        }
        return groups;
    }

    /**
     * 删除分组
     *
     * @param groupId
     */
    @Override
    @Transactional
    public void deleteGroup(Long groupId) {
        FireFightingSystemGroupEntity groupEntity = fireFightingSystemGroupMapper.selectById(groupId);
        if (Objects.isNull(groupEntity)) {
            throw new BadRequest("分组不存在");
        }

        String systemIds = groupEntity.getSystemIds();
        List<Long> systemIdList = Arrays.stream(systemIds.split(",")).map(Long::parseLong).collect(Collectors.toList());
        // 删除映射关系
        systemEquipmentRelationService.remove(
                Wrappers.<SystemEquipmentRelationEntity>lambdaQuery()
                        .in(!systemIdList.isEmpty(), SystemEquipmentRelationEntity::getSystemId, systemIdList)
        );
        // 删除分组
        fireFightingSystemGroupMapper.deleteById(groupId);
    }
}
