package com.liang.common.fileupload.controller;

import com.liang.common.base.BaseController;
import com.liang.common.base.BaseResult;
import com.liang.common.utils.ExcelPoiUtil;
import com.liang.common.utils.FileNameValidator;
import com.liang.entity.*;
import com.liang.service.*;
import io.swagger.annotations.Api;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author liang
 * @date 2023-03-27-15:35
 * @description 文件操作公共控制器
 **/
@Api(value = "文件操作公共控制器", tags = "文件操作公共控制器")
@Controller
@RequestMapping("/fileupload")
public class FileUploadController extends BaseController {
    final static Logger logger = LoggerFactory.getLogger(FileUploadController.class);

    @Resource
    private BasePersonService basePersonService;
    @Resource
    private PrjProjectroleService projectroleService;
    @Resource
    private BaseCompanyService baseCompanyService;
    @Resource
    private PrjGwtaskService prjGwtaskService;
    @Resource
    private StaSourceFeeService staSourceFeeService;

    @PostMapping("/upload")
    @ResponseBody
    public BaseResult upload(MultipartHttpServletRequest request) throws IOException {
        Iterator<String> itr = request.getFileNames();
        String fileType = request.getParameter("fileType");
        String ret = "";

        Map<String, String> resultMap = new HashMap<>();
        if (itr.hasNext()) {
            String uploadFile = itr.next();
            Map<String, Object> xlsMap = new HashMap<>();
            MultipartFile file = request.getFile(uploadFile);
            if (fileType.equals("memberFile")) {
                List<PrjMember> list = ExcelPoiUtil.memberImport(file);
                List<String> tipList = new ArrayList<>();
                List<Map<String, String>> roleList = projectroleService.getProjectRole();

                for (int i = 0; i < list.size(); i++) {
                    PrjMember member = list.get(i);
                    BasePerson person = basePersonService.queryById(member.getRy());
                    if (person != null) {
                        BaseCompany company = baseCompanyService.queryById(person.getDw());
                        member.setDw(person.getDw());
                        member.setDwmc(person.getDwmc());
                        member.setDwmc(person.getDwmc());
                        member.setZc(person.getZc());
                        member.setZcmc(person.getZcmc());
                        member.setXl(person.getXl());
                        if (person.getXlmc() != null)
                            member.setXlmc(person.getXlmc());
                        else
                            member.setXlmc("");
                        if (company != null) {
                            member.setDwlx(company.getLx().toString());
                            member.setDwlxmc(company.getLxmc());
                        }
                    } else {
                        tipList.add(member.getRyxm());
                    }
                    boolean roleFlag = false;
                    for (Map<String, String> map : roleList) {
                        if (map.get("name").trim().equals(member.getXmjsmc())) {
                            member.setXmjsmc(member.getXmjsmc());
                            member.setXmjs(map.get("code").toString());
                            roleFlag = true;
                            break;
                        }
                    }
                    if (!roleFlag) {
                        member.setXmjs("3");
                        member.setXmjsmc("完成人");
                    }
                    list.set(i, member);
                }

                if (tipList.size() == 0 && list.size() > 0)
                    xlsMap.put("code", 0);
                else if (tipList.size() > 0)
                    xlsMap.put("code", 10);
                else
                    xlsMap.put("code", 20);
                xlsMap.put("tipList", tipList);
                xlsMap.put("list", list);
                xlsMap.put("fileType", fileType);

                return BaseResult.success("主要完成人导入成功!", xlsMap);
            }
            if (fileType.equals("personFile")) {
                List<StaDirector> list = ExcelPoiUtil.directorImport(file);
                List<String> tipList = new ArrayList<>();
                List<BasePerson> resultList = new ArrayList<>();
//                list.sort(Comparator.comparing(StaDirector::getXh));
                for (int i = 0; i < list.size(); i++) {
                    StaDirector director = list.get(i);
                    BasePerson person = basePersonService.queryById(director.getFzr());
                    if (person != null) {
                        person.setXh(director.getXh());
                        resultList.add(person);
                    } else {
                        tipList.add(director.getXm());
                    }
                }

                if (tipList.size() == 0 && resultList.size() > 0)
                    xlsMap.put("code", 0);
                else if (tipList.size() > 0)
                    xlsMap.put("code", 10);
                else
                    xlsMap.put("code", 20);
                xlsMap.put("tipList", tipList);
                xlsMap.put("list", resultList);
                xlsMap.put("fileType", fileType);

                return BaseResult.success("项目负责人导入成功!", xlsMap);
            }
            //差旅费批量导入
            if(fileType.equals("clfFile")){
                List<StaTravelexpenses> list = ExcelPoiUtil.clfImport(file);

                List<String> tipList = new ArrayList<>();
                for (int i = 0; i < list.size(); i++) {
                    StaTravelexpenses staTravelexpenses = list.get(i);
                    BasePerson person = basePersonService.queryById(staTravelexpenses.getCcr());
                    if (person != null) {
                        list.get(i).setCcrxm(person.getXm());
                    } else {
                        tipList.add(list.get(i).getCcr().toString());
                    }
                }

                if (tipList.size() == 0 && list.size() > 0)
                    xlsMap.put("code", 0);
                else if (tipList.size() > 0)
                    xlsMap.put("code", 10);
                else
                    xlsMap.put("code", 20);
                xlsMap.put("tipList", tipList);
                xlsMap.put("list", list);
                xlsMap.put("fileType", fileType);
                return BaseResult.success("材料费导入成功!", xlsMap);
            }
            //会议费批量导入
            if (fileType.equals("hyfFile")){
                List<StaMeetingFee> list = ExcelPoiUtil.hyfImport(file);
                if (list.size()>0){
                xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("会议费导入成功!", xlsMap);
            }
            //资料费批量导入
            if(fileType.equals("zlfFile")){
                List<StaSourceFee> list = ExcelPoiUtil.zlfImport(file);
                //添加判断条件，同一部门一本书籍只能申请一次，不可重复申请
                String deptName = getSysUserInfo().getDeptName();
                //获取该部门下已申请的书籍
                List<StaSourceFee> TsmcList = staSourceFeeService.searchSourceTsmcByDeptName(deptName);
                Set<String> tsmcSet = new HashSet<>();
                Set<String> tsmcSet2 = new HashSet<>();
                //用于存储部门已申请重复数据
                List<String> filteredList = new ArrayList<>();
                //用于自我查重重复数据
                List<String> filtered2List = new ArrayList<>();
                for (StaSourceFee fee : list) {
                    tsmcSet.add(fee.getTsmc());
                }
                //自我查重
                for (StaSourceFee fee : list) {
                    String bookName = fee.getTsmc();
                    if (!tsmcSet2.add(bookName)) {// 如果添加失败，说明是重复的
                        filtered2List.add(bookName);
                    }
                }
                // 查找第二个列表中与集合中的 tsmc 重复的值
                for (StaSourceFee fee : TsmcList) {
                    if (tsmcSet.contains(fee.getTsmc())) {
                        filteredList.add(fee.getTsmc());
                    }
                }
                if (filteredList.size()>0||filtered2List.size()>0){
                    xlsMap.put("code",10);
                    xlsMap.put("fileType",fileType);
                    StringBuilder messageBuilder = new StringBuilder();
                    if (filteredList.size()>0){
                    messageBuilder.append(deptName + "在资料费中已申请过：");
                    for (int i = 0; i < filteredList.size(); i++) {
                        String bookName = filteredList.get(i);
                        messageBuilder.append(bookName);
                        if (i < filteredList.size() - 1) {
                            messageBuilder.append(", ");
                        }
                        }
                    }
                    if (filtered2List.size()>0){
                        messageBuilder.append("表格中申请出现重复资料：");
                        for (int i = 0; i < filtered2List.size(); i++) {
                            String bookName = filtered2List.get(i);
                            messageBuilder.append(bookName);
                            if (i < filtered2List.size() - 1) {
                                messageBuilder.append(", ");
                            }
                        }
                    }
                    String message = messageBuilder.toString();
                    return BaseResult.failure(message);
                }else {
                    xlsMap.put("code", 0);
                    xlsMap.put("list",list);
                    xlsMap.put("fileType",fileType);
                    return BaseResult.success("资料费导入成功!", xlsMap);
                }
            }
            //印刷费批量导入
            if(fileType.equals("ysfFile")){
                List<StaPrintingFee> list = ExcelPoiUtil.ysfImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("印刷费导入成功!", xlsMap);
            }
            //知识产权费批量导入
            if(fileType.equals("zscqfFile")){
                List<StaIntellectualProperty> list = ExcelPoiUtil.zscqfImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("知识产权费导入成功!", xlsMap);
            }
            //间接费批量导入
            if (fileType.equals("jjfFile")){
                List<StaIndirectCosts> list = ExcelPoiUtil.jjfImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("间接费导入成功!", xlsMap);
            }
            //专家费批量导入
            if (fileType.equals("zjfFile")){
                List<StaExpertFee> list = ExcelPoiUtil.zjfImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("专家费导入成功!", xlsMap);
            }
            //设备使用费批量导入
            if (fileType.equals("devFile")){
                List<StaDeviceexpenses> list = ExcelPoiUtil.devImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("设备使用费导入成功!", xlsMap);
            }
            //材料费批量导入
            if (fileType.equals("CLfsFile")){
                List<StaMaterial> list = ExcelPoiUtil.CLfsImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("材料费导入成功!", xlsMap);
            }
            //软件费批量导入
            if(fileType.equals("swFile")){
                List<StaSoftwareexpenses> list = ExcelPoiUtil.swImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("软件使用费导入成功!", xlsMap);
            }
            //外委研究支出费
            if (fileType.equals("WwFile")){
                List<StaOutexpense> list = ExcelPoiUtil.WwImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("外委研究支出费导入成功!", xlsMap);
            }
            //外协测试实验与加工费
            if (fileType.equals("WxFile")){
                List<StaOutttesting> list = ExcelPoiUtil.WxImport(file);
                if (list.size()>0){
                    xlsMap.put("code",0);
                }else {
                    xlsMap.put("code", 10);
                }
                xlsMap.put("list",list);
                xlsMap.put("fileType",fileType);
                return BaseResult.success("外协测试实验与加工费导入成功!", xlsMap);
            }
            ret = file.getOriginalFilename();
            FileNameValidator fileNameValidator = new FileNameValidator();
            Integer nuk = fileNameValidator.isValidFileName(ret);
            if ( nuk==1){
                return BaseResult.failure("文件名为空不合法!");
            }
            if (nuk ==2){
                return BaseResult.failure("文件名过长!");
            }
            if (nuk == 3) {
                return BaseResult.failure("文件名包含非法字符");
            }
            try {
                Date date = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String str = sdf.format(date);  //文件上传日期

                SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMM");
                String strFolder = sdf1.format(date);  //增加时间文件夹

                String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();

                String targetFile = uploadFolder + "/" + strFolder + "/" + uuid + "_" + ret;
                File files = new File(targetFile);
                logger.info(targetFile);
                if (!files.getParentFile().exists())
                    files.getParentFile().mkdir();

                file.transferTo(files);

                if (logger.isInfoEnabled()) {
                    logger.info("FileUploadController -- put -- storageFile = {}", ret);
                }
                String fileUrl = request.getScheme() + "://" +
                        request.getServerName() + ":" + webfileport + "/" + strFolder + "/" + uuid + "_" + ret;
                resultMap.put("code", "0");
                resultMap.put("fileName", ret);
                resultMap.put("fileUrl", fileUrl);
                resultMap.put("fileDate", str);
                resultMap.put("fileType", fileType);

                if (fileType.equals("gwtask")) {
                    PrjGwtask prjGwtask = new PrjGwtask();
                    prjGwtask.setScr(getSysUserInfo().getName());
                    prjGwtask.setWeburl(fileUrl);
                    prjGwtask.setBz("");
                    prjGwtask.setWjm(ret);
                    prjGwtaskService.insert(prjGwtask);
                    resultMap.put("scr", getSysUserInfo().getName());
                    resultMap.put("id", prjGwtask.getId().toString());
                }

                return BaseResult.success("文件上传成功!", resultMap);
            } catch (IOException e) {
                e.printStackTrace();
                //出现异常，则告诉页面失败
                resultMap.put("code", "-1");
                return BaseResult.failure("文件上传失败!");
            }
        } else {
            resultMap.put("code", "-2");
            return BaseResult.failure("未发现上传文件!");
        }
    }

    @GetMapping("{filename}")
    public BaseResult getTemplate(@PathVariable("filename") String filename) {
        Map<String, String> resultMap = new HashMap<>();

        String fileUrl = "http://" +
                webfileip + ":" + webfileport + "/template/" + filename;

        resultMap.put("code", "0");
        resultMap.put("fileUrl", fileUrl);
        return BaseResult.success("文件上传成功!", resultMap);
    }

    @RequestMapping("/exportWord")
    public void exportWord(HttpServletResponse response) throws Exception {
        // 加载模板文件
        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("template.docx");

        XWPFDocument document = new XWPFDocument(OPCPackage.open(inputStream));

        // 填充占位符
        Map<String, Object> data = new HashMap<>();
        data.put("title", "测试标题");
        data.put("content", "测试内容");
        processTemplate(document, data);

        // 设置response头信息
        String fileName = "test.docx";
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/msword");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        // 输出文件
        OutputStream outputStream = response.getOutputStream();
        document.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

    private void processTemplate(XWPFDocument document, Map<String, Object> data) {
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            processParagraph(paragraph, data);
        }
        for (XWPFTable tbl : document.getTables()) {
            for (XWPFTableRow row : tbl.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        processParagraph(paragraph, data);
                    }
                }
            }
        }
    }

    private void processParagraph(XWPFParagraph paragraph, Map<String, Object> data) {
        for (XWPFRun run : paragraph.getRuns()) {
            String text = run.getText(0);
            if (text != null) {
                for (Map.Entry<String, Object> entry : data.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    if (text.contains(key)) {
                        text = text.replace(key, String.valueOf(value));
                        run.setText(text, 0);
                    }
                }
            }
        }
    }
}
