package com.zzsn.knowbase.controller;

import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zzsn.knowbase.constant.Constants;
import com.zzsn.knowbase.entity.*;
import com.zzsn.knowbase.service.IEnclosureService;
import com.zzsn.knowbase.service.IKnowledgeService;
import com.zzsn.knowbase.service.ILocalFileService;
import com.zzsn.knowbase.util.*;
import com.zzsn.knowbase.vo.IntelligentQaParam;
import com.zzsn.knowbase.vo.KnowledgeParam;
import com.zzsn.knowbase.vo.KnowledgeVO;
import com.zzsn.knowbase.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 *  知识
 * @Author: chenshiqiang
 * @Version: V1.0
 */
@Api(tags = "知识")
@RestController
@RequestMapping("/api/knowledge")
@Slf4j
public class KnowledgeController {
    @Autowired
    private IKnowledgeService knowledgeService;

    @Value("${python.intelligentQaUrl:}")
    private String intelligentQaUrl;

    @Autowired
    private ILocalFileService localFileService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IEnclosureService enclosureService;

    /**
     * 分页列表查询
     */
    @GetMapping(value = "/list")
    public Result<?> queryPageList(KnowledgeParam knowledgeParam,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   @RequestParam(name = "column", defaultValue = "common") String column,
                                   @RequestParam(name = "order", defaultValue = "desc") String order) {
        if (null != knowledgeParam.getSearchInfo() && Integer.valueOf("2").equals(knowledgeParam.getSearchScope())) {
            IPage<KnowledgeVO> pageList = knowledgeService.listFromPython(knowledgeParam, pageNo, pageSize, column, order);
            return Result.OK(pageList);
        }
        if(Constants.SC_CATEGORY.equals(knowledgeParam.getTypeIds()) && "0".equals(knowledgeParam.getKnowledgeProjectId())){
            knowledgeParam.setKnowledgeProjectId(null);
        }
        IPage<KnowledgeVO> pageList = knowledgeService.queryPageList(knowledgeParam, pageNo, pageSize, column, order);
        return Result.OK(pageList);
    }

    /**
     * 详情
     */
    @GetMapping(value = "/getById")
    public Result<?> getById(@RequestParam String id) {
        log.info("{}===query begin", new Date());
        KnowledgeVO knowledgeVO = knowledgeService.getById(id);
        if(knowledgeVO==null){
            return  Result.OK("nothing");
        }
        if (null != knowledgeVO.getPublishDate() && (!knowledgeVO.getPublishDate().isEmpty())) {
            knowledgeVO.setPublishDate(EsDateUtil.esFieldDateMapping(knowledgeVO.getPublishDate()));
        }
        if (null != knowledgeVO.getVerifyTime() && (!knowledgeVO.getVerifyTime().isEmpty())) {
            knowledgeVO.setVerifyTime(EsDateUtil.esFieldDateMapping(knowledgeVO.getVerifyTime()));
        }
        return Result.OK(knowledgeVO);
    }
    /**
     * 根据附件id查询详情
     */
    @GetMapping(value = "/getEnclosureById")
    public Result<?> getEnclosureById(@RequestParam String id) {
        Enclosure byId = enclosureService.getById(id);
        if(byId==null){
            return Result.OK("文件不存在！");
        }
        byId.setUrlDomain(MinioUtil.getDomainUrl());
        return Result.OK(byId);
    }
    /**
     * 附件上传
     */
    @PostMapping(value = "/uploadFile")
    public Result<?> uploadFile(HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        Result<List<KnowFile>> result = localFileService.upload(fileMap);
        return Result.OK(result);
    }


    @GetMapping(value = "/listFromPython")
    public Result<?> listFromPython(KnowledgeParam knowledgeParam,
                                    @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                    @RequestParam(name = "column", defaultValue = "common") String column,
                                    @RequestParam(name = "order", defaultValue = "desc") String order) {
        IPage<KnowledgeVO> pageList = knowledgeService.listFromPython(knowledgeParam, pageNo, pageSize, column, order);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param knowledge
     * @return
     */
    @ApiOperation(value = "知识-添加", notes = "知识-添加")
    @PostMapping(value = "/uploadKnowledge")
    public Result<?> uploadKnowledge(HttpServletRequest request, Knowledge knowledge) {
        MultipartHttpServletRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);

        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        Result<List<KnowFile>> result = localFileService.upload(fileMap);
        log.info("upload result:{}", result);
        if (!Integer.valueOf("200").equals(result.getCode())) {
            return Result.error(result.getMessage());
        }
        List<KnowFile> resultList = result.getResult();
        KbAuthorizedUser userInfo = SpringContextUtils.getUserInfo();
        knowledge.setImportData(0);
        CompletableFuture.runAsync(() -> this.add(resultList, knowledge, userInfo));
        return Result.OK("添加成功！");
    }

