package com.izouma.nineth.service;

import cn.hutool.core.collection.CollectionUtil;
import com.izouma.nineth.domain.Asset;
import com.izouma.nineth.domain.MetaItem;
import com.izouma.nineth.domain.SpaceObjectsInfo;
import com.izouma.nineth.dto.BuildingDTO;
import com.izouma.nineth.dto.BuildingPosDTO;
import com.izouma.nineth.dto.MetaRestResult;
import com.izouma.nineth.enums.MetaItemEnum;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.AssetRepo;
import com.izouma.nineth.repo.MetaItemRepo;
import com.izouma.nineth.repo.SpaceObjectsInfoRepo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

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

@Service
@AllArgsConstructor
public class MetaPlayerInfoService {

    private SpaceObjectsInfoRepo spaceObjectsInfoRepo;

    private AssetRepo assetRepo;

    private MetaItemRepo metaItemRepo;

    public MetaRestResult<SpaceObjectsInfo> metaSpaceInfo(Long userId, Long spaceId) {
        SpaceObjectsInfo spaceObjectsInfo = spaceObjectsInfoRepo.findBySpaceId(spaceId);
        if (Objects.isNull(spaceObjectsInfo)) {
            return MetaRestResult.returnError(String.format("不存在空间id：%S的空间信息", spaceId));
        }
        spaceObjectsInfo.setPersonal(spaceObjectsInfo.getUserId().equals(userId));
        // 如果是查询个人空间物品信息，统计用户剩余物品信息
        try {
            if (spaceObjectsInfo.isPersonal()) {
                List<SpaceObjectsInfo> spaceObjectsInfos = spaceObjectsInfoRepo.findAllByUserId(userId);
                spaceObjectsInfo.setBuildingList(buildingList(userId, spaceObjectsInfos));
            }
        } catch (Exception e) {
            return MetaRestResult.returnError(e.getMessage());
        }
        return MetaRestResult.returnSuccess(spaceObjectsInfo);
    }

    public MetaRestResult<SpaceObjectsInfo> updateMetaPersonalSpace(SpaceObjectsInfo spaceObjectsInfo) {
        if(Objects.isNull(spaceObjectsInfo.getId())) {
            return MetaRestResult.returnError("参数不合法，缺少空间物品信息记录id");
        }
        SpaceObjectsInfo dbSpaceObjectsInfo = spaceObjectsInfoRepo.findById(spaceObjectsInfo.getId()).orElse(null);
        if(Objects.isNull(dbSpaceObjectsInfo)) {
            return MetaRestResult.returnError(String.format("操作失败：不存在id[%S]的空间物品数据", spaceObjectsInfo.getSpaceId()));
        }
        List<BuildingPosDTO> buildingPosList = spaceObjectsInfo.getBuildingPosList();
        if (CollectionUtil.isEmpty(buildingPosList)) {
            dbSpaceObjectsInfo.setBuildingPosList(null);
            return MetaRestResult.returnSuccess(spaceObjectsInfoRepo.save(dbSpaceObjectsInfo));
        }
        Map<Long, Integer> map = new HashMap<>();
        // 统计要修改的个人空间各物品数据
        buildingPosList.forEach(buildingPosDTO -> {
            Long key = buildingPosDTO.getItemId();
            if (map.containsKey(key)) {
                map.put(key, map.get(key) + 1);
            } else {
                map.put(key, 1);
            }
        });
        List<SpaceObjectsInfo> spaceObjectsInfos = spaceObjectsInfoRepo.findAllByUserIdAndIdNot(dbSpaceObjectsInfo.getUserId(), dbSpaceObjectsInfo.getId());
        List<BuildingDTO> buildingDTOS = buildingList(dbSpaceObjectsInfo.getUserId(), spaceObjectsInfos);
        // 查询用户所有已经编辑过的物品id
        Set<Long> keys = map.keySet();
        if (!check(keys, buildingDTOS)) {
            return MetaRestResult.returnError("当前用户物品数据异常：用户未持有相关藏品，个人空间中有已编辑藏品信息");
        }
        // 比较个人空间拥有的各物品最大数量
        try {
            keys.forEach(key -> {
                buildingDTOS.forEach(buildingDTO -> {
                    if (key.equals(buildingDTO.getItmeId())) {
                        if (map.get(key) > buildingDTO.getCount()) {
                            throw new BusinessException("操作失败：当前用户修改该物品数量大于用户持有最大数量");
                        }
                    }
                });
            });
        } catch (Exception e) {
            return MetaRestResult.returnError(e.getMessage());
        }
        dbSpaceObjectsInfo.setBuildingPosList(spaceObjectsInfo.getBuildingPosList());
        return MetaRestResult.returnSuccess("修改成功", spaceObjectsInfoRepo.save(dbSpaceObjectsInfo));
    }

