package com.YuyeTech.HeartRate.game.gameInfo.service;

import com.YuyeTech.HeartRate.common.service.CommonServiceImpl;
import com.YuyeTech.HeartRate.dto.GameDTO;
import com.YuyeTech.HeartRate.dto.GameTagDTO;
import com.YuyeTech.HeartRate.enums.PictureType;
import com.YuyeTech.HeartRate.exception.UserException;
import com.YuyeTech.HeartRate.game.gameInfo.repository.GamePicturesRepository;
import com.YuyeTech.HeartRate.game.gameInfo.vo.GameInfoVo;
import com.YuyeTech.HeartRate.game.gameInfo.vo.GameTagReferenceVo;
import com.YuyeTech.HeartRate.game.gameInfo.projo.GameInfo;
import com.YuyeTech.HeartRate.game.gameInfo.repository.GameInfoRepository;
import com.YuyeTech.HeartRate.game.imageInfo.service.PicturesService;
import com.YuyeTech.HeartRate.utils.AliyunOSSUtil;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author:slambb
 * @date:2020/1/10
 */
@Service
@Transactional
public class GameInfoServiceImpl extends CommonServiceImpl<GameInfoVo, GameInfo, String> implements GameInfoService {
    @PersistenceContext
    private EntityManager em;

    @Autowired
    private GameInfoRepository gameInfoRepository;

    @Autowired
    private GamePicturesRepository gamePicturesRepository;

//    @Autowired
//    private PicturesRepository picturesRepository;

    @Autowired
    private PicturesService picturesService;

    @Autowired
    private AliyunOSSUtil aliyunOSSUtil;

    @Autowired
    private FavoritesService favoritesService;

    @Autowired
    private GameTagReferenceService gameTagReferenceService;

