package com.usky.website.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.website.domain.SiteArticle;
import com.usky.website.domain.SiteCategory;
import com.usky.website.mapper.SiteArticleMapper;
import com.usky.website.mapper.SiteCategoryMapper;
import com.usky.website.service.SiteArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 官网_内容管理 服务实现类
 * </p>
 *
 * @author ya
 * @since 2022-08-31
 */
@Service
public class SiteArticleServiceImpl extends AbstractCrudService<SiteArticleMapper, SiteArticle> implements SiteArticleService {

    @Autowired
    private SiteCategoryMapper siteCategoryMapper;

    @Override
    public CommonPage<SiteArticle> siteArticleList(Integer categoryid, Integer id, Integer articleid, String title, String order, Integer pageNum, Integer pageSize) {
        IPage<SiteArticle> page = new Page<>(pageNum, pageSize);
        List<Integer> categoryidList = new ArrayList<>();
        if (categoryid != null && categoryid != 0) {
            if (categoryid == 18) {
                LambdaQueryWrapper<SiteCategory> queryWrapper1 = Wrappers.lambdaQuery();
                queryWrapper1.select(SiteCategory::getId)
                        .eq(SiteCategory::getPid, categoryid)
                        .eq(SiteCategory::getStatus, 1);
                List<SiteCategory> list = siteCategoryMapper.selectList(queryWrapper1);
                for (int i = 0; i < list.size(); i++) {
                    categoryidList.add(list.get(i).getId());
                }
            } else {
                LambdaQueryWrapper<SiteCategory> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(SiteCategory::getStatus,1);
                List<SiteCategory> siteCategoryList = siteCategoryMapper.selectList(queryWrapper);

                List<Integer> childIds = new ArrayList<>();
                List<Integer> finalCategoryidList = siteCategoryList.stream().filter(site -> site.getPid().equals(categoryid))
                        .map(vo -> {
                            List<Integer> ids = getChildrenData(vo,siteCategoryList);
                            if(ids.size() > 0){
                                ids.stream().forEach(s -> childIds.add(s));
                            }
                            return vo.getId();
                        }).collect(Collectors.toList());
                finalCategoryidList.add(categoryid);
                if(childIds.size() > 0){
                    childIds.stream().forEach(e -> finalCategoryidList.add(e));
                }
                for (int i = 0; i < finalCategoryidList.size(); i++) {
                    categoryidList.add(finalCategoryidList.get(i));
                }
            }
        }

        if(articleid != null){
            this.updateArticleHits(articleid);
        }

        LambdaQueryWrapper<SiteCategory> queryWrapper1 = Wrappers.lambdaQuery();
        queryWrapper1.eq(SiteCategory::getStatus, 1)
                .in(CollectionUtil.isNotEmpty(categoryidList), SiteCategory::getId, categoryidList);
        List<SiteCategory> list = siteCategoryMapper.selectList(queryWrapper1);

        LambdaQueryWrapper<SiteArticle> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(CollectionUtil.isNotEmpty(categoryidList), SiteArticle::getCategoryid, categoryidList)
                .eq(id != null, SiteArticle::getId, id)
                .like(StringUtils.isNotBlank(title), SiteArticle::getTitle, title);
        if(StringUtils.isNotBlank(order) && order.equals("sortindex")){
            queryWrapper.orderByDesc(SiteArticle::getIstop).orderByAsc(SiteArticle::getSortindex, SiteArticle::getId);
        }else{
            queryWrapper.orderByDesc(SiteArticle::getIstop,SiteArticle::getCreatedate);
        }

        page = this.page(page, queryWrapper);

        for (int i = 0; i < page.getRecords().size(); i++) {
            for (int j = 0; j < list.size(); j++) {
                if (page.getRecords().get(i).getCategoryid().equals(list.get(j).getId())) {
                    page.getRecords().get(i).setCategoryName(list.get(j).getCategoryName());
                }
            }
        }
        return new CommonPage<>(page.getRecords(), page.getTotal(), pageSize, pageNum);
    }

    @Override
    public void addSiteArticle(SiteArticle siteArticle) {
        siteArticle.setCreatedate(new Date());
        this.save(siteArticle);
    }

    @Override
    public void updateSiteArticle(SiteArticle siteArticle) {
        siteArticle.setModifydate(new Date());
        this.updateById(siteArticle);
    }

    @Override
    public void delSiteArticle(Integer id) {
        this.removeById(id);
    }

    //异步多线程调用
    //更新官网_内容管理表中点击量字段值（每调用一次某个内容，就+1次对应表id的点击量字段值）
    @Async("asyncServiceExecutor")
    public void updateArticleHits(Integer articleid){
        UpdateWrapper<SiteArticle> updateWrapper = Wrappers.update();
        updateWrapper.setSql("hits = hits + 1")
                .eq("id",articleid);

        this.update(updateWrapper);

    }

    public List<Integer> getChildrenData(SiteCategory root,List<SiteCategory> all){
        List<Integer> childIds = new ArrayList<>();
        List<Integer> ids = all.stream().filter(list -> list.getPid().equals(root.getId()))
                .map(list -> {
                    List<Integer> childs = getChildrenData(list,all);
                    if(childs.size() > 0){
                        childs.stream().forEach(s ->childIds.add(s));
                    }
                    return list.getId();
                })
                .collect(Collectors.toList());
        if(childIds.size() > 0){
            childIds.stream().forEach(e -> ids.add(e));
        }

        return ids;
    }
}