    private List<BuildingDTO> buildingList(Long userId, List<SpaceObjectsInfo> spaceObjectsInfos) {
        List<BuildingDTO> buildingList = new ArrayList<>();
        List<MetaItem> metaItems = metaItemRepo.findAllByType(MetaItemEnum.BUILDING);
        // 统计该用户所有物品信息
        metaItems.forEach(metaItem -> {
            List<Asset> assets = assetRepo.findAllByUserIdAndNameLike(userId, "%" + metaItem.getName() + "%");
            if (CollectionUtil.isNotEmpty(assets)) {
                buildingList.add(new BuildingDTO(metaItem.getId(), metaItem.getName(), assets.size()));
            }
        });
        // 如果该该用户没有空间信息直接返回 buildingList
        if (CollectionUtil.isEmpty(spaceObjectsInfos)) {
            return buildingList;
        }
        // 统计该用户已经编辑过的物品信息
        Map<Long, Integer> map = new HashMap<>();
        spaceObjectsInfos.forEach(spaceObjectsInfo -> {
            if (CollectionUtil.isNotEmpty(spaceObjectsInfo.getBuildingPosList())) {
                spaceObjectsInfo.getBuildingPosList().forEach(buildingPosDTO -> {
                    Long key = buildingPosDTO.getItemId();
                    if (map.containsKey(key)) {
                        map.put(key, map.get(key) + 1);
                    } else {
                        map.put(key, 1);
                    }
                });
            }
        });
        if(CollectionUtil.isEmpty(buildingList)) {
            // 如过buildingList为空，且用户有编辑过的物品返回错误
            if (CollectionUtil.isNotEmpty(map)) {
                throw new BusinessException("当前用户物品数据异常：用户未持有相关藏品，个人空间中有已编辑藏品信息");
            }
            // 如过buildingList为空，且用户没有编辑过物品 正常返回buildingList
            return buildingList;
        }
        // 如过buildingList不为为空，且用户没有编辑过物品，返回buildingList
        if (CollectionUtil.isEmpty(map)) {
            return buildingList;
        }
        // 查询用户所有已经编辑过的物品id
        Set<Long> keys = map.keySet();
        if (!check(keys, buildingList)) {
            throw new BusinessException("当前用户物品数据异常：用户未持有相关藏品，个人空间中有已编辑藏品信息");
        }
        // 查询剩余未编辑物品信息
        buildingList.forEach(buildingDTO -> {
            keys.forEach(key -> {
                if (buildingDTO.getItmeId().equals(key)) {
                    int newCount = buildingDTO.getCount() - map.get(key);
                    // 如果用户剩余物品数量为负数，返回失败
                    if (newCount < 0) {
                        throw new BusinessException("当前用户物品数据异常：个人空间中编辑存在物品编辑数量大于持有量");
                    }
                    buildingDTO.setCount(newCount);
                }
            });
        });
        // 返回用户剩余物品信息
        return buildingList;
    }

    public boolean check(Set<Long> keys, List<BuildingDTO> buildingList) {
        // 查询用户拥有的所有的物品id
        List<Long> all = buildingList.stream().map(BuildingDTO::getItmeId).collect(Collectors.toList());
        // 如果用户编辑过未拥有的物品返回错误
        return new HashSet<>(all).containsAll(keys);
    }
}
