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

import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.jutil.jdk.web.db.PageList;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import cn.reghao.jutil.jdk.io.TextFile;
import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
import cn.reghao.tnb.content.api.constant.PostScope;
import cn.reghao.tnb.content.api.dto.VideoCard;
import cn.reghao.tnb.content.app.ContentApplication;
import cn.reghao.tnb.content.app.vod.db.mapper.*;
import cn.reghao.tnb.content.app.vod.model.po.*;
import cn.reghao.tnb.content.app.util.redis.ds.RedisHash;
import cn.reghao.tnb.content.app.util.redis.ds.RedisSet;
import cn.reghao.tnb.content.app.util.redis.ds.RedisSortedSet;
import cn.reghao.tnb.content.app.vod.model.vo.BannerVideoVO;
import cn.reghao.tnb.content.app.vod.service.rcmd.RedisKeys;
import cn.reghao.tnb.content.app.vod.service.rcmd.UserInterestBased;
import cn.reghao.tnb.search.api.dto.VideoSummary;
import cn.reghao.tnb.search.api.iface.DataSearchService;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2023-04-24 03:32:04
 */
@Slf4j
@ActiveProfiles("dev")
@SpringBootTest(classes = ContentApplication.class)
public class VideoPostTest {
    @Autowired
    VideoPostMapper videoPostMapper;
    @Autowired
    VideoStatisticMapper videoStatisticMapper;
    @Autowired
    PostCategoryMapper postCategoryMapper;
    @Autowired
    VideoPostService videoPostService;

    @Autowired
    RedisSortedSet sortedSet;
    @Autowired
    RedisHash<VideoCard> redisHash;
    @Autowired
    VideoPostQuery videoPostQuery;
    @Autowired
    private VideoFileMapper videoFileMapper;

    @Test
    public void getPageByTag() {
        int pageSize = 100;
        int nextId = 0;
        // List<VideoPost> videoPosts = videoPostMapper.findAllById(pageSize, nextId);

        String bannerKey = "tnb:content:video:banner";
        List<VideoStatistic> list = videoStatisticMapper.findAll();
        for (VideoStatistic videoStatistic : list) {
            String videoId = videoStatistic.getVideoId();
            int hotIndex = getHotIndex(videoStatistic);
            sortedSet.add(bannerKey, videoId, hotIndex);
        }
    }

    private int getHotIndex(VideoStatistic videoStatistic) {
        String videoId = videoStatistic.getVideoId();
        VideoPost videoPost = videoPostMapper.findByVideoId(videoId);
        LocalDateTime publishAt = videoPost.getPublishAt();
        long publishBy = videoPost.getPublishBy();

        double coin = videoStatistic.getCoin().doubleValue();
        double favorite = videoStatistic.getFavorite().doubleValue();
        double danmaku = videoStatistic.getDanmaku().doubleValue();
        double comment = videoStatistic.getComment().doubleValue();
        double view = videoStatistic.getView().doubleValue();
        double thumbUp = videoStatistic.getThumbUp().doubleValue();
        double share = videoStatistic.getShare().doubleValue();

        double weight = coin*0.4 + favorite*0.3 + danmaku*0.4 + comment*0.4 + view*0.25 + thumbUp*0.4 + share*0.6;
        if (publishAt.plusDays(1).isAfter(LocalDateTime.now())) {
            weight = weight*1.5;
        }

        int weight1 = (int) Math.floor(weight);
        return weight1;
    }