    private void add(List<KnowFile> resultList, Knowledge knowledge, KbAuthorizedUser userInfo) {

        if (null == resultList || resultList.isEmpty()) {
            return;
        }
        for (KnowFile knowFileResult : resultList) {
            knowledge.setId(null);
            knowledge.setTitle(null);
            knowledgeService.addKnowledge(knowFileResult, knowledge, userInfo);
        }
    }

    /**
     * 编辑
     *
     * @param knowledge
     * @return
     */
    @ApiOperation(value = "信息源组类别-编辑", notes = "信息源组类别-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody Knowledge knowledge) {
        knowledgeService.updateKnowledge(knowledge);
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param
     * @return
     */
    @PostMapping(value = "/delete")
    public Result<?> delete(@RequestBody DeleteParam deleteParam) {
        knowledgeService.deleteKnowledge(deleteParam.getKnowledgeList());
        return Result.OK("删除成功!");
    }

    @GetMapping(value = "/parse")
    public Result<?> parse(@RequestParam(name = "filePath") String filePath) throws IOException {
        String s = DocUtil.docParseHtml(filePath);
        return Result.OK(s);
    }

    /**
     * 智能问答
     *
     * @param intelligentQaParam
     * @return
     */
    @PostMapping(value = "/IntelligentQa")
    public Result<?> intelligentQa(@RequestBody IntelligentQaParam intelligentQaParam) throws IOException {
        JSONObject params = new JSONObject();
        params.put("score_threshold", intelligentQaParam.getScoreThreshold());
        params.put("question", intelligentQaParam.getQuestion());
        params.put("knowledge_base_id", intelligentQaParam.getKbKnowledgeIds().split(","));
        params.put("size", intelligentQaParam.getSize());
        String result = HttpUtil.doPost(intelligentQaUrl, params, 120000);
        if (!result.isEmpty()) {
            JSONObject jsonObject = JSON.parseObject(result);
            return Result.OK(jsonObject.get("result"));
        }
        return Result.error("响应失败");
    }

    /**
     * 通过excel导入
     *
     * @return
     */
    @RequestMapping(value = "/importInfo", method = RequestMethod.POST)
    public Result<?> importInfo(HttpServletRequest request, HttpServletResponse response) {
        KbAuthorizedUser userInfo = SpringContextUtils.getUserInfo();
        assert userInfo != null;
        return knowledgeService.doImportInfo(request, userInfo.getId());

    }

    /**
     * 下载导入模板
     */
    @RequestMapping(value = "/download")
    public Result<?> download(HttpServletRequest request, HttpServletResponse response) {
        try {
            List<KnowledgeExcel> dataList = new ArrayList<>();
            String filePath = Constants.TEMP_FILES_DIR + "template.xlsx";
            ExcelExportUtil.writeExcelFront(dataList, "知识库列表导入模板", filePath, KnowledgeExcel.class);
            ExcelExportUtil.download(response, filePath, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.OK();
    }

    /**
     * 预导出
     *
     * @param newsIds 资讯知识ids
     * @param fileIds 文件知识ids
     */
    @PostMapping(value = "/export")
    public Result<?> exportCollectionXls(HttpServletRequest request,
                                         String newsIds, String fileIds) {
        log.info("newsIds:{},fileIds:{}",newsIds,fileIds);
        if(!newsIds.isEmpty()){
            knowledgeService.exportExcel(newsIds);
        }
        if(!fileIds.isEmpty()){
            knowledgeService.exportPackage(fileIds);
        }

        return Result.OK(true);
    }

    /**
     * 导出
     *
     * @param newsIds 资讯知识ids
     * @param fileIds 文件知识ids
     */

    @RequestMapping(value = "/downloadFile")
    public void downloadXls(HttpServletResponse response, String newsIds, String fileIds) {
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        //获取下载路径
        Object newsObject = redisUtil.get(newsIds);
        Object fileObject = redisUtil.get(fileIds);
        String fileName = UUID.randomUUID().toString().replace("-", "");
        String newsFilePath = null;
        String fileFilePath = null;
        if (newsObject != null) {
            newsFilePath = newsObject.toString();
        }
        if (fileObject != null) {
            fileFilePath = fileObject.toString();
        }
        try {
            if ((!newsIds.isEmpty())&&(!fileIds.isEmpty())) {
                log.info("files and news package downloading ");
                List<String> list=new ArrayList<>();
                list.add(newsFilePath);
                list.add(fileFilePath);
                log.info("newsFilePath:{},fileFilePath:{}",newsFilePath,fileFilePath);
                String filePath = knowledgeService.comprocessByName(list,fileName );
                log.info("filePath:{}",filePath);
                response.setHeader("content-Disposition", "attachment;filename=" + URLEncoder.encode(filePath, "UTF-8"));
                ExcelExportUtil.download(response, filePath, true);
                return;
            }
            if (fileIds.isEmpty()) {//news
                log.info("only news downloading");
                redisUtil.del(newsIds);
                if(newsFilePath==null){
                    log.error("nothing");
                    return;
                }
                log.info("newsFilePath:{}",newsFilePath);
                response.setHeader("content-Disposition", "attachment;filename=" + URLEncoder.encode(newsFilePath, "UTF-8"));
                ExcelExportUtil.download(response, newsFilePath, true);
                return;
            }
            log.info("only files downloading");
            String s = knowledgeService.exportPackage(fileIds);
            log.info("packageFile:{}",s);
            response.setHeader("content-Disposition", "attachment;filename=" + URLEncoder.encode(s, "UTF-8"));
            ExcelExportUtil.download(response, s, true);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }

    }
    /**
     * Minio多文件打包下载
     * @param response
     */
    @GetMapping("/downloadMinioFiles")
    public void downloadMinioFiles(String fileIds,HttpServletResponse response) throws IOException {
        List<Enclosure> fileList = enclosureService.getFilePathByIds(fileIds);
        //被压缩文件InputStream
        InputStream[] srcFiles = new InputStream[fileList.size()];
        //被压缩文件名称
        String[] srcFileNames = new String[fileList.size()];
        for (int i = 0; i < fileList.size(); i++) {
            String fileUrl = fileList.get(i).getUrlPath();
            if(fileUrl.startsWith("/")){
                fileUrl = fileUrl.substring(1);
            }
            //提取存储桶名
            String bucketName = fileUrl.split("/")[0];
            String fileName = fileUrl.replace(bucketName+"/","");
            InputStream inputStream = MinioUtil.getMinioFile(bucketName,fileName);
            if (inputStream == null) {
                continue;
            }
            srcFiles[i] = inputStream;
            srcFileNames[i] = fileList.get(i).getName();
        }
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("下载测试.zip", "UTF-8"));
        //多个文件压缩成压缩包返回
        ZipUtil.zip(response.getOutputStream(), srcFileNames, srcFiles);
    }
    /**
     * 文本类数据导出
     * @param response
     */
    @RequestMapping(value = "/downloadNewsFiles")
    public void downloadNewsFiles(String newsIds,HttpServletResponse response) throws Exception {
        List<KnowledgeVO> knowledgeList = knowledgeService.queryListByIds(newsIds);
        //封装数据
        List<KnowledgeExcel> dataList = new ArrayList<>();
        for (KnowledgeVO knowledgeVO : knowledgeList) {
            KnowledgeExcel knowledgeExcel = new KnowledgeExcel();
            BeanUtils.copyProperties(knowledgeVO, knowledgeExcel);
            dataList.add(knowledgeExcel);
            if(StringUtils.isEmpty(knowledgeExcel.getContent())){
                knowledgeExcel.setContent(ContentUtility.TransferHTML2Text(knowledgeExcel.getContentWithTag()));
            }
        }
        String filePath = Constants.TEMP_FILES_DIR + "downloadNewsFiles.xlsx";
        ExcelExportUtil.writeExcelFront(dataList, "数据导出", filePath, KnowledgeExcel.class);
        ExcelExportUtil.download(response, filePath, true);
    }
}

@Data
class DeleteParam {
    private List<Knowledge> knowledgeList;
}