package org.jeecg.modules.adweb.seo.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xkcoding.http.util.StringUtil;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;

import org.apache.poi.ss.usermodel.Sheet;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.adweb.seo.dto.AvesApiSearchKeywordsDTO;
import org.jeecg.modules.adweb.seo.entity.SeoKeywords;
import org.jeecg.modules.adweb.seo.service.ISeoKeywordsRankService;
import org.jeecg.modules.adweb.seo.service.ISeoKeywordsService;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Description: 关键词 @Author: jeecg-boot @Date: 2024-10-15 @Version: V1.0
 */
@Tag(name = "关键词")
@RestController
@RequestMapping("/seo/seoKeywords")
@Slf4j
public class SeoKeywordsController extends JeecgController<SeoKeywords, ISeoKeywordsService> {
    @Autowired private ISeoKeywordsService seoKeywordsService;

    @Autowired ISeoKeywordsRankService seoKeywordsRankService;

    @Autowired ISeoKeywordsRankService seoKpiStatisticsService;

    @Autowired private ISysBaseAPI sysBaseAPI;

    /**
     * 分页列表查询
     *
     * @param seoKeywords
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    // @AutoLog(value = "关键词-分页列表查询")
    @Operation(summary = "关键词-分页列表查询")
    @GetMapping(value = "/list")
    public Result<IPage<SeoKeywords>> queryPageList(
            SeoKeywords seoKeywords,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req) {
        if ((seoKeywords.getSiteCode() == null || seoKeywords.getSiteCode().isEmpty())) {
            return Result.OK();
        }
        QueryWrapper<SeoKeywords> queryWrapper = new QueryWrapper<>();
        if (StringUtil.isNotEmpty(seoKeywords.getKeywords())) {
            queryWrapper.like("keywords", "%" + seoKeywords.getKeywords() + "%");
        }
//        queryWrapper.eq("related_keyword_id", seoKeywords.getRelatedKeywordId());
//        queryWrapper.eq("subscription_id", seoKeywords.getSubscriptionId());
        queryWrapper.eq("site_code", seoKeywords.getSiteCode());
        if (seoKeywords.getKeywordType() != null) {
            queryWrapper.eq("keyword_type", seoKeywords.getKeywordType());
        }
        queryWrapper.ne("status", 0);
        queryWrapper.orderByAsc("priority").orderByDesc("optimize_process").orderByDesc("create_time");
        Page<SeoKeywords> page = new Page<SeoKeywords>(pageNo, pageSize);
        IPage<SeoKeywords> pageList = seoKeywordsService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param seoKeywords
     * @return
     */
    @AutoLog(value = "关键词-添加")
    @Operation(summary = "关键词-添加")
    @PreAuthorize("@jps.requiresPermissions('serp:seo_keywords:add')")
    @PostMapping(value = "/add")
    public Result<String> add(@RequestBody SeoKeywords seoKeywords) {
        seoKeywordsService.save(seoKeywords);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param seoKeywords
     * @return
     */
    @AutoLog(value = "关键词-编辑")
    @Operation(summary = "关键词-编辑")
    @PreAuthorize("@jps.requiresPermissions('serp:seo_keywords:edit')")
    @RequestMapping(
            value = "/edit",
            method = {RequestMethod.PUT, RequestMethod.POST})
    public Result<String> edit(@RequestBody SeoKeywords seoKeywords) {
        seoKeywordsService.updateById(seoKeywords);
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "关键词-通过id删除")
    @Operation(summary = "关键词-通过id删除")
    @PreAuthorize("@jps.requiresPermissions('serp:seo_keywords:delete')")
    @DeleteMapping(value = "/delete")
    public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
        seoKeywordsService.removeById(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "关键词-批量删除")
    @Operation(summary = "关键词-批量删除")
    @PreAuthorize("@jps.requiresPermissions('serp:seo_keywords:deleteBatch')")
    @DeleteMapping(value = "/deleteBatch")
    public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.seoKeywordsService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功!");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    // @AutoLog(value = "关键词-通过id查询")
    @Operation(summary = "关键词-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<SeoKeywords> queryById(@RequestParam(name = "id", required = true) String id) {
        SeoKeywords seoKeywords = seoKeywordsService.getById(id);
        if (seoKeywords == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(seoKeywords);
    }

    /**
     * 导出excel
     *
     * @param request
     */
    @PreAuthorize("@jps.requiresPermissions('serp:seo_keywords:exportXls')")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request) throws Exception {
        // Step.1 组装查询条件
        //		QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(sysUser,
        // request.getParameterMap());
        // Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        // update-begin--Author:kangxiaolin  Date:20180825
        // for：[03]用户导出，如果选择数据则只导出相关数据--------------------
        //		String selections = request.getParameter("selections");
        //		if(!oConvertUtils.isEmpty(selections)){
        //			queryWrapper.in("id",selections.split(","));
        //		}
        // update-end--Author:kangxiaolin  Date:20180825
        // for：[03]用户导出，如果选择数据则只导出相关数据----------------------
        //		List<SysUser> pageList = sysUserService.list(queryWrapper);
        AvesApiSearchKeywordsDTO avesApiSearchKeywordsDTO = new AvesApiSearchKeywordsDTO();
        Result<?> res = this.queryRankInfoList(avesApiSearchKeywordsDTO, 1, 5000, request);
        if (res == null || res.getResult() == null) {
            return null;
        }
        IPage<SeoKeywords> pageList = (IPage<SeoKeywords>) res.getResult();
        if (pageList.getRecords().isEmpty()) {
            return null;
        }
        ArrayList<String> columns = null;
        // 表头信息
        if (sysBaseAPI.isAdmin()) {
            columns = new ArrayList<>(Arrays.asList("序号", "关键词", "url", "关键词类型"));
        } else {
            columns = new ArrayList<>(Arrays.asList("序号", "关键词", "关键词类型"));
        }

        // 将关键词信息改为可以导出的格式
        List<Map<String, Object>> list = new ArrayList<>();
        List<SeoKeywords> enquiryList = pageList.getRecords();

        List<String> dates = pageList.getRecords().get(0).getDateList();
        columns.addAll(dates);

        boolean isAdmin = sysBaseAPI.isAdmin();

        for (int i = 0; i < enquiryList.size(); i++) {
            SeoKeywords seoKeywords = enquiryList.get(i);
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("序号", i + 1);
            map.put("关键词", seoKeywords.getKeywords());
            if (isAdmin) {
                map.put("url", seoKeywords.getPositionUrl());
            }
            if (seoKeywords.getKeywordType() == 1) {
                map.put("关键词类型", "指定词");
            } else if (seoKeywords.getKeywordType() == 2) {
                map.put("关键词类型", "长尾词");
            }
            // 遍历日期
            for (String date : dates) {
                map.put(
                        date,
                        Integer.valueOf(
                                seoKeywords.getRankInfo().get(date) == null
                                        ? "0"
                                        : seoKeywords.getRankInfo().get(date)));
            }
            list.add(map);
        }
        // 导出文件名称
        mv.addObject(NormalExcelConstants.FILE_NAME, "关键词排行");
        mv.addObject(NormalExcelConstants.CLASS, SysUser.class);
        LoginUser user = SecureUtil.currentUser();
        ExportParams exportParams =
                new ExportParams("关键词排行数据", "导出人:" + user.getRealname(), "导出信息");
        mv.addObject(NormalExcelConstants.PARAMS, exportParams);
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /** 关键词排名页面 - 列表数据 */
    @AutoLog(value = "营销推广-SEO-关键词排名统计查询接口")
    @RequestMapping(value = "/keywordList")
    public Result<?> queryRankInfoList(
            AvesApiSearchKeywordsDTO avesApiSearchKeywordsDTO,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req)
            throws Exception {
        if (sysBaseAPI.isNotOwnSite(avesApiSearchKeywordsDTO.getSiteCode())) {
            return Result.OK(new Page<>());
        }
        // 参数判断
        IPage<SeoKeywords> pageList = new Page<>();
        String siteCode = req.getParameter("siteCode");
        if (StringUtil.isEmpty(siteCode)) {
            siteCode = avesApiSearchKeywordsDTO.getSiteCode();
        }
        if (StringUtil.isEmpty(siteCode)) {
            log.info("缺少siteCode参数");
            return Result.OK(pageList);
        }
        String subscriptionId = avesApiSearchKeywordsDTO.getSubscriptionId();
        Integer keywordType = avesApiSearchKeywordsDTO.getKeywordType();
        // 查询关键词
        String column = req.getParameter("column");
        String order = req.getParameter("order");
        String buttonColumn = req.getParameter("buttonColmn");
        String buttonSort = req.getParameter("buttonSort");
        Page<SeoKeywords> page = new Page<SeoKeywords>(pageNo, pageSize);
        List<String> dateList =
                seoKeywordsService.getKeywordsLastSevenDays(siteCode, keywordType, subscriptionId);
        pageList =
                seoKeywordsService.getKeywordList(
                        page,
                        avesApiSearchKeywordsDTO.getRankStart(),
                        avesApiSearchKeywordsDTO.getRankEnd(),
                        avesApiSearchKeywordsDTO.getKeywords(),
                        siteCode,
                        keywordType,
                        avesApiSearchKeywordsDTO.getReachStandard() != null
                                && avesApiSearchKeywordsDTO.getReachStandard() == 1,
                        subscriptionId,
                        column,
                        order,
                        buttonColumn,
                        buttonSort,
                        dateList);

        // 给关键词对象增加排名信息
        if (pageList == null) {
            return Result.error("未获取到关键词数据");
        }
        seoKeywordsRankService.addRankInfoByIntervalTimeByType(
                pageList.getRecords(),
                avesApiSearchKeywordsDTO.getKeywordType(),
                siteCode,
                subscriptionId,
                dateList);
        log.info(pageList.toString());
        return Result.OK(pageList);
    }

    /**
     * Excel导出 关键词排名的导出
     *
     * @param avesApiSearchKeywordsDTO 查询参数
     * @return 询盘列表
     */
    @RequestMapping(value = "/exportExcel")
    public void exportExcel(
            AvesApiSearchKeywordsDTO avesApiSearchKeywordsDTO,
            HttpServletRequest req,
            HttpServletResponse response)
            throws Exception {
        Result<?> res = this.queryRankInfoList(avesApiSearchKeywordsDTO, 1, 5000, req);
        if (res == null || res.getResult() == null) {
            return;
        }
        IPage<SeoKeywords> pageList = (IPage<SeoKeywords>) res.getResult();
        if (pageList.getRecords().isEmpty()) {
            return;
        }
        ArrayList<String> columns = null;
        // 表头信息
        if (sysBaseAPI.isAdmin()) {
            columns = new ArrayList<>(Arrays.asList("序号", "关键词", "url", "关键词类型"));
        } else {
            columns = new ArrayList<>(Arrays.asList("序号", "关键词", "关键词类型"));
        }

        // 将关键词信息改为可以导出的格式
        List<Map<String, Object>> list = new ArrayList<>();
        List<SeoKeywords> enquiryList = pageList.getRecords();

        List<String> dates = pageList.getRecords().get(0).getDateList();
        columns.addAll(dates);

        boolean isAdmin = sysBaseAPI.isAdmin();

        for (int i = 0; i < enquiryList.size(); i++) {
            SeoKeywords seoKeywords = enquiryList.get(i);
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("序号", i + 1);
            map.put("关键词", seoKeywords.getKeywords());
            if (isAdmin) {
                map.put("url", seoKeywords.getPositionUrl());
            }
            if (seoKeywords.getKeywordType() == 1) {
                map.put("关键词类型", "指定词");
            } else if (seoKeywords.getKeywordType() == 2) {
                map.put("关键词类型", "长尾词");
            }
            // 遍历日期
            for (String date : dates) {
                map.put(
                        date,
                        Integer.valueOf(
                                seoKeywords.getRankInfo().get(date) == null
                                        ? "0"
                                        : seoKeywords.getRankInfo().get(date)));
            }
            list.add(map);
        }
        StringBuilder fileName = new StringBuilder();
        fileName.append("关键词排名导出");

        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        // test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
        ServletOutputStream out = null;
        ExcelWriter writer = ExcelUtil.getWriter(true);
        try {
            Sheet sheet = writer.getSheet();
            sheet.setDefaultColumnWidth(12);
            sheet.setDefaultRowHeightInPoints(20);
            // 设置请求头属性
            response.setHeader(
                    "Content-Disposition",
                    "attachment;filename="
                            + new String(
                                    (fileName + ".xlsx").getBytes(), StandardCharsets.ISO_8859_1));
            out = response.getOutputStream();
            log.info("导出数据：" + list);
            writer.write(list, true);
            seoKeywordsRankService.setSizeColumn(sheet, list.get(0).size());
            // 写出到文件
            writer.flush(out, true);
            // 关闭writer，释放内存
            writer.close();
            // 此处记得关闭输出Servlet流
            IoUtil.close(out);
        } catch (IOException e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * @param seoKeywords
     * @return
     */
    @GetMapping(value = "/getSeoKeyword")
    public Result<?> getSeoKeyword(SeoKeywords seoKeywords) {
        QueryWrapper<SeoKeywords> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("keywords", seoKeywords.getKeywords());
        queryWrapper.eq("site_code", seoKeywords.getSiteCode());
        queryWrapper.ne("status", 0);
        queryWrapper.eq("subscription_id", seoKeywords.getSubscriptionId());
        List<SeoKeywords> seoKeywordsList = seoKeywordsService.list(queryWrapper);
        if (!seoKeywordsList.isEmpty()) {
            return Result.OK(false);
        }
        return Result.OK(true);
    }
}
