package cn.reghao.tnb.search.app.blog.service;

import cn.reghao.tnb.search.app.blog.db.repository.ArticleRepository;
import cn.reghao.tnb.search.app.blog.db.repository.ArticleTagRepository;
import cn.reghao.tnb.search.app.blog.db.repository.CategoryRepository;
import cn.reghao.tnb.search.app.blog.model.ArticleType;
import cn.reghao.tnb.search.app.blog.model.CategoryType;
import cn.reghao.tnb.search.app.blog.model.po.Category;
import cn.reghao.tnb.search.app.blog.model.vo.CategoryCount;
import cn.reghao.tnb.search.app.blog.model.vo.GroupCount;
import cn.reghao.jutil.jdk.web.result.Result;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2023-04-10 17:54:39
 */
@Service
public class CategoryService {
    private final CategoryRepository categoryRepository;
    private final ArticleTagRepository articleTagRepository;
    private final ArticleRepository articleRepository;

    public CategoryService(CategoryRepository categoryRepository, ArticleTagRepository articleTagRepository,
                           ArticleRepository articleRepository) {
        this.categoryRepository = categoryRepository;
        this.articleTagRepository = articleTagRepository;
        this.articleRepository = articleRepository;
    }

    public Result add(String name) {
        Category category = categoryRepository.findByName(name);
        if (category != null) {
            return Result.fail(String.format("%s exist", name));
        }

        category = new Category(CategoryType.Category.getValue(), name);
        categoryRepository.save(category);
        return Result.success();
    }

    public Result deleteCategory(int id) {
        Category category = categoryRepository.findById(id).orElse(null);
        if (category == null) {
            return Result.fail("not exist");
        }

        int type = category.getType();
        if (type == CategoryType.Category.getValue()) {
            int postType = ArticleType.Article.getValue();
            int articleCount = articleRepository.countByCategoryIdAndPostType(id, postType);
            if (articleCount != 0) {
                return Result.fail("分类中包含有文章");
            }

            int postType1 = ArticleType.Question.getValue();
            int questionCount = articleRepository.countByCategoryIdAndPostType(id, postType1);
            if (questionCount != 0) {
                return Result.fail("Question 中含有此分类");
            }
        } else if (type == CategoryType.Tag.getValue()) {
            int total = articleTagRepository.countByTagId(id);
            if (total != 0) {
                return Result.fail("标签中包含有文章");
            }
        }

        categoryRepository.delete(category);
        return Result.success();
    }

    public List<Category> findAllCategory() {
        return categoryRepository.findAllByType(CategoryType.Category.getValue());
    }

    /**
     * 根据分类/标签包含的 article 数量降序返回, 只有后台管理时才显示 article 数量为 0 的分类/标签
     *
     * @param
     * @return
     * @date 2025-09-17 09:35:37
     */
    public List<CategoryCount> findCategoryCountByPage(int type, boolean admin) {
        List<GroupCount> groupCountList;
        if (type == CategoryType.Category.getValue()) {
            groupCountList = categoryRepository.findCategoryGroup();
        } else if (type == CategoryType.Tag.getValue()) {
            groupCountList = categoryRepository.findTagGroup();
        } else {
            return Collections.emptyList();
        }

        List<CategoryCount> list = groupCountList.stream()
                .map(CategoryCount::new)
                .collect(Collectors.toList());
        if (admin) {
            List<Category> categoryList = categoryRepository.findAllByType(type);
            if (categoryList.size() > list.size()) {
                Set<Integer> idSet = list.stream().map(CategoryCount::getId).collect(Collectors.toSet());
                for (Category category : categoryList) {
                    if (!idSet.contains(category.getId())) {
                        list.add(new CategoryCount(category));
                    }
                }
            }
        }

        list = list.stream()
                .sorted((o1, o2) -> o2.getTotal()- o1.getTotal())
                .collect(Collectors.toList());
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setIndex(i+1);
        }
        return list;
    }
}