    /**
     * 实现查询游戏类目对应的列表
     *
     * @param categoryType
     * @param pageable
     * @return
     */
    @Override
    public List<GameDTO> findList(String userId, Integer categoryType, String endTime, Pageable pageable) {

        //排序规则和分页
        Specification<GameInfo> specification = new Specification<GameInfo>() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //增加筛选条件
                Predicate predicate = cb.conjunction();
                predicate.getExpressions().add(cb.equal(root.get("gameStatus").as(String.class), 1));

                if (categoryType != 0) {
                    predicate.getExpressions().add(cb.equal(root.get("gameType").as(String.class), categoryType));
                }

                //结束日期
//                if (endTime != null && !endTime.trim().equals("")) {
//                    predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("showTime").as(String.class), endTime));
//                }

                return predicate;
            }
        };
        List<GameDTO> gameDTOList = gameInfoRepository.findAll(specification, pageable).stream().map(e -> new GameDTO(
                e.getGameId(),
                e.getGameName(),
                aliyunOSSUtil.addDomainName(e.getGameIcon()),
                e.getGameDescription(),
                aliyunOSSUtil.addDomainName(e.getGamePicture()),
                //获取收藏信息
                favoritesService.findByUserIdAndFObjectId(userId, e.getGameId()),
                e.getGameRankingId(),
                e.getGameRankingShow().equals(1),
                e.getCreateTime(),
                gameTagReferenceService.findGameTagByGameId(e.getGameRankingId(), e.getGameId()),
                e.getPlatform()
        )).collect(Collectors.toList());
        return gameDTOList;
    }

    @Override
    public List<GameDTO> findListByTypeAndPlatform(String userId, Integer categoryType, Integer platform, String endTime, Pageable pageable) {

        //排序规则和分页
        Specification<GameInfo> specification = new Specification<GameInfo>() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //增加筛选条件
                Predicate predicate = cb.conjunction();
                predicate.getExpressions().add(cb.equal(root.get("gameStatus").as(String.class), 1));

                if (categoryType != 0) {
                    predicate.getExpressions().add(cb.equal(root.get("gameType").as(String.class), categoryType));
                }

                Predicate p1 = cb.equal(root.get("platform").as(String.class), platform);
                Predicate p2 = cb.equal(root.get("platform").as(String.class), 2);
                predicate.getExpressions().add(cb.or(p1, p2));

                //结束日期
//                if (endTime != null && !endTime.trim().equals("")) {
//                    predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("showTime").as(String.class), endTime));
//                }

                return predicate;
            }
        };
        List<GameDTO> gameDTOList = gameInfoRepository.findAll(specification, pageable).stream().map(e -> new GameDTO(
                e.getGameId(),
                e.getGameName(),
                aliyunOSSUtil.addDomainName(e.getGameIcon()),
                e.getGameDescription(),
                aliyunOSSUtil.addDomainName(e.getGamePicture()),
                //获取收藏信息
                favoritesService.findByUserIdAndFObjectId(userId, e.getGameId()),
                e.getGameRankingId(),
                e.getGameRankingShow().equals(1),
                e.getCreateTime(),
                gameTagReferenceService.findGameTagByGameId(e.getGameRankingId(), e.getGameId()),
                e.getPlatform()
        )).collect(Collectors.toList());
        return gameDTOList;
    }


    @Override
    public List<GameDTO> findListByTag(String userId, Integer categoryType, Integer platform, Integer tagId, Pageable pageable) {
        GameTagReferenceVo gameTagVo = new GameTagReferenceVo();
        gameTagVo.setTagId(tagId);
        List<GameTagReferenceVo> gameTagList = gameTagReferenceService.listVo(gameTagVo);
        List<String> gameIdList = gameTagList.stream().map(GameTagReferenceVo::getGameId).collect(Collectors.toList());

        //排序规则和分页
        Specification<GameInfo> specification = new Specification<GameInfo>() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                //增加筛选条件
                Predicate predicate = cb.conjunction();
                predicate.getExpressions().add(cb.equal(root.get("gameStatus").as(String.class), 1));

                if (categoryType != 0) {
                    predicate.getExpressions().add(cb.equal(root.get("gameType").as(String.class), categoryType));
                }

                Predicate p1 = cb.equal(root.get("platform").as(String.class), platform);
                Predicate p2 = cb.equal(root.get("platform").as(String.class), 2);
                predicate.getExpressions().add(cb.or(p1, p2));

                //game ids  in
                List<Predicate> list = com.google.common.collect.Lists.newArrayList();
                if(null!=gameIdList&& gameIdList.size()>0){
                    CriteriaBuilder.In<String> in = cb.in(root.get("gameId"));
                    for (String id : gameIdList) {
                        in.value(id);
                    }
                    list.add(in);
                }
                predicate.getExpressions().add(cb.and(list.toArray(new Predicate[list.size()])));

                return predicate;
            }
        };

        List<GameDTO> gameDTOList = gameInfoRepository.findAll(specification, pageable).stream().map(e -> new GameDTO(
                e.getGameId(),
                e.getGameName(),
                aliyunOSSUtil.addDomainName(e.getGameIcon()),
                e.getGameDescription(),
                aliyunOSSUtil.addDomainName(e.getGamePicture()),
                //获取收藏信息
                favoritesService.findByUserIdAndFObjectId(userId, e.getGameId()),
                e.getGameRankingId(),
                e.getGameRankingShow().equals(1),
                e.getCreateTime(),
                gameTagReferenceService.findGameTagByGameId(e.getGameRankingId(), e.getGameId()),
                e.getPlatform()
        )).collect(Collectors.toList());

        return gameDTOList;
    }

    @Override
    public Page<GameInfo> findPage(String userId, Integer categoryType, Pageable pageable) {
        //假如是0的话，分页查询全部数据
        if (categoryType == 0) {
            Page<GameInfo> gameInfos = gameInfoRepository.findAll(pageable);
            List<GameInfo> gameInfoList = gameInfos.stream().map(e -> {
                e.setGameIcon(aliyunOSSUtil.addDomainName(e.getGameIcon()));
                e.setGamePicture(aliyunOSSUtil.addDomainName(e.getGamePicture()));
                return e;
            }).collect(Collectors.toList());

            return new PageImpl<GameInfo>(gameInfoList, pageable, gameInfos.getTotalElements());
        } else {
            Page<GameInfo> gameInfos = gameInfoRepository.findPageByGameType(categoryType, pageable);
            List<GameInfo> gameInfoList = gameInfos.stream().map(e -> {
                e.setGameIcon(aliyunOSSUtil.addDomainName(e.getGameIcon()));
                e.setGamePicture(aliyunOSSUtil.addDomainName(e.getGamePicture()));
                return e;
            }).collect(Collectors.toList());

            return new PageImpl<GameInfo>(gameInfoList, pageable, gameInfos.getTotalElements());
        }
    }

    @Override
    public List<GameInfo> findAll() {
        return gameInfoRepository.findAll();
    }

    /**
     * 查询游戏详情
     *
     * @param gameId
     * @param addDomain
     * @return
     */
    @Override
    public Map findByGameDetail(String gameId, Boolean addDomain) {
        //1.先查游戏基本数据
        GameInfo gameInfo = findByGameId(gameId, addDomain);

        //2.根据游戏id 在游戏图片 查询图片相关id（后续废弃这个操作）
        List<Integer> pictureIds = gamePicturesRepository.findByGameId(gameId).stream().map(
                e -> e.getPictureId()).collect(Collectors.toList());

        //3.根据图片id
        List<String> picturesList = new ArrayList<>();
        //关联旧数据（这里是兼容处理旧图片）
        if (pictureIds.size() != 0) {
            if (addDomain) {
                picturesList = picturesService.findAllByPictureIdListAndDomain(pictureIds);
            } else {
                picturesList = picturesService.findAllByPictureIdListAndNoDomain(pictureIds);
            }
        }
        //再查询图片库是否还有新增的图片url
        List<String> picturesList1 = picturesService.findByPictureTypeAndAssociatedId(PictureType.GAME_SCROLL.ordinal(), gameInfo.getGameId()).stream()
                .map(e -> addDomain ? aliyunOSSUtil.addDomainName(e.getPictureUrl()) : e.getPictureUrl()).collect(Collectors.toList());

        List<GameTagDTO> gameTagDTOS = gameTagReferenceService.findGameTagByGameId(gameInfo.getGameRankingId(), gameInfo.getGameId());
        picturesList.addAll(picturesList1);

        Map map = new HashMap();
        map.put("gameInfo", gameInfo);
        map.put("gamePicturesList", picturesList);
        map.put("gameTags", gameTagDTOS);
        return map;
    }

    @Override
    public GameInfo addGameInfo(GameInfo gameInfo) {
        return gameInfoRepository.save(gameInfo);
    }

    @Override
    public GameInfo addGameInfoAndFlush(GameInfo gameInfo) {
        return gameInfoRepository.saveAndFlush(gameInfo);
    }


    @Override
    public GameInfo findByGameId(String gameId, Boolean bDomain) {
        //1.先查游戏基本数据
        GameInfo gameInfo = gameInfoRepository.findByGameId(gameId);
        if (gameInfo != null && bDomain) {
            //修改url，添加访问域名
            String gameIcon = gameInfo.getGameIcon();
            if (gameIcon != null) {
                String urlIcon = aliyunOSSUtil.addDomainName(gameIcon);
                gameInfo.setGameIcon(urlIcon);
            }
            String gamePicture = gameInfo.getGamePicture();
            if (gamePicture != null) {
                String urlPicture = aliyunOSSUtil.addDomainName(gamePicture);
                gameInfo.setGamePicture(urlPicture);
            }
            //清楚对象缓存，避免update到数据库
            Session session = em.unwrap(Session.class);
            session.evict(gameInfo);
        }
        return gameInfo;
    }

    @Override
    public String deleteByGameId(String gameId) {
        try {
            gameInfoRepository.deleteById(gameId);
        } catch (UserException e) {
            return "error";
        }
        return "success";
    }

    @Override
    public List<GameDTO> findAllByRankingShow(String userId, Integer rankingShow, Pageable pageable) {

        List<GameDTO> gameDTOList = gameInfoRepository.findAllByGameRankingShow(rankingShow, pageable).stream().map(e -> new GameDTO(
                e.getGameId(),
                e.getGameName(),
                aliyunOSSUtil.addDomainName(e.getGameIcon()),
                e.getGameDescription(),
                aliyunOSSUtil.addDomainName(e.getGamePicture()),
                //获取收藏信息
                favoritesService.findByUserIdAndFObjectId(userId, e.getGameId()),
                e.getGameRankingId(),
                e.getGameRankingShow().equals(1),
                e.getCreateTime(),
                gameTagReferenceService.findGameTagByGameId(e.getGameRankingId(), e.getGameId()),
                e.getPlatform()
        )).collect(Collectors.toList());
        return gameDTOList;
    }

    @Override
    public List<GameDTO> findAllByRankingShowAndPlatform(String userId, Integer rankingShow, Integer platform, Pageable pageable) {

        List<GameDTO> gameDTOList = gameInfoRepository.findAllByGameRankingShow(rankingShow, pageable).stream()
                .filter(e -> e.getPlatform().equals(platform) || e.getPlatform().equals(2)).map(e -> new GameDTO(
                        e.getGameId(),
                        e.getGameName(),
                        aliyunOSSUtil.addDomainName(e.getGameIcon()),
                        e.getGameDescription(),
                        aliyunOSSUtil.addDomainName(e.getGamePicture()),
                        //获取收藏信息
                        favoritesService.findByUserIdAndFObjectId(userId, e.getGameId()),
                        e.getGameRankingId(),
                        e.getGameRankingShow().equals(1),
                        e.getCreateTime(),
                        gameTagReferenceService.findGameTagByGameId(e.getGameRankingId(), e.getGameId()),
                        e.getPlatform()
                )).collect(Collectors.toList());
        return gameDTOList;
    }

    @Override
    public Page<GameInfo> fuzzySearchByGameName(Pageable pageable, String gameName) {
        return gameInfoRepository.fuzzySearchByUsername(pageable, gameName);
    }

    /**
     * 3D 根据游戏分类 获取游戏列表
     *
     * @param categoryType
     * @param pageable
     * @return
     */
    @Override
    public List<GameInfo> TDFindList(Integer categoryType, Pageable pageable) {
        return gameInfoRepository.findByGameType(categoryType, pageable);
    }
}