    @Autowired
    VideoTagMapper videoTagMapper;
    @Autowired
    UserInterestBased userInterestBased;
    @Test
    public void addTags() {
        /*List<GroupCount> list = videoPostTagMapper.findByGroupBy();
        List<String> list0 = list.stream().map(groupCount -> {
            String tagId = groupCount.getId();
            VideoTag videoTag = videoTagMapper.findByTagId(tagId);
            if (videoTag == null) {
                return tagId;
            }

            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        list0.forEach(tagId -> {
            videoTagMapper.deleteByTagId(tagId);
            videoPostTagMapper.deleteByTagId(tagId);
            log.info("delete tag id -> {}", tagId);
        });*/

        /*Map<String, List<String>> map = new HashMap<>();
        List<VideoTag> list = videoTagMapper.findAll();
        for (VideoTag videoTag : list) {
            String tagId = videoTag.getTagId();
            List<String> videoIds = videoPostTagMapper.findByTagId(tagId);
            if (videoIds.size() > 3) {
                userInterestBased.addCategoryItems1(tagId, videoIds);
                log.info("add {} items with tag id {}", videoIds.size(), tagId);
            }
        }*/
    }

    @Autowired
    RedisSet redisSet;
    @Test
    public void setRcmd() {
        long userId = 10002L;
        String itemsKey = RedisKeys.getUserItemKey(userId);
        Set<String> videoIds = userInterestBased.getUserInterestItems(userId);
        if (!videoIds.isEmpty()) {
            List<VideoCard> videoCards = videoPostQuery.getVideoCards(new ArrayList<>(videoIds));
            VideoCard[] arr = videoCards.toArray(new VideoCard[0]);
            redisSet.sadd(itemsKey, arr);
        }
    }

    @Test
    public void getRcmd() {
        long userId = 10002L;
        String itemsKey = RedisKeys.getUserItemKey(userId);
        List<VideoCard> videoCards = new ArrayList<>();
        List<Object> list = redisSet.spop(itemsKey, 12);
        for (Object obj : list) {
            if (obj instanceof VideoCard) {
                videoCards.add((VideoCard) obj);
            }
        }

        System.out.println();
    }

    @Autowired
    BannerVideoMapper bannerVideoMapper;
    @Test
    public void getBannerVideo() {
        List<VideoPost> list = videoPostMapper.findAll();
        long createAt = System.currentTimeMillis();
        List<BannerVideo> bannerVideoList = list.stream().map(videoPost -> {
            return new BannerVideo(videoPost, createAt);
        }).collect(Collectors.toList());

        if (!bannerVideoList.isEmpty()) {
            bannerVideoMapper.saveAll(bannerVideoList.subList(0, 100));
        }

        List<BannerVideoVO> list1 =  bannerVideoMapper.findBannerVideos();
        System.out.println();
    }

    @Autowired
    VideoCategoryPostMapper videoCategoryPostMapper;
    @Test
    public void videoCategoryPostTest() {
        List<VideoCategoryPost> videoCategoryPostList = new ArrayList<>();
        int categoryPid = 11;
        List<VideoPost> list = videoPostMapper.findGroupByUserAndCategory(categoryPid);
        for (VideoPost videoPost : list) {
            long publishBy = videoPost.getPublishBy();
            int categoryId = videoPost.getCategoryId();
            VideoPost videoPost1 = videoPostMapper.findUserAndCategory(publishBy, categoryId);
            videoCategoryPostList.add(new VideoCategoryPost(videoPost1));
        }

        if (!videoCategoryPostList.isEmpty()) {
            videoCategoryPostMapper.deleteByCategoryPid(categoryPid);
            videoCategoryPostMapper.saveAll(videoCategoryPostList);
        }
    }

    @Test
    public void videoPostTagTest() {
        Map<String, List<VideoPost>> map = new ConcurrentHashMap<>();
        Set<String> tagList = new HashSet<>();
        List<VideoPost> videoPostList = videoPostMapper.findAll();

        for (VideoPost videoPost : videoPostList) {
            String title = videoPost.getTitle();
            /*List<VideoPost> list = map.computeIfAbsent(title, v -> new ArrayList<>());
            if (!list.isEmpty()) {
                VideoPost videoPost1 = list.get(0);
                if (videoPost1.getDuration() == videoPost.getDuration() &&
                        videoPost1.getHorizontal() == videoPost.getHorizontal()) {
                    list.add(videoPost);
                }
            } else {
                list.add(videoPost);
            }*/
        }

        /*List<String> urls = new ArrayList<>();
        map.forEach((k, v) -> {
            if (v.size() <= 1) {
                map.remove(k);
            } else {
                StringBuilder sb = new StringBuilder();
                boolean contain = false;
                for (VideoPost  videoPost : v) {
                    long publishBy = videoPost.getPublishBy();
                    if (publishBy == 11002) {
                        contain = true;
                        break;
                    }
                }
            }
        });

        for (int i = 0; i < urls.size(); i++) {
            System.out.printf("%s -> %s\n", i, urls.get(i));
        }*/

        System.out.println();
    }

