package com.yh.saas.plugin.news.service.impl;

import com.alipay.sofa.runtime.api.annotation.SofaReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.winsea.svc.base.base.constant.SystemConstant;
import com.winsea.svc.base.base.entity.CommonAppendix;
import com.winsea.svc.base.base.entity.CommonCompany;
import com.winsea.svc.base.base.entity.CommonStaff;
import com.winsea.svc.base.base.entity.CommonTenant;
import com.winsea.svc.base.base.service.IAppendixService;
import com.winsea.svc.base.base.service.ICommonCompanyService;
import com.winsea.svc.base.base.service.ICommonStaffService;
import com.winsea.svc.base.base.service.ICommonTenantService;
import com.winsea.svc.base.base.view.CommonTreeView;
import com.yh.saas.plugin.news.entity.AnnoIssueInfo;
import com.yh.saas.plugin.news.entity.AnnoReadUserInfo;
import com.yh.saas.plugin.news.entity.AnnoReadUserLike;
import com.yh.saas.plugin.news.entity.CommonAnnouncementIssueInfo;
import com.yh.saas.plugin.news.enums.DefaultNewsEnums;
import com.yh.saas.plugin.news.mapper.NewsAnnoIssueInfoMapper;
import com.yh.saas.plugin.news.mapper.NewsAnnouncementIssueInfoMapper;
import com.yh.saas.plugin.news.service.IAnnoIssueInfoService;
import com.yh.saas.plugin.news.service.INewsAnnoReadUserInfoService;
import com.yh.saas.plugin.news.service.INewsAnnoReadUserLikeService;
import com.yh.saas.plugin.news.service.INewsAnnouncementInfoService;
import com.yh.saas.common.support.util.IdGenerator;
import com.yh.saas.common.support.util.query.QueryUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 租户服务实现
 *
 * @author SunTianjun
 */
@Service
public class NewsAnnouncementInfoServiceImpl extends ServiceImpl<NewsAnnouncementIssueInfoMapper, CommonAnnouncementIssueInfo> implements INewsAnnouncementInfoService {

    @Autowired
    private IAnnoIssueInfoService issueInfoService;

    @Autowired
    private INewsAnnoReadUserInfoService readUserInfoService;

    @Autowired
    private NewsAnnoIssueInfoMapper annoIssueInfoMapper;

    @SofaReference
    private ICommonTenantService commonTenantService;

    @SofaReference
    private ICommonCompanyService companyService;

    @SofaReference
    private ICommonStaffService staffService;

    @Autowired
    private INewsAnnoReadUserLikeService readUserLikeService;

    @SofaReference
    private IAppendixService appendixService;

    private static ExecutorService executor = Executors.newFixedThreadPool(5);

    // 字段转换匹配
    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    /**
     * 查询系统新闻一览信息
     *
     * @param issueInfo 查询条件
     * @return
     */
    @Override
    public Page<CommonAnnouncementIssueInfo> queryCommonPage(CommonAnnouncementIssueInfo issueInfo) {
        Wrapper<CommonAnnouncementIssueInfo> wrapper = QueryUtils.convertExampleToWrapper(issueInfo);
        if (StringUtils.isNotBlank(issueInfo.getSearchKeyword())) {
            wrapper.andNew("title like {0}", "%" + issueInfo.getSearchKeyword() + "%");
        }
        if (StringUtils.isNotBlank(issueInfo.getDefaultNews())) {
            wrapper.eq(CommonAnnouncementIssueInfo.QueryFields.DEFAULT_NEWS, issueInfo.getDefaultNews());
        }
        String orderColunm = issueInfo.getOrderColunm();
        String order = issueInfo.getOrder();
        if (StringUtils.isNotBlank(orderColunm) && StringUtils.isNotBlank(order)) {
            issueInfo.setOrderColunm("");
            wrapper.orderBy(humpToLine(orderColunm), Boolean.parseBoolean(order));
            wrapper.orderBy(CommonAnnouncementIssueInfo.QueryFields.ISSUE_DATE, false);
        } else {
            wrapper.orderBy(CommonAnnouncementIssueInfo.QueryFields.IS_ISSUE, true);
            wrapper.orderBy(CommonAnnouncementIssueInfo.QueryFields.ISSUE_DATE, false);
        }
        Page<CommonAnnouncementIssueInfo> page = this.selectPage(issueInfo.getQueryPage(), wrapper);
        page.getRecords().stream().forEach(info -> {
                    String defaultNews = info.getDefaultNews();
                    if (DefaultNewsEnums.DEFAULT_NEWS_TYPE_0.getCode().equalsIgnoreCase(defaultNews) || StringUtils.isBlank(defaultNews)) {
                        info.setDefaultNewsName(DefaultNewsEnums.DEFAULT_NEWS_TYPE_0.getValue());
                    } else if (DefaultNewsEnums.DEFAULT_NEWS_TYPE_1.getCode().equalsIgnoreCase(defaultNews)) {
                        info.setDefaultNewsName(DefaultNewsEnums.DEFAULT_NEWS_TYPE_1.getValue());
                    }
                }
        );
        return page;
    }

