package org.jeecg.modules.adweb.seo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xkcoding.http.util.StringUtil;

import jakarta.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.adweb.common.constant.AdwebConstant;
import org.jeecg.modules.adweb.seo.dto.ComprehensiveStatistics;
import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
import org.jeecg.modules.adweb.seo.entity.SeoKeywordsSerp;
import org.jeecg.modules.adweb.seo.entity.SeoPlanSubscription;
import org.jeecg.modules.adweb.seo.mapper.SeoKeywordsMapper;
import org.jeecg.modules.adweb.seo.service.ISeoKeywordsRankService;
import org.jeecg.modules.adweb.seo.service.ISeoKeywordsSerpService;
import org.jeecg.modules.adweb.seo.service.ISeoKeywordsService;
import org.jeecg.modules.adweb.seo.service.ISeoPlanSubscriptionService;
import org.jeecg.modules.adweb.seo.vo.RankInfoVO;
import org.jeecg.modules.adweb.seo.vo.SeoRankInfoVO;
import org.jeecg.modules.adweb.site.entity.AdwebSite;
import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
import org.jeecg.modules.adweb.site.service.ISiteUserPermissionService;
import org.jeecg.modules.adweb.subscribePlan.entity.SubscribePlan;
import org.jeecg.modules.adweb.subscribePlan.mapper.SubscribePlanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @Description: seo_kpi_statistics @Author: jeecg-boot @Date: 2024-10-09 @Version: V1.0
 */
@Service
@Slf4j
public class SeoKeywordsRankServiceImpl implements ISeoKeywordsRankService {

    @Autowired private IAdwebSiteService adwebSiteService;

    @Autowired private ISysBaseAPI sysBaseAPI;

    @Autowired private ISiteUserPermissionService siteUserPermissionService;

    @Autowired private ISeoPlanSubscriptionService seoPlanSubscriptionService;

    @Autowired private ISeoKeywordsService seoKeywordsService;

    @Resource private SeoKeywordsMapper seoKeywordsMapper;

    @Autowired private ISeoKeywordsSerpService seoKeywordsSerpService;

    @Resource private SubscribePlanMapper subscribePlanMapper;