    @Test
    public void videoTest() throws IOException, InterruptedException {
        List<String> list = new ArrayList<>();
        File dir = new File("/home/reghao/Downloads/tele/1");
        for (File file : dir.listFiles()) {
            parseJson(file, list);
        }

        Set<String> set = new HashSet<>(list);
        Queue<String> queue = new ArrayDeque<>(set);
        ExecutorService threadPool = ThreadPoolWrapper.threadPool("search-pool", 20);
        ThreadPoolExecutor tpe = (ThreadPoolExecutor) threadPool;
        while (!Thread.interrupted()) {
            try {
                if (tpe.getActiveCount() < 20) {
                    String line = queue.poll();
                    if (line != null) {
                        String title = "";
                        if (line.endsWith(".mp4")) {
                            title = line.replace(".mp4", "");
                        } else if (line.endsWith(".MP4")) {
                            title = line.replace(".MP4", "");
                        } else if (line.endsWith(".mov")) {
                            title = line.replace(".mov", "");
                        } else if (line.endsWith(".MOV")) {
                            title = line.replace(".MOV", "");
                        } else if (line.endsWith(".m4v")) {
                            title = line.replace(".m4v", "");
                        } else {
                            title = StringUtils.trimAllWhitespace(line);
                        }

                        threadPool.submit(new SearchTask(title));
                    } else {
                        log.info("queue is empty");
                    }
                } else {
                    //log.info("当前线程队列有 {} 个线程, 其中 {} 个活跃线程, 休眠 1s 等待线程池空闲...", tpe.getQueue().size(), tpe.getActiveCount());
                    Thread.sleep(1_000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class SearchTask implements Runnable {
        private String title;

        public SearchTask(String title) {
            this.title = title;
        }

        public void run() {
            List<VideoPost> list1 = videoPostMapper.findByTitle(title);
            if (list1.isEmpty()) {
                log.info("notexist {}", title);
            } else {
                List<String> videoIds = list1.stream().map(VideoPost::getVideoId).collect(Collectors.toList());
                log.info("exist {} videoId {}", title, videoIds);
            }
        }
    }

    private void parseJson(File jsonFile, List<String> list) {
        JsonObject jsonObject = JsonConverter.jsonFileToObject(jsonFile, JsonObject.class);
        for (JsonElement jsonElement : jsonObject.get("messages").getAsJsonArray()) {
            try {
                JsonObject jsonObject1 = jsonElement.getAsJsonObject();
                String filename = jsonObject1.get("file_name").getAsString();
                if (filename.isBlank()) {
                    continue;
                }

                long dateUnixtime = jsonObject1.get("date_unixtime").getAsLong();
                DateTimeConverter.localDateTime(dateUnixtime*1000);
                list.add(filename);
            } catch (Exception e) {
                //e.printStackTrace();
            }
        }
    }

    @Test
    public void vodTest() {
        File dir = new File("/home/reghao/disk/2/vod/tg/");
        for (File file : dir.listFiles()) {
            if (file.isDirectory()) {
                continue;
            }

            String filename = file.getName();
            String title = "";
            if (filename.endsWith(".mp4")) {
                title = filename.replace(".mp4", "");
            } else if (filename.endsWith(".mov")) {
                title = filename.replace(".mov", "");
            } else if (filename.endsWith(".MP4")) {
                title = filename.replace(".MP4", "");
            }

            List<VideoPost> list1 = videoPostMapper.findByTitle(title);
            if (list1.isEmpty()) {
                //log.info("notexist {}", title);
            } else {
                List<String> videoIds = list1.stream().map(VideoPost::getVideoId).collect(Collectors.toList());
                log.info("exist {} videoId {}", title, videoIds);
            }
        }
    }

    private void test1() {
        String tagId = "77d4093c54aa4e568ea58788e5b1bfaa";
        int scope = PostScope.PROTECT.getCode();
        //videoPostTagMapper.saveAll(list1);

        TextFile textFile = new TextFile();
        StringBuilder sb = new StringBuilder();
        String filePath = "/home/reghao/Downloads/1_fyt91.txt";
        //filePath = "/home/reghao/Downloads/1_fytgc.txt";

        List<VideoTag> list = new ArrayList<>();
        for (String line : textFile.read(filePath)) {
            if (line.startsWith("exist")) {
                String videoIdsStr = line.split(" videoId ")[1];
                String[] videoIds = videoIdsStr.replace("[", "")
                        .replace("]", "")
                        .split(", ");

                for (String videoId : videoIds) {
                    /*VideoPost videoPost = videoPostMapper.findByVideoId(videoId);
                    long publishBy = videoPost.getPublishBy();*/
                    sb.append("'").append(videoId).append("',");
                    list.add(new VideoTag(videoId, scope, tagId));
                }
            }
        }

        videoTagMapper.saveAll(list);
        System.out.println(sb.toString());
    }

    @DubboReference(check = false, retries = 0, timeout = 60_000)
    DataSearchService dataSearchService;
    @Autowired
    SearchService searchService;
    @Test
    public void putSearchDataTest() {
        int pageSize = 1000;
        int nextId = 0;
        List<VideoPost> videoPosts = videoPostMapper.findAllById(pageSize, nextId);
        while (!videoPosts.isEmpty()) {
            List<VideoSummary> videoSummaryList = videoPosts.stream()
                    .map(this::getVideoSummary)
                    .collect(Collectors.toList());
            if (!videoSummaryList.isEmpty()) {
                dataSearchService.addVideoSummaryList(videoSummaryList);
            }

            nextId = videoPosts.get(videoPosts.size()-1).getId();
            videoPosts = videoPostMapper.findAllById(pageSize, nextId);
            log.info("start nextId {} with size {}", nextId, videoPosts.size());
        }
    }

    private VideoSummary getVideoSummary(VideoPost videoPost) {
        String videoId = videoPost.getVideoId();
        String title = videoPost.getTitle();
        int scope = videoPost.getScope();
        long publishTime = DateTimeConverter.msTimestamp(videoPost.getPublishAt());
        return new VideoSummary(videoId, title, scope, publishTime);
    }

    @Test
    public void searchVideoTest() {
        int pn = 1;
        String kw = "隔壁";
        List<Integer> scopes = List.of(PostScope.PUBLIC.getCode(), PostScope.PROTECT.getCode());
        PageList<VideoSummary> pageList = dataSearchService.searchVideo(kw, scopes, pn);
        Map<String, List<VideoSummary>> map = pageList.getList().stream()
                .collect(Collectors.groupingBy(VideoSummary::getVideoId));
        PageList<VideoCard> pageList1 = searchService.searchByKeyword(kw, "", pn);
        System.out.println();
    }

    @Test
    public void videoCategoryTest() {
        /*PostCategory postCategory1 = new PostCategory(0, "杂");
        PostCategory postCategory2 = new PostCategory(1, "bili");

        List<PostCategory> list = List.of(postCategory1, postCategory2);
        postCategoryMapper.saveAll(list);*/

        videoFileMapper.findAll().forEach(videoFile -> {
            String objectId = videoFile.getObjectId();
            String url = videoFile.getUrl();
            String url1 = url.replace("oss.reghao.cn", "oss2.reghao.cn");
            videoFileMapper.updateUrl(objectId, url1);
            log.info("update url {}", url1);
        });
    }
}