    /**
     * 查询 系统新闻详情
     *
     * @param commonIssueInfo 查询条件
     * @return
     */
    @Override
    public CommonAnnouncementIssueInfo queryCommonDetail(CommonAnnouncementIssueInfo commonIssueInfo) {
        return this.selectById(commonIssueInfo.getId());
    }

    /**
     * 查询所有租户的已发布的新闻
     *
     * @param annoIssueInfo 查询条件
     * @return
     */
    @Override
    public Page<AnnoIssueInfo> queryTenantPage(AnnoIssueInfo annoIssueInfo) {
        annoIssueInfo.setReleaseFlag("2");
        annoIssueInfo.setSystemFlag("1");
        Page<AnnoIssueInfo> issueInfoPage = annoIssueInfo.getQueryPage();
        List<AnnoIssueInfo> announcementVos = annoIssueInfoMapper.queryPage(annoIssueInfo, issueInfoPage);
        return issueInfoPage.setRecords(announcementVos);
    }

    /**
     * 查询 租户的已发布的新闻详细
     *
     * @param annoIssueInfo 查询条件
     * @return
     */
    @Override
    public AnnoIssueInfo queryTenantDetail(AnnoIssueInfo annoIssueInfo) {
        return issueInfoService.selectById(annoIssueInfo.getId());
    }


    /**
     * 获取接收范围信息
     */
    @Override
    public List<CommonTreeView> getSendScopeList() {
        List<CommonTenant> tenantList = commonTenantService.selectList(new EntityWrapper<CommonTenant>()
                .orderBy(CommonTenant.QueryFields.TENANT_NAME, true));

        List<CommonTreeView> treeViewList = new ArrayList<>();
        List<CommonTreeView> childViewList = new ArrayList<>();
        CommonTreeView parentView = new CommonTreeView();
        parentView.setId(SystemConstant.SYSTEM_COMP_ID);
        parentView.setName("全部");
        parentView.setParentId("-1");
        tenantList.forEach(tenant -> {
            CommonTreeView childView = new CommonTreeView();
            childView.setId(tenant.getTenantId());
            childView.setName(tenant.getTenantName());
            childView.setParentId(SystemConstant.SYSTEM_COMP_ID);
            childViewList.add(childView);
        });
        parentView.setChildren(childViewList);
        treeViewList.add(parentView);
        return treeViewList;
    }

    /**
     * 创建新闻信息
     *
     * @param commonIssueInfo
     * @return
     */
    @Override
    @Transactional
    public String createCommonIssueInfo(CommonAnnouncementIssueInfo commonIssueInfo) {
        commonIssueInfo.setId(IdGenerator.generateUUID());
        commonIssueInfo.setIssueDate(new Date());
        getDefaultNews(commonIssueInfo.getDefaultNews());// 清除之前相同的默认新闻
        if (!StringUtils.isEmpty(commonIssueInfo.getIsIssue()) && "1".equals(commonIssueInfo.getIsIssue())) {
            release(commonIssueInfo);
        }
        this.insert(commonIssueInfo);
        return commonIssueInfo.getId();
    }

    /**
     * 更新新闻信息
     *
     * @param commonIssueInfo
     * @return
     */
    @Override
    @Transactional
    public String updateCommonIssueInfo(CommonAnnouncementIssueInfo commonIssueInfo) {
        commonIssueInfo.setIssueDate(new Date());
        getDefaultNews(commonIssueInfo.getDefaultNews());// 清除之前相同的默认新闻
        if (!StringUtils.isEmpty(commonIssueInfo.getIsIssue()) && "1".equals(commonIssueInfo.getIsIssue())) {
            release(commonIssueInfo);
        }
        this.updateById(commonIssueInfo);
        return commonIssueInfo.getId();
    }

    /**
     * 删除
     *
     * @param commonIssueInfo
     */
    @Override
    @Transactional
    public void remove(CommonAnnouncementIssueInfo commonIssueInfo) {
        this.deleteById(commonIssueInfo.getId());
        List<String> infoId = new ArrayList<>();
        List<String> detailId = new ArrayList<>();
        List<AnnoIssueInfo> issueInfoList = issueInfoService.selectList(new EntityWrapper<AnnoIssueInfo>()
                .eq(AnnoIssueInfo.QueryFiles.PARENT_ID, commonIssueInfo.getId()));
        if (CollectionUtils.isNotEmpty(issueInfoList)) {
            infoId = issueInfoList.stream().map(AnnoIssueInfo::getId).collect(Collectors.toList());
            List<AnnoReadUserInfo> readUserInfoList = readUserInfoService.selectList(new EntityWrapper<AnnoReadUserInfo>()
                    .in(AnnoReadUserInfo.QueryFiles.ANNOUNCEMENT_ID, infoId));
            if (CollectionUtils.isNotEmpty(readUserInfoList)) {
                detailId = readUserInfoList.stream().map(AnnoReadUserInfo::getId).collect(Collectors.toList());
            }
        }
        if (CollectionUtils.isNotEmpty(infoId)) {
            issueInfoService.deleteBatchIds(infoId);
        }
        if (CollectionUtils.isNotEmpty(detailId)) {
            readUserInfoService.deleteBatchIds(detailId);
        }
    }

    /**
     * 发布
     */
    private void release(CommonAnnouncementIssueInfo commonIssueInfo) {

        // 如果当前新闻有封面需要给所有被发送的公司复制一份
        CommonAppendix appendix = appendixService.selectById(commonIssueInfo.getOssCoverUrl());

        // 取出所有要发送的租户
        List<String> tenantIdList = Arrays.asList(commonIssueInfo.getTenantId().split(",", -1));
        List<CommonCompany> companyList;
        List<AnnoIssueInfo> issueInfoList = new ArrayList<>();
        List<AnnoReadUserInfo> readUserInfoList = new ArrayList<>();
        if (CollectionUtils.isEmpty(tenantIdList)) {
            return;
        }
        for (String tenantId : tenantIdList) {
            if (StringUtils.isBlank(tenantId)) {
                continue;
            }
            // 查出当前租户所有公司
            companyList = companyService.selectList(new EntityWrapper<CommonCompany>()
                    .eq(CommonCompany.QueryFields.TENANT_ID, tenantId));
            if (CollectionUtils.isEmpty(companyList)) {
                continue;
            }
            companyList.forEach(company -> {

                AnnoIssueInfo issueInfo = createIssueInfo(commonIssueInfo, company, tenantId);

                // 给每个公司插一份附件信息
                if (appendix != null) {
                    appendix.setCompId(company.getCompId());
                    appendix.setAppendixId(IdGenerator.generateUUID());
                    appendixService.insert(appendix);
                    issueInfo.setOssCoverUrl(appendix.getAppendixId());
                }

                List<AnnoReadUserInfo> tempList = createReadUserInfo(issueInfo, company, commonIssueInfo);
                if (CollectionUtils.isNotEmpty(tempList)) {
                    issueInfoList.add(issueInfo);
                    readUserInfoList.addAll(tempList);
                }
            });
        }
        if (CollectionUtils.isNotEmpty(issueInfoList)) {
            issueInfoService.insertBatch(issueInfoList);
        }
        if (CollectionUtils.isNotEmpty(readUserInfoList)) {
            readUserInfoService.insertBatch(readUserInfoList);
        }
    }

    private AnnoIssueInfo createIssueInfo(CommonAnnouncementIssueInfo commonIssueInfo, CommonCompany company, String tenantId) {
        AnnoIssueInfo issueInfo = new AnnoIssueInfo();
        BeanUtils.copyProperties(commonIssueInfo, issueInfo);
        issueInfo.setCompId(company.getCompId());
        issueInfo.setId(IdGenerator.generateUUID());
        issueInfo.setSystemFlag("1");
        issueInfo.setParentId(commonIssueInfo.getId());
        issueInfo.setTenantId(tenantId);
        issueInfo.setTenantName(company.getCompName());
        return issueInfo;
    }

    private List<AnnoReadUserInfo> createReadUserInfo(
            AnnoIssueInfo issueInfo,
            CommonCompany companyInfo,
            CommonAnnouncementIssueInfo commonIssueInfo
    ) {
        List<AnnoReadUserInfo> readUserInfoList = new ArrayList<>();
        List<String> staffIdList;

        // 按喜好发送， 查询选中当前新闻类型的职员id
        if (commonIssueInfo.getLikeFlag()) {
            staffIdList = readUserLikeService.selectList(new EntityWrapper<AnnoReadUserLike>().eq(AnnoReadUserLike.QueryFiles.TYPE_ID, commonIssueInfo.getTypeId())
                    .eq(AnnoReadUserLike.QueryFiles.COMP_ID, companyInfo.getCompId())).stream().map(AnnoReadUserLike::getStaffId).collect(Collectors.toList());
        } else {
            staffIdList = staffService.findCompStaffs(companyInfo.getCompId()).stream().map(CommonStaff::getStaffId).collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(staffIdList)) {
            staffIdList.forEach(id -> {
                AnnoReadUserInfo annoReadUserInfo = new AnnoReadUserInfo();
                annoReadUserInfo.setAnnouncementId(issueInfo.getId());
                annoReadUserInfo.setCompId(issueInfo.getCompId());
                annoReadUserInfo.setReadUserId(id);
                annoReadUserInfo.setId(IdGenerator.generateUUID());
                annoReadUserInfo.setIsRead("0");
                readUserInfoList.add(annoReadUserInfo);
                //开启线程池进行发送
                executor.execute(() -> issueInfoService.jpush(issueInfo, annoReadUserInfo));
            });
        }
        return readUserInfoList;
    }

    /**
     * 去除之前已存在的默认新闻
     *
     * @param flag
     */
    private void getDefaultNews(String flag) {
        if (DefaultNewsEnums.DEFAULT_NEWS_TYPE_0.getCode().equalsIgnoreCase(flag)) {
            return;
        }
        // 查出首页显示的默认新闻(使用插入新用户默认首页显示新闻的查询方式)
        Wrapper<CommonAnnouncementIssueInfo> wrapper = new EntityWrapper<>();
        wrapper.ne(CommonAnnouncementIssueInfo.QueryFields.DEFAULT_NEWS, DefaultNewsEnums.DEFAULT_NEWS_TYPE_0.getCode());
        wrapper.isNotNull(CommonAnnouncementIssueInfo.QueryFields.DEFAULT_NEWS);
        wrapper.orderBy(CommonAnnouncementIssueInfo.QueryFields.ISSUE_DATE, false);
        List<CommonAnnouncementIssueInfo> commonInfoList = this.selectList(wrapper);
        for (int i = 0; i < commonInfoList.size(); i++) {
            CommonAnnouncementIssueInfo issueInfo = commonInfoList.get(i);
            //首页只显示两条数据，多余的改为老用户状态
            if (i < 1) {
                issueInfo.setDefaultNews(DefaultNewsEnums.DEFAULT_NEWS_TYPE_1.getCode());
            } else {
                issueInfo.setDefaultNews(DefaultNewsEnums.DEFAULT_NEWS_TYPE_0.getCode());
            }
            this.updateById(issueInfo);
        }
    }

    /**
     * 驼峰转下划线,效率比上面高
     */
    public static String humpToLine(String str) {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

}
