package cn.reghao.tnb.content.app.vod.service.impl;

import cn.reghao.jutil.jdk.web.db.Page;
import cn.reghao.jutil.jdk.web.db.PageList;
import cn.reghao.tnb.content.api.dto.VideoRegion;
import cn.reghao.tnb.content.app.vod.db.mapper.PostCategoryMapper;
import cn.reghao.tnb.content.app.vod.db.mapper.VideoCategoryPostMapper;
import cn.reghao.tnb.content.app.vod.model.dto.CategoryAdd;
import cn.reghao.tnb.content.app.vod.model.po.PostCategory;
import cn.reghao.tnb.content.app.vod.model.po.VideoCategoryPost;
import cn.reghao.tnb.content.app.vod.model.po.VideoPost;
import cn.reghao.tnb.content.app.vod.model.query.CategoryQuery;
import cn.reghao.tnb.content.app.vod.model.query.VideoQuery;
import cn.reghao.tnb.content.app.vod.service.CategoryService;
import cn.reghao.tnb.content.app.util.redis.ds.RedisStringObject;
import org.springframework.stereotype.Service;

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

/**
 * @author reghao
 * @date 2024-08-06 21:08:56
 */
@Service
public class CategoryServiceImpl implements CategoryService {
    private final PostCategoryMapper postCategoryMapper;
    private final RedisStringObject redisStringObject;
    private final VideoCategoryPostMapper videoCategoryPostMapper;

    public CategoryServiceImpl(PostCategoryMapper postCategoryMapper, RedisStringObject redisStringObject,
                               VideoCategoryPostMapper videoCategoryPostMapper) {
        this.postCategoryMapper = postCategoryMapper;
        this.redisStringObject = redisStringObject;
        this.videoCategoryPostMapper = videoCategoryPostMapper;
    }

    @Override
    public List<VideoRegion> getCategories(boolean vip) {
        CategoryQuery categoryQuery = new CategoryQuery.Builder().build();
        List<PostCategory> list = getVideoCategories(categoryQuery);
        setVideoCategory(list);

        Map<Integer, VideoRegion> map = new HashMap<>(list.size());
        for (PostCategory category : list) {
            if (category.getVip() && !vip) {
                continue;
            }

            int pid = category.getPid();
            int id = category.getId();
            String name = category.getName();
            int regionId = 0;
            String icon = "";
            int sort = category.getSort();
            if (pid == 0) {
                map.put(id, new VideoRegion(pid, regionId, id, name, icon, sort));
            } else {
                map.get(pid).getChildren().add(new VideoRegion(pid, regionId, id, name, icon, sort));
            }
        }

        List<VideoRegion> parents = new ArrayList<>(map.values()).stream()
                .filter(videoRegion -> !videoRegion.getChildren().isEmpty())
                .sorted(Comparator.comparingInt(VideoRegion::getSort))
                .collect(Collectors.toList());
        /*parents.forEach(videoRegion -> {
            videoRegion.getChildren().sort(Comparator.comparingInt(VideoRegion::getSort));
        });*/
        return parents;
    }

    private List<PostCategory> getVideoCategories(CategoryQuery categoryQuery) {
        int pageNumber = 1;
        int pageSize = 1000;
        Page page = new Page(pageNumber, pageSize);
        List<PostCategory> list = postCategoryMapper.findVideoCategoryByPage(page, categoryQuery);
        if (list.isEmpty()) {
            initVideoCategory();
        }

        return postCategoryMapper.findVideoCategoryByPage(page, categoryQuery);
    }

    private void initVideoCategory() {
        PostCategory postCategory1 = new PostCategory(0, "大杂烩");
        postCategoryMapper.save(postCategory1);

        int pid = postCategory1.getId();
        PostCategory postCategory2 = new PostCategory(pid, "杂");
        postCategoryMapper.save(postCategory2);
    }

    private void setVideoCategory(List<PostCategory> list) {
        String keyPrefix = "tnb:content:video:category";
        list.forEach(videoCategory -> {
            int id = videoCategory.getId();
            String key = String.format("%s:%s", keyPrefix, id);
            redisStringObject.set(key, videoCategory);
        });
    }

    @Override
    public PostCategory getVideoCategory(int id) {
        String key = String.format("tnb:content:video:category:%s", id);
        Object value = redisStringObject.get(key);
        if (value instanceof PostCategory) {
            return (PostCategory) value;
        }

        return null;
    }

    @Override
    public void addVideoCategory(CategoryAdd categoryAdd) {
        PostCategory postCategory1 = new PostCategory(categoryAdd);
        List<PostCategory> list = List.of(postCategory1);
        postCategoryMapper.saveAll(list);
    }

    @Override
    public void setVideoCategoryPost(VideoPost videoPost) {
        int categoryId = videoPost.getCategoryId();
        long publishBy = videoPost.getPublishBy();
        VideoCategoryPost videoCategoryPost = videoCategoryPostMapper.findByCategoryIdAndUserId(categoryId, publishBy);
        if (videoCategoryPost == null) {
            videoCategoryPost = new VideoCategoryPost(videoPost);
            videoCategoryPostMapper.save(videoCategoryPost);
        } else {
            videoCategoryPost.setVideoId(videoPost.getVideoId());
            videoCategoryPost.setScope(videoPost.getScope());
            videoCategoryPost.setPublishAt(videoPost.getPublishAt());
            videoCategoryPostMapper.updateVideoCategoryPost(videoCategoryPost);
        }
    }

    @Override
    public PageList<String> getVideoIdsByCategory(VideoQuery videoQuery, int pageNumber, int pageSize) {
        int total = videoCategoryPostMapper.countByCriteria(videoQuery);
        if (total > pageSize*100) {
            total = pageSize*100;
            if (pageNumber > 100) {
                pageNumber = 100;
            }
        } else if (total == 0) {
            return PageList.empty();
        }

        Page page = new Page(pageNumber, pageSize);
        List<String> videoIds = videoCategoryPostMapper.findVideoCategoryPostByPage(page, videoQuery).stream()
                .map(VideoCategoryPost::getVideoId)
                .collect(Collectors.toList());
        return PageList.pageList(pageNumber, pageSize, total, videoIds);
    }
}