    @Override
    public List<AdwebSite> getAllSites() {
        log.info("获取当前用户管理的 父 站点信息");
        List<AdwebSite> siteList = null;
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        QueryWrapper<AdwebSite> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "name", "code");
        queryWrapper.eq("site_type", AdwebConstant.SITE).orderByDesc("create_time");
        queryWrapper.eq("status", AdwebConstant.STATUS).isNull("parent_group_code");
        if (sysBaseAPI.isOem()) {
            List<String> oemGroupUids = sysBaseAPI.getOemGroupUids();
            List<String> codeList = siteUserPermissionService.getSiteCodeListByUids(oemGroupUids);
            queryWrapper.in("code", codeList);
        } else if (!sysBaseAPI.isAdmin()) {
            List<String> codeList = siteUserPermissionService.getSiteCodeList(sysUser.getId());
            queryWrapper.in("code", codeList);
        }
        siteList = adwebSiteService.list(queryWrapper);
        this.setPlanName(siteList);
        return siteList;
    }

    /** 放入营销方案名称 */
    private void setPlanName(List<AdwebSite> siteList) {
        if (CollectionUtils.isEmpty(siteList)) {
            return;
        }

        List<Integer> siteIds = new ArrayList<>();
        for (AdwebSite site : siteList) {
            siteIds.add(site.getId());
        }

        QueryWrapper<SeoPlanSubscription> historyQueryWrapper = new QueryWrapper<>();
        historyQueryWrapper.select("id", "plan_id", "site_id", "plan_name", "plan_type");
        historyQueryWrapper.in("site_id", siteIds);
        historyQueryWrapper.eq("status", 1);
        List<SeoPlanSubscription> seoPlanSubscriptions = seoPlanSubscriptionService.list(historyQueryWrapper);
        if (CollectionUtils.isEmpty(seoPlanSubscriptions)) {
            return;
        }

        for (AdwebSite site : siteList) {
            for (SeoPlanSubscription seoPlanSubscription : seoPlanSubscriptions) {
                if (seoPlanSubscription.getSiteId().equals(site.getId() + "")) {
                    site.setPlanId(seoPlanSubscription.getPlanId());
                    site.setPlanName(seoPlanSubscription.getPlanName());
                    site.setSubscriptionId(seoPlanSubscription.getId());
                    site.setPlanType(seoPlanSubscription.getPlanType());
                }
            }
        }
    }

    /**
     * 获得综合统计的数据
     *
     * @param siteCode 站点code
     * @param planId 套餐表id
     * @return 综合统计的数据
     */
    @Override
    public ComprehensiveStatistics getComprehensiveInfo(String siteCode, String planId) {
        ComprehensiveStatistics comprehensiveStatistics = new ComprehensiveStatistics();
        SubscribePlan subscribePlan = subscribePlanMapper.selectById(planId);
        log.info("planId:{}, subscribePlan:{}", planId, subscribePlan.toString());
        if (subscribePlan != null) {
            // 添加套餐数据
            comprehensiveStatistics.setPlanAppointKeywordNum(subscribePlan.getSpecifyKeyword());
            comprehensiveStatistics.setPlanLongTailKeywordNum(subscribePlan.getLongTailKeyword());
            comprehensiveStatistics.setPlanOuterLinkNum(subscribePlan.getExternalLinks());
            comprehensiveStatistics.setPlanArticleNum(subscribePlan.getArticle());
        }
        // 添加站点数据
        // 1.获取站点指定词数量
        QueryWrapper<SeoKeywords> seoKeywordsQueryWrapper = new QueryWrapper<>();
        seoKeywordsQueryWrapper.eq("site_code", siteCode);
        seoKeywordsQueryWrapper.eq("status", 1);
        seoKeywordsQueryWrapper.eq("keyword_type", 1);
        Long appointKeywordNum = seoKeywordsMapper.selectCount(seoKeywordsQueryWrapper);
        // 2.获取站点关键词数量
        QueryWrapper<SeoKeywords> seoKeywordsQueryWrapper1 = new QueryWrapper<>();
        seoKeywordsQueryWrapper1.eq("site_code", siteCode);
        seoKeywordsQueryWrapper1.eq("status", 1);
        seoKeywordsQueryWrapper1.eq("keyword_type", 2);
        Long longTailKeywordNum = seoKeywordsMapper.selectCount(seoKeywordsQueryWrapper1);
        comprehensiveStatistics.setAppointKeywordNum(Math.toIntExact(appointKeywordNum));
        comprehensiveStatistics.setLongTailKeywordNum(Math.toIntExact(longTailKeywordNum));
        return comprehensiveStatistics;
    }

    @Override
    public Map getRankInfo(String siteCode, String subscriptionId) throws ParseException {
        List<SeoRankInfoVO> seoRankInfos = this.getSeoRankInfo(siteCode, subscriptionId);

        Map map = new HashMap<>();
        map.put("appointKeyword", seoRankInfos.get(0));
        map.put("longTailKeyword", seoRankInfos.get(1));
        return map;
    }

    /**
     * 获取一个站点的关键词排名数量
     *
     * @param siteCode 站点code
     * @return 关键词排名数量
     */
    @Override
    public List<SeoRankInfoVO> getSeoRankInfo(String siteCode, String subscriptionId)
            throws ParseException {
        // 排名信息
        SeoRankInfoVO appointRankInfo = new SeoRankInfoVO();
        SeoRankInfoVO longTailRankInfo = new SeoRankInfoVO();
        // 1-10
        Map<String, Integer> first = dealKeywordsRankData(siteCode, subscriptionId, 1, 10);
        if (first.containsKey("appoint")) {
            appointRankInfo.setFirstNum(first.get("appoint"));
        }
        if (first.containsKey("longTail")) {
            longTailRankInfo.setFirstNum(first.get("longTail"));
        }

        // 11-30
        Map<String, Integer> second = dealKeywordsRankData(siteCode, subscriptionId, 11, 30);
        if (second.containsKey("appoint")) {
            appointRankInfo.setSecondNum(second.get("appoint"));
        }
        if (second.containsKey("longTail")) {
            longTailRankInfo.setSecondNum(second.get("longTail"));
        }
        // 31-100
        Map<String, Integer> third = dealKeywordsRankData(siteCode, subscriptionId, 31, 100);
        if (third.containsKey("appoint")) {
            appointRankInfo.setThirdType(third.get("appoint"));
        }
        if (third.containsKey("longTail")) {
            longTailRankInfo.setThirdType(third.get("longTail"));
        }
        List<SeoRankInfoVO> list = new ArrayList<>();
        list.add(appointRankInfo);
        list.add(longTailRankInfo);
        return list;
    }

    private Map<String, Integer> dealKeywordsRankData(
            String siteCode, String subscriptionId, Integer rankStart, Integer rankEnd) {
        Map<String, Integer> KeywordsRankMap = new HashMap<>();

        // 指定词
        List<String> appointDateList =
                seoKeywordsService.getKeywordsLastSevenDays(siteCode, 1, subscriptionId);
        String appointDatesStr = "";
        if (CollectionUtils.isNotEmpty(appointDateList)) {
            for (int i = 0; i < appointDateList.size(); i++) {
                if (i == appointDateList.size() - 1) {
                    appointDatesStr += "'" + appointDateList.get(i) + "'";
                } else {
                    appointDatesStr += "'" + appointDateList.get(i) + "'" + ",";
                }
            }
            appointDatesStr = "(" + appointDatesStr + ")";

            // 指定词
            RankInfoVO appointRankInfo =
                    seoKeywordsMapper.queryKeywordNumByRankRange(
                            siteCode, subscriptionId, rankStart, rankEnd, appointDatesStr, "1");
            if (appointRankInfo != null) {
                KeywordsRankMap.put("appoint", appointRankInfo.getKeywordNum());
            }
        }

        // 长尾词
        List<String> dateList = seoKeywordsService.getKeywordsLastSevenDays(siteCode, 2, subscriptionId);
        String dateStr = "";
        if (CollectionUtils.isNotEmpty(dateList)) {
            for (int i = 0; i < dateList.size(); i++) {
                if (i == dateList.size() - 1) {
                    dateStr += "'" + dateList.get(i) + "'";
                } else {
                    dateStr += "'" + dateList.get(i) + "'" + ",";
                }
            }
            dateStr = "(" + dateStr + ")";
            RankInfoVO longRankInfo =
                    seoKeywordsMapper.queryKeywordNumByRankRange(
                            siteCode, subscriptionId, rankStart, rankEnd, dateStr, "2");
            if (longRankInfo != null) {
                KeywordsRankMap.put("longTail", longRankInfo.getKeywordNum());
            }
        }
        return KeywordsRankMap;
    }

    /**
     * 给列表中的关键字增加排名信息
     * 根据关键词类型
     * @param keywordList 关键词列表
     *
     */
    @Override
    public void addRankInfoByIntervalTimeByType(List<SeoKeywords> keywordList, Integer keywordType, String siteCode, String subscriptionId, List<String> dateList) throws Exception {
        if (CollectionUtils.isEmpty(keywordList)) {
            return;
        }

        String datesStr = "";
        if(CollectionUtils.isEmpty(dateList)){
            return;
        }else{
            for(int i = 0; i < dateList.size(); i++){
                if(i == dateList.size() - 1){
                    datesStr +=  "'" + dateList.get(i) + "'";
                }else{
                    datesStr +=  "'" + dateList.get(i) + "'" + ",";
                }
            }
            datesStr = "(" + datesStr + ")";
        }
        List<Integer> keywordIds = keywordList.stream().map(SeoKeywords::getId).collect(Collectors.toList());
        List<SeoKeywordsSerp> serpList = seoKeywordsSerpService.list(new LambdaQueryWrapper<SeoKeywordsSerp>()
                .in(SeoKeywordsSerp::getKeywordsId, keywordIds)
                .in(SeoKeywordsSerp::getSeDate, dateList));
        List<SeoKeywordsSerp> noRepeatSerpList = new ArrayList<>();
        Map<String, Integer> serpMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(serpList)){
            for (SeoKeywordsSerp seoKeywordsSerp : serpList) {
                seoKeywordsSerp.setKey(seoKeywordsSerp.getKeywordsId() + "_" + seoKeywordsSerp.getSeDate());
                if(CollectionUtils.isNotEmpty(noRepeatSerpList)){
                    List<SeoKeywordsSerp> have = noRepeatSerpList.stream().filter(o -> o.getKey().equals(seoKeywordsSerp.getKey())).collect(Collectors.toList());
                    if(CollectionUtils.isEmpty(have)){
                        serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
                        noRepeatSerpList.add(seoKeywordsSerp);
                    }else{
                        log.info("重复的数据：" + seoKeywordsSerp.getKey());
                    }
                }else {
                    serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
                    noRepeatSerpList.add(seoKeywordsSerp);
                }
            }
        }

        for (SeoKeywords keyword : keywordList) {
            Map<String, String> rankInfo = new LinkedHashMap<>();
            for (String date : dateList) {

                // 从Map中获取那天的排名信息
                Integer rankAbsolute = serpMap.get(keyword.getId() + "_" + date);

                if(rankAbsolute == null){
                    rankAbsolute = 0;
                }
                rankInfo.put(date, rankAbsolute + "");
            }

            keyword.setRankInfo(rankInfo);
            keyword.setIpAddress("223.112.18.226");

            keyword.setDateList(dateList);
            if(StringUtil.isEmpty(keyword.getSearchUrl())){
                keyword.setSearchUrl("https://www.google.com/");
            }
        }
    }

    /**
     * 自适应宽度(中文支持)
     * @param sheet
     * @param size 因为for循环从0开始，size值为 列数-1
     */
    @Override
    public void setSizeColumn(Sheet sheet, int size) {
        for (int columnNum = 0; columnNum <= size; columnNum++) {
            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
            for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
                Row currentRow;
                //当前行未被使用过
                if (sheet.getRow(rowNum) == null) {
                    currentRow = sheet.createRow(rowNum);
                } else {
                    currentRow = sheet.getRow(rowNum);
                }

                if (currentRow.getCell(columnNum) != null) {
                    Cell currentCell = currentRow.getCell(columnNum);
                    if (currentCell.getCellType() == CellType.STRING) {
                        int length = currentCell.getStringCellValue().getBytes().length;
                        if (columnWidth < length) {
                            columnWidth = length;
                        }
                    }
                }
            }
            sheet.setColumnWidth(columnNum, columnWidth * 256);
        }
    }
}
