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

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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

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

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

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
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.base.controller.JeecgController;
import org.jeecg.modules.adweb.common.util.AdaptiveWidthUtils;
import org.jeecg.modules.adweb.enquiry.entity.AdwebPublicEnquiryRule;
import org.jeecg.modules.adweb.enquiry.service.IAdwebPublicEnquiryRuleService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 用于询盘规则过滤
 * @Author: jeecg-boot
 * @Date: 2023-02-01
 * @Version: V1.0
 */
@Tag(name = "用于询盘规则过滤")
@RestController
@RequestMapping("/adweb/adwebEnquiryRule")
@Slf4j
public class AdwebPublicEnquriyRuleController
        extends JeecgController<AdwebPublicEnquiryRule, IAdwebPublicEnquiryRuleService> {
    @Resource private IAdwebPublicEnquiryRuleService adwebEnquiryRuleService;

    /**
     * 分页列表查询
     *
     * @param adwebEnquiryRule
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "用于询盘规则过滤-分页列表查询")
    @Operation(summary = "用于询盘规则过滤-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(
            AdwebPublicEnquiryRule adwebEnquiryRule,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req) {
        Page<AdwebPublicEnquiryRule> page = new Page<AdwebPublicEnquiryRule>(pageNo, pageSize);
        String column = req.getParameter("column");
        String order = req.getParameter("order");
        IPage<AdwebPublicEnquiryRule> pageList = getPageList(page, adwebEnquiryRule, column, order);
        return Result.OK(pageList);
    }

    public IPage<AdwebPublicEnquiryRule> getPageList(
            Page<AdwebPublicEnquiryRule> page,
            AdwebPublicEnquiryRule adwebEnquiryRule,
            String column,
            String order) {
        IPage<AdwebPublicEnquiryRule> pageList =
                adwebEnquiryRuleService.pageList(
                        page,
                        adwebEnquiryRule.getWord(),
                        adwebEnquiryRule.getBlackOrWhiteList(),
                        adwebEnquiryRule.getIsEnable(),
                        adwebEnquiryRule.getUseStatus(),
                        column,
                        order);
        return pageList;
    }

    /**
     * 添加
     *
     * @param adwebEnquiryRule
     * @return
     */
    @AutoLog(value = "用于询盘规则过滤-添加")
    @Operation(summary = "用于询盘规则过滤-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody AdwebPublicEnquiryRule adwebEnquiryRule) {
        if (StringUtils.isBlank(adwebEnquiryRule.getWord())) {
            return Result.error("规则关键词不能为空");
        }

        adwebEnquiryRule.setWord(
                adwebEnquiryRule.getWord().replaceAll(" {2,}", " ").trim().toLowerCase());

        int count =
                (int)
                        adwebEnquiryRuleService.count(
                                new LambdaQueryWrapper<AdwebPublicEnquiryRule>()
                                        .eq(
                                                AdwebPublicEnquiryRule::getWord,
                                                adwebEnquiryRule.getWord())
                                        .ne(AdwebPublicEnquiryRule::getStatus, 0)
                                        .eq(
                                                AdwebPublicEnquiryRule::getUseStatus,
                                                adwebEnquiryRule.getUseStatus()));
        if (count > 0) {
            return Result.error("规则关键词已存在");
        }

        adwebEnquiryRule.setStatus(1);
        adwebEnquiryRuleService.save(adwebEnquiryRule);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param adwebEnquiryRule
     * @return
     */
    @AutoLog(value = "用于询盘规则过滤-编辑")
    @Operation(summary = "用于询盘规则过滤-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody AdwebPublicEnquiryRule adwebEnquiryRule) {
        if (StringUtils.isBlank(adwebEnquiryRule.getWord())) {
            return Result.error("规则关键词不能为空");
        }

        adwebEnquiryRule.setWord(
                adwebEnquiryRule.getWord().replaceAll(" {2,}", " ").trim().toLowerCase());

        int count =
                (int)
                        adwebEnquiryRuleService.count(
                                new LambdaQueryWrapper<AdwebPublicEnquiryRule>()
                                        .eq(
                                                AdwebPublicEnquiryRule::getWord,
                                                adwebEnquiryRule.getWord())
                                        .ne(AdwebPublicEnquiryRule::getStatus, 0)
                                        .ne(AdwebPublicEnquiryRule::getId, adwebEnquiryRule.getId())
                                        .eq(
                                                AdwebPublicEnquiryRule::getUseStatus,
                                                adwebEnquiryRule.getUseStatus()));

        if (count > 0) {
            return Result.error("规则关键词已存在");
        }

        adwebEnquiryRuleService.updateById(adwebEnquiryRule);
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "用于询盘规则过滤-通过id删除")
    @Operation(summary = "用于询盘规则过滤-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {

        if (id == null) {
            return Result.error("参数不识别！");
        }
        boolean update =
                adwebEnquiryRuleService.update(
                        new LambdaUpdateWrapper<AdwebPublicEnquiryRule>()
                                .set(AdwebPublicEnquiryRule::getStatus, 0)
                                .eq(AdwebPublicEnquiryRule::getId, id));

        return update ? Result.OK("删除成功!") : Result.error("删除失败!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "用于询盘规则过滤-批量删除")
    @Operation(summary = "用于询盘规则过滤-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        if (ids == null) {
            return Result.error("参数不识别！");
        }
        List<String> idList = Arrays.asList(ids.split(","));
        boolean update =
                adwebEnquiryRuleService.update(
                        new LambdaUpdateWrapper<AdwebPublicEnquiryRule>()
                                .set(AdwebPublicEnquiryRule::getStatus, 0)
                                .in(AdwebPublicEnquiryRule::getId, idList));
        return update ? Result.OK("批量删除成功!") : Result.error("批量删除失败!");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "用于询盘规则过滤-通过id查询")
    @Operation(summary = "用于询盘规则过滤-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        if (StringUtils.isNotBlank(id)) {
            return Result.error("参数不识别！");
        }

        AdwebPublicEnquiryRule adwebEnquiryRule = adwebEnquiryRuleService.getById(id);
        if (adwebEnquiryRule == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(adwebEnquiryRule);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param adwebEnquiryRule
     */
    @RequestMapping(value = "/exportXls")
    public void exportXls(
            HttpServletRequest request,
            AdwebPublicEnquiryRule adwebEnquiryRule,
            HttpServletResponse response) {
        Page<AdwebPublicEnquiryRule> page = new Page<AdwebPublicEnquiryRule>(1, -1);
        String column = request.getParameter("column");
        String order = request.getParameter("order");
        List<AdwebPublicEnquiryRule> list =
                getPageList(page, adwebEnquiryRule, column, order).getRecords();
        //		QueryWrapper<AdwebPublicEnquiryRule> queryWrapper =
        // QueryGenerator.initQueryWrapper(adwebEnquiryRule, request.getParameterMap());
        //		queryWrapper.ne("status", 0);
        //		List<AdwebPublicEnquiryRule> list = adwebEnquiryRuleService.list(queryWrapper);
        // 通过工具类创建writer，默认创建xls格式
        ExcelWriter writer = ExcelUtil.getWriter(true);

        writer.addHeaderAlias("word", "关键词");
        writer.addHeaderAlias("translateWord", "关键词翻译");
        writer.addHeaderAlias("blackOrWhiteList", "黑白名单");
        writer.addHeaderAlias("isEnable", "是否启用");
        writer.addHeaderAlias("useStatus", "作用域");
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);

        StringBuilder fileName = new StringBuilder();
        fileName.append("用于询盘规则过滤");

        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        // test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
        ServletOutputStream out = null;
        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();
            writer.write(list, true);
            AdaptiveWidthUtils.setSizeColumn(sheet, 3);
            // 写出到文件
            writer.flush(out, true);
            // 关闭writer，释放内存
            writer.close();
            // 此处记得关闭输出Servlet流
            IoUtil.close(out);
        } catch (IOException e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 通过excel导入数据
     *
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(@RequestParam("file") MultipartFile file) {
        try {
            // 字节输入流
            InputStream inputStream = file.getInputStream();
            // 通过输入流创建ExcelReader 对象
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            // 这个同上导入
            reader.addHeaderAlias("关键词", "word");
            reader.addHeaderAlias("关键词翻译", "translateWord");
            reader.addHeaderAlias("黑白名单", "blackOrWhiteList");
            reader.addHeaderAlias("是否启用", "isEnable");
            reader.addHeaderAlias("作用域", "useStatus");

            List<AdwebPublicEnquiryRule> rulesList = reader.readAll(AdwebPublicEnquiryRule.class);

            if (rulesList.isEmpty()) {
                return Result.error("导入数据异常！");
            }

            for (AdwebPublicEnquiryRule adwebEnquiryRule : rulesList) {
                LambdaUpdateWrapper<AdwebPublicEnquiryRule> updateWrapper =
                        new LambdaUpdateWrapper();
                updateWrapper.eq(AdwebPublicEnquiryRule::getWord, adwebEnquiryRule.getWord());
                updateWrapper.ne(AdwebPublicEnquiryRule::getStatus, 0);
                updateWrapper.eq(AdwebPublicEnquiryRule::getUseStatus, 0);
                updateWrapper.set(
                        AdwebPublicEnquiryRule::getTranslateWord,
                        adwebEnquiryRule.getTranslateWord());
                adwebEnquiryRuleService.update(updateWrapper);
            }

            List<String> wordList =
                    rulesList.stream()
                            .map(AdwebPublicEnquiryRule::getWord)
                            .collect(Collectors.toList());
            List<AdwebPublicEnquiryRule> adwebEnquiryRules =
                    adwebEnquiryRuleService.list(
                            new LambdaQueryWrapper<AdwebPublicEnquiryRule>()
                                    .in(AdwebPublicEnquiryRule::getWord, wordList)
                                    .ne(AdwebPublicEnquiryRule::getStatus, 0)
                                    .select(AdwebPublicEnquiryRule::getWord)
                                    .eq(AdwebPublicEnquiryRule::getUseStatus, 0));
            List<String> adwebEnquiryRuleList =
                    adwebEnquiryRules.stream()
                            .map(AdwebPublicEnquiryRule::getWord)
                            .collect(Collectors.toList());

            List<AdwebPublicEnquiryRule> collect =
                    rulesList.stream()
                            .filter(
                                    adwebEnquiryRule ->
                                            !adwebEnquiryRuleList.contains(
                                                    adwebEnquiryRule.getWord()))
                            .collect(Collectors.toList());

            collect.forEach(adwebEnquiryRule -> adwebEnquiryRule.setStatus(1));

            if (CollectionUtils.isNotEmpty(collect)) {
                adwebEnquiryRuleService.saveBatch(collect);
            }
            return Result.OK(
                    "文件导入成功！数据行数："
                            + rulesList.size()
                            + ",重复数据行数："
                            + adwebEnquiryRules.size()
                            + ",导入数据行数："
                            + collect.size());
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error("文件导入失败！失败信息：" + e.getMessage());
        }
    }
}
