package com.jeeplus.pubmodules.oss.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.jeeplus.aop.demo.annotation.DemoMode;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.flowable.feign.IFinanceApi;
import com.jeeplus.logging.annotation.ApiLog;
import com.jeeplus.pubmodules.oss.domain.WorkAttachment;
import com.jeeplus.pubmodules.oss.service.OSSClientService;
import com.jeeplus.pubmodules.oss.service.OssService;
import com.jeeplus.pubmodules.oss.service.dto.*;
import com.jeeplus.pubmodules.oss.utils.FileUtil;
import com.jeeplus.pubmodules.serialNumTpl.service.SerialnumTplService;
import com.jeeplus.sys.domain.WorkAttachmentInfo;
import com.jeeplus.sys.feign.IOfficeApi;
//import com.jeeplus.sys.service.OfficeService;
import com.jeeplus.sys.feign.IUserApi;
//import com.jeeplus.sys.service.UserService;
import com.jeeplus.sys.service.dto.CertDTO;
import com.jeeplus.sys.service.dto.OfficeDTO;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.sys.service.dto.WorkAttachmentInfoDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Slf4j
@Api(tags ="oss")
@RestController
@RequestMapping(value = "/oss/file")
public class OssFileController {

    @Value("${config.accessory.aliyun.aliyunUrl}")
    private String aliyunUrl;

    @Value("${config.accessory.aliyun.aliyunDownloadUrl}")
    private String aliyunDownloadUrl;

    @Resource
    private OssService ossService;

    @Resource
    private SerialnumTplService serialnumTplService;

    @Autowired
    private OSSClientService ossClientService;

//    @Autowired
//    private UserService userService;

//    @Autowired
//    private OfficeService officeService;

    @ApiOperation(value = "保存数据")
    @PostMapping("/saveMsg")
    public void saveMsg(@RequestBody List<WorkAttachment> workAttachments) {
        String currentToken = TokenProvider.getCurrentToken();
        ossService.saveMsg(workAttachments,currentToken);
    }

    @GetMapping("/deleteMsgByFileName")
    @ApiOperation(value = "删除数据")
    public void deleteMsgByFileName(@RequestParam String url) {
        ossService.deleteMsgByFileName(url);
    }

    @GetMapping("/deleteMsgById")
    @ApiOperation(value = "根据id删除数据")
    public void deleteMsgById(@RequestParam String id) {
        ossService.deleteMsgById(id);
    }

    @GetMapping("/getTemporaryUrl")
    @ApiOperation(value = "根据url获取临时文件地址")
    public ResponseEntity<String> getTemporaryUrl(@RequestParam String url) {
        String temporaryLookUrl = ossService.getFileTemporaryLookUrl(aliyunUrl + url);
        return ResponseEntity.ok(temporaryLookUrl);
    }

    @GetMapping("/getThumbnailTemporaryLookUrl")
    @ApiOperation(value = "根据url获取临时文件缩略图地址")
    public ResponseEntity<String> getThumbnailTemporaryLookUrl(@RequestParam String url) {
        String temporaryLookUrl = ossService.getThumbnailTemporaryLookUrl(aliyunUrl + url);
        return ResponseEntity.ok(temporaryLookUrl);
    }

    @GetMapping("/getFileTemporaryLookUrlWithWatermark")
    @ApiOperation(value = "根据url获取临时文件带水印、虚化原图地址")
    public ResponseEntity<String> getFileTemporaryLookUrlWithWatermark(@RequestParam String url) {
        String temporaryLookUrl = ossService.getFileTemporaryLookUrlWithWatermark(aliyunUrl + url);
        return ResponseEntity.ok(temporaryLookUrl);
    }

    @GetMapping("/getThumbnailTemporaryWithWatermarkDimLookUrl")
    @ApiOperation(value = "根据url获取临时文件带水印、虚化、缩略图地址")
    public ResponseEntity<String> getThumbnailTemporaryWithWatermarkDimLookUrl(@RequestParam String url) {
        String temporaryLookUrl = ossService.getThumbnailTemporaryWithWatermarkDimLookUrl(aliyunUrl + url);
        return ResponseEntity.ok(temporaryLookUrl);
    }

    @GetMapping("/findFileList")
    @ApiOperation(value = "查询数据")
    public ResponseEntity<List<AttachmentDTO>> findFileList(@RequestParam("attachmentId") String attachmentId) {
        List<AttachmentDTO> list = ossService.findFileList(attachmentId);
        return ResponseEntity.ok(list);
    }

    /**
     * 下载附件
     */
    @GetMapping("/downLoadAttach")
    @ApiOperation(value = "下载附件")
    public String downLoadAttach(@RequestParam String file, HttpServletResponse response, HttpServletRequest request) throws IOException {
        file = "http://oss.gangwaninfo.com" + file;
        file = file.replace("amp;", "");
        String fileName = file.substring(file.lastIndexOf("/") + 1, file.length());
        String cons = "";
        if (file.contains(aliyunUrl)) {
            cons = aliyunUrl;
        } else if (file.contains("http://gangwan-app.oss-cn-hangzhou.aliyuncs.com")) {
            cons = "http://gangwan-app.oss-cn-hangzhou.aliyuncs.com";
        } else {
            cons = aliyunDownloadUrl;
        }
        String key = file.split(cons + "/")[1];
        log.info("-----------------------------------------");
        log.info("fileName=" + fileName);
        log.info("key=" + key);
        log.info("-----------------------------------------");
        ossService.downByStream(key, fileName, response, request.getHeader("USER-AGENT"));
        return null;
    }

    @GetMapping("/getFileSizeByUrl")
    @ApiOperation(value = "根据文件路径获取文件信息")
    public ResponseEntity<FileDetailDTO> getFileSizeByUrl(@RequestParam("url") String url) {
        FileDetailDTO fileDetailDTO = ossService.getFileSizeByUrl(url);
        return ResponseEntity.ok(fileDetailDTO);
    }

    @GetMapping("/getSFZSizeByUrl")
    @ApiOperation(value = "根据文件路径获取身份证图片信息")
    public ResponseEntity<FileDetailDTO> getSFZSizeByUrl(@RequestParam("url") String url) {
        FileDetailDTO fileDetailDTO = ossService.getSFZSizeByUrl(url);
        return ResponseEntity.ok(fileDetailDTO);
    }

    /**
     * 上传文件
     * @return
     * @throws IOException
     */
    @ApiOperation("上传文件")
    @PostMapping("webUpload/upload")
    public ResponseEntity<FileUrlDto> webUpload(MultipartFile file) throws IOException {
        String dir = "note";
        FileUrlDto dto = ossService.webUpload(file,dir);
        return ResponseEntity.ok(dto);
    }

    /**
     * 上传文件
     * @return
     * @throws IOException
     */
    @ApiOperation("上传文件")
    @PostMapping("webUpload/fileUpload")
    public ResponseEntity<FileUrlDto> fileUpload(MultipartFile file,@RequestParam(required = false) String dir) throws IOException {
        if(StringUtils.isBlank(dir)){
            dir = "oss";
        }
        FileUrlDto dto = ossService.webUpload(file,dir);
        return ResponseEntity.ok(dto);
    }

    /**
     * 根据attachmentId查询附件信息（list）
     * @param id
     * @return
     */
    @PostMapping("selectWorkAttachmentByAttachmentId")
    public List<WorkAttachmentInfo> selectWorkAttachmentByAttachmentId(String id){
        return ossService.selectWorkAttachmentByAttachmentId(id);
    }

    /**
     * 根据id查询用户
     *
     * @param id
     * @return
     */
    @ApiLog("查询用户")
    @GetMapping("queryById")
    @ApiOperation(value = "查询用户")
    public ResponseEntity queryById(@RequestParam("id") String id) {
        UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getById ( id );
        if (CollectionUtil.isEmpty(userDTO.getCertDTOList())){
            List<CertDTO> certListByUserId = SpringUtil.getBean ( IUserApi.class ).getCertListByUserId();
//            List<CertDTO> certListByUserId = userService.getCertListByUserId();
            userDTO.setCertDTOList(certListByUserId);
        }

        for (CertDTO cert : userDTO.getCertDTOList()) {
            List<WorkAttachmentInfoDTO> files = ossService.findAttachement(cert.getId(), "certificate");
            if (CollectionUtils.isNotEmpty(files)) {
                cert.setCertificateAttachment(files);
            }
        }
        if(StringUtils.isNotBlank(userDTO.getManageOfficeIds())){
            //获取当前人管理的部门id
            List<String> manageOfficeIdList= Arrays.asList(userDTO.getManageOfficeIds().split(","));
            //查询这些部门信息
            List<String> officeNameList = SpringUtil.getBean ( IOfficeApi.class ).getOfficeNameByIds(manageOfficeIdList);
//            List<String> officeNameList = officeService.getOfficeNameByIds(manageOfficeIdList);
            userDTO.setManageOfficeNameList(officeNameList);
        }
        if(ObjectUtil.isNotEmpty(userDTO)) {
            if(CollectionUtil.isNotEmpty(userDTO.getCertDTOList())){
                userDTO.getCertDTOList().stream().forEach(item->{
                    if (StringUtils.isNotBlank(item.getFileUrl())){
                        String fileTemporaryLookUrl = ossService.getFileTemporaryLookUrl(item.getFileUrl());
                        item.setFileLsUrl(fileTemporaryLookUrl);
                    }
                });
            }
        }
        //根据office.id 查询部门的所有父节点信息
        if(null != userDTO.getOfficeDTO() && StringUtils.isNotBlank(userDTO.getOfficeDTO().getId())){
            OfficeDTO office = SpringUtil.getBean ( IOfficeApi.class ).getOfficeById(userDTO.getOfficeDTO().getId());
//            OfficeDTO office = officeService.getOfficeById(userDTO.getOfficeDTO().getId());
            //将office的父节点信息进行分割并查询赋值
            if(null != office){
                List<String> officeIdList = Arrays.asList(office.getParentIds().split(","));
                Integer sort = 0;
                if(null != officeIdList && officeIdList.size()>0){
                    for (String officeId : officeIdList) {
                        if(StringUtils.isNotBlank(officeId) && !"0".equals(officeId)){
                            sort ++ ;
                            OfficeDTO officeChild = SpringUtil.getBean ( IOfficeApi.class ).getOfficeById(officeId);
//                            OfficeDTO officeChild = officeService.getOfficeById(officeId);
                            if(null != officeChild) {
                                switch (sort){
                                    case 1:
                                        userDTO.setCompanyDTO(officeChild);
                                        break;
                                    case 2:
                                        userDTO.setCorporationDTO(officeChild);
                                        break;
                                    case 3:
                                        userDTO.setOfficeDTO(officeChild);
                                        break;
                                }
                            }
                        }
                    }
                }
            }

        }
        return ResponseEntity.ok ( userDTO );
    }

    /**
     * 财务模块保存附件使用
     * @param map
     */
    @RequestMapping(value = "financeFileSave", method = RequestMethod.POST)
    public void insertWorkAttachment (@RequestBody Map<String ,String > map){
        String attachmentInfo = map.get("workAttachment");
        String userDtoInfo = map.get("userDTO");
        WorkAttachment attachment = JSON.parseObject(attachmentInfo, new TypeReference<WorkAttachment>() {});
        UserDTO userDTO = JSON.parseObject(userDtoInfo, new TypeReference<UserDTO>() {});
        ossService.insertWorkAttachment(attachment,userDTO);
    }

    @GetMapping("/deleteById")
    @ApiOperation(value = "根据id删除财务文件数据")
    public void deleteById(@RequestParam String id) {
        ossService.deleteById(id);
    }

    /**
     * 保存附件操作
     * @param map
     */
    @RequestMapping(value = "saveOrUpdateFileList", method = RequestMethod.POST)
    public void saveOrUpdateFileList(@RequestBody Map<String ,String > map){
        String fileListInfo = map.get("fileList");
        String attachmentId = map.get("attachmentId");
        String attachmentFlag = map.get("attachmentFlag");
        String currentToken = map.get("currentToken");
        List<WorkAttachmentDto> fileList = JSON.parseObject(fileListInfo, new TypeReference<List<WorkAttachmentDto>>() {});
        ossService.saveOrUpdateFileList(fileList,attachmentId,attachmentFlag,currentToken);
    }

    @RequestMapping(value = "saveOrUpdateFileListFlag", method = RequestMethod.POST)
    public void saveOrUpdateFileListFlag(@RequestBody Map<String ,String > map) {
        String fileListInfo = map.get("fileList");
        String attachmentId = map.get("attachmentId");
        String attachmentFlag = map.get("attachmentFlag");
        String currentToken = map.get("currentToken");
        List<WorkAttachmentInfoDTO> fileList = JSON.parseObject(fileListInfo, new TypeReference<List<WorkAttachmentInfoDTO>>() {});
        ossService.saveOrUpdateFileListFlag(fileList,attachmentId,attachmentFlag,currentToken);
    }


    @GetMapping("/deleteByAttachmentId")
    @ApiOperation(value = "根据attachmentId删除附件")
    public void deleteByAttachmentId(String attachmentId) {
        ossService.deleteByAttachmentId(attachmentId);
    }

    @GetMapping("/deleteByAttachmentIdNotInIds")
    @ApiOperation(value = "根据attachmentId删除附件")
    public void deleteByAttachmentIdNotInIds(String attachmentId,List<String> delIds) {
        ossService.deleteByAttachmentIdNotInIds(attachmentId,delIds);
    }

    /**
     * 根据attachmentId查询附件信息（list）
     * @param attachmentId
     * @return
     */
    @PostMapping("selectListByAttachmentId")
    public List<WorkAttachmentInfo> selectListByAttachmentId(@RequestParam String attachmentId){
        return ossService.selectListByAttachmentId(attachmentId);
    }

    @ApiOperation(value = "根据ids删除财务文件数据")
    @RequestMapping(value = "deleteByIds", method = RequestMethod.POST)
    public void deleteByIds(@RequestBody String ids) {
        List<String> idList = JSON.parseObject(ids, new TypeReference<List<String>>() {});
        idList.forEach(id->{
            ossService.deleteById(id);
        });

    }

    /**
     * 保存附件操作
     * @param map
     */
    @RequestMapping(value = "saveFile", method = RequestMethod.POST)
    public String saveFile(@RequestBody Map<String ,String > map){
        WorkAttachmentDto workAttachmentDto = JSON.parseObject(map.get("workAttachmentDtoInfo"), new TypeReference<WorkAttachmentDto>() {});
        UserDTO userDTO = JSON.parseObject(map.get("userDTOInfo"), new TypeReference<UserDTO>() {});
        String attachmentId = map.get("attachmentId");
        String attachmentFlag = map.get("attachmentFlag");
        Integer sort = Integer.parseInt(map.get("sortInfo"));
        return ossService.saveFile(workAttachmentDto,userDTO,attachmentId,attachmentFlag,sort);
    }

    /**
     * 附件下载到本地指定文件夹
     * @param key
     * @param fileName
     * @param downFileStr
     */
    @RequestMapping(value = "/downByStreamSaveLocal", method = RequestMethod.POST)
    public void downByStreamSaveLocal(String key, String fileName, String downFileStr) {
        ossClientService.downByStreamSaveLocal(key, fileName, downFileStr);
    }


    /**
     * 根据路径下载所有文件到本地指定文件夹
     */
    @RequestMapping(value = "/downloadFolderFromOss", method = RequestMethod.POST)
    public void downloadFolderFromOss(String prefix, String localDir) {
        ossClientService.downloadFolderFromOss(prefix, localDir);
    }

    /**
     * 获取编号模板编号
     * @param companyId
     * @param bizCode
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/genSerialNum", method = RequestMethod.POST)
    public String genSerialNum(String companyId, String bizCode,String currentToken) throws Exception{
        return serialnumTplService.genSerialNum(companyId, bizCode, currentToken);
    }

    /**
     * 获取编号模板报告编号
     * @param companyId
     * @param bizCode
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/genSerialNumNoSort", method = RequestMethod.POST)
    public String genSerialNumNoSort(String companyId, String bizCode,String currentToken) throws Exception{
        return serialnumTplService.genSerialNumNoSort(companyId, bizCode,currentToken);
    }

    /**
     * 获取编号模板报告编号
     * @param companyId
     * @param bizCode
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/genSerialReviewNum", method = RequestMethod.POST)
    public String genSerialReviewNum(String companyId, String bizCode,String currentToken) throws Exception{
        return serialnumTplService.genSerialReviewNum(companyId, bizCode,currentToken);
    }

    /**
     * 根据关联id和url查询数据信息
     * @param workattachment
     * @return
     */
    @RequestMapping(value = "getByAttachmentIdAndUrlAndAttachmentFlag", method = RequestMethod.POST)
    public List<WorkAttachmentInfo> getByAttachmentIdAndUrlAndAttachmentFlag(@RequestBody WorkAttachmentInfo workattachment){
        return ossService.getByAttachmentIdAndUrlAndAttachmentFlag(workattachment);
    }

    /**
     * 附件下载到本地指定文件夹(签章系统)
     * @param key
     * @param fileName
     * @param downFileStr
     */
    @RequestMapping(value = "/downQzByStreamSaveLocal", method = RequestMethod.POST)
    public void downQzByStreamSaveLocal(String key, String fileName,String downFileStr) throws Exception{
        ossClientService.downQzByStreamSaveLocal(key,fileName,downFileStr);
    }

    @PostMapping("datePath")
    public String datePath() {
        return ossClientService.datePath();
    }

    @RequestMapping(value = "/uploadFile2OSS", method = RequestMethod.POST)
    public String uploadFile2OSS(InputStream inStream,String fileDir,String fileName) {
        return ossClientService.uploadFile2OSS(inStream, fileDir, fileName);
    }

    @RequestMapping(value = "/uploadFileSignatureOSS", method = RequestMethod.POST)
    public String uploadFileSignatureOSS(String filePath,String fileDir,String fileName) {
        return ossClientService.uploadFileSignatureOSS(filePath, fileDir, fileName);
    }

    /**
     * 保存附件操作
     * @param map
     */
    @RequestMapping(value = "saveMsg2", method = RequestMethod.POST)
    public void saveMsg2(@RequestBody Map<String ,String > map){
        String attachmentInfo = map.get("workAttachments");
        String currentToken = map.get("currentToken");
        List<WorkAttachment> list = JSON.parseObject(attachmentInfo, new TypeReference<List<WorkAttachment>>() {});
        ossService.saveMsg(list,currentToken);
    }

    /**
     * 移动端所需
     * 解析xml文件附件信息（发票报销）
     * @param file
     * @return
     */
    @DemoMode
    @PostMapping("/disposeXmlFileApp")
    @ApiOperation(value = "解析xml文件附件信息（发票报销）")
    public Map<String,Object> disposeXmlFileApp( MultipartFile file) throws IOException {
        Map<String,Object> map = new HashMap();
        //创建DOM4J解析器对象
        File newFile = null;
        try {
            //MultipartFile转File
            newFile = FileUtil.transformMultipartFile(file);
            // 创建一个 DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 使用工厂创建一个 DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 使用 DocumentBuilder 解析 XML 文件
            Document document = builder.parse(newFile);
            // 获取所有header节点的集合
            NodeList headerList = document.getElementsByTagName("Header");
            // 获取所有eInvoiceDataList节点的集合
            NodeList eInvoiceDataList = document.getElementsByTagName("EInvoiceData");
            // 获取所有taxSupervisionInfo节点的集合
            NodeList taxSupervisionInfoList = document.getElementsByTagName("TaxSupervisionInfo");

            Map<String,String> map1 = xmlNodeListDataDispose(headerList, document);
            Map<String,String> map2 = xmlNodeListDataDispose(eInvoiceDataList, document);
            Map<String,String> map3 = xmlNodeListDataDispose(taxSupervisionInfoList, document);
            map.putAll(map1);
            map.putAll(map2);
            map.putAll(map3);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            newFile.delete();
        }

        //对文件进行上传到阿里云操作
        String dir = "note";
        FileUrlDto dto = ossService.webUpload(file,dir);
        map.put("url", dto.getUrl());
        map.put("lsUrl", dto.getLsUrl());
        return map;
    }

    /**
     * 解析xml文件附件信息（发票报销）
     * @param file
     * @return
     */
    @DemoMode
    @PostMapping("/disposeXmlFile")
    @ApiOperation(value = "解析xml文件附件信息（发票报销）")
    public Map<String,Object> disposeXmlFile( MultipartFile file) {
        Map<String,Object> map = new HashMap();
        //创建DOM4J解析器对象
        File newFile = null;
        try {
            //MultipartFile转File
            newFile = FileUtil.transformMultipartFile(file);
            // 创建一个 DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 使用工厂创建一个 DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 使用 DocumentBuilder 解析 XML 文件
            Document document = builder.parse(newFile);
            // 获取所有header节点的集合
            NodeList headerList = document.getElementsByTagName("Header");
            // 获取所有eInvoiceDataList节点的集合
            NodeList eInvoiceDataList = document.getElementsByTagName("EInvoiceData");
            // 获取所有taxSupervisionInfo节点的集合
            NodeList taxSupervisionInfoList = document.getElementsByTagName("TaxSupervisionInfo");

            Map<String,String> map1 = xmlNodeListDataDispose(headerList, document);
            Map<String,String> map2 = xmlNodeListDataDispose(eInvoiceDataList, document);
            Map<String,String> map3 = xmlNodeListDataDispose(taxSupervisionInfoList, document);
            map.putAll(map1);
            map.putAll(map2);
            map.putAll(map3);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            newFile.delete();
        }
        return map;
    }

    /**
     * 下载附件
     */
    @PostMapping("/downLoadFileDisposeXmlFile")
    @ApiOperation(value = "下载附件")
    public Map<String,Object> downLoadFileDisposeXmlFile(@RequestParam String file) {
        file = "http://oss.gangwaninfo.com" + file;
        file = file.replace("amp;", "");
        String fileName = file.substring(file.lastIndexOf("/") + 1, file.length());
        String cons = "";
        if (file.contains(aliyunUrl)) {
            cons = aliyunUrl;
        } else if (file.contains("http://gangwan-app.oss-cn-hangzhou.aliyuncs.com")) {
            cons = "http://gangwan-app.oss-cn-hangzhou.aliyuncs.com";
        } else {
            cons = aliyunDownloadUrl;
        }
        String key = file.split(cons + "/")[1];
        log.info("-----------------------------------------");
        log.info("fileName=" + fileName);
        log.info("key=" + key);
        log.info("-----------------------------------------");

        String path = null;
        if(System.getProperty("os.name").toLowerCase().contains("win")){
            path = "D:/attachment-file/";
        }else{
            path = "/attachment-file/";
        }
        ossClientService.downByStreamSaveLocal(key, fileName, path+fileName);

        Map<String,Object> map = new HashMap();
        //创建DOM4J解析器对象
        File newFile = new File(path + fileName);
        try {
            //MultipartFile转File
            //newFile = FileUtil.transformMultipartFile(file);
            // 创建一个 DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 使用工厂创建一个 DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 使用 DocumentBuilder 解析 XML 文件
            Document document = builder.parse(newFile);
            // 获取所有header节点的集合
            NodeList headerList = document.getElementsByTagName("Header");
            // 获取所有eInvoiceDataList节点的集合
            NodeList eInvoiceDataList = document.getElementsByTagName("EInvoiceData");
            // 获取所有taxSupervisionInfo节点的集合
            NodeList taxSupervisionInfoList = document.getElementsByTagName("TaxSupervisionInfo");

            Map<String,String> map1 = xmlNodeListDataDispose(headerList, document);
            Map<String,String> map2 = xmlNodeListDataDispose(eInvoiceDataList, document);
            Map<String,String> map3 = xmlNodeListDataDispose(taxSupervisionInfoList, document);
            map.putAll(map1);
            map.putAll(map2);
            map.putAll(map3);

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            newFile.delete();
        }
        return map;
    }

    /**
     * 对节点集合进行遍历，并获取每个节点下的参数信息
     * @param nodeList
     * @param document
     * @return
     */
    public Map<String,String> xmlNodeListDataDispose(NodeList nodeList,Document document){
        Map<String,String> map = new HashMap<>();
        Map<String, Integer> keyCounter = new HashMap<>(); // 同名节点计数器
        if(null != nodeList && nodeList.getLength()>0){
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node topNode = nodeList.item(i); // 0层：Header/EInvoiceData/TaxSupervisionInfo
                NodeList childNodes = topNode.getChildNodes();
                // 初始化层级为1（顶层直接子节点），父前缀为空
                Map<String,String> map1 = xmlDataDispose(childNodes, document, "", 1, keyCounter);
                map.putAll(map1);
            }
        }
        return map;
    }

    /**
     * 修复同名节点重复拼接问题：第2层与第1层同名时，仅保留1次节点名
     * 规则：0/1层不拼接，2层若与1层同名则不重复拼接，3层及以下正常拼接
     */
    public Map<String,String> xmlDataDispose(NodeList childNodes,Document document, String parentPrefix, int currentLevel, Map<String, Integer> keyCounter){
        Map<String,String> map = new HashMap<>();
        for (int k = 0; k < childNodes.getLength(); k++) {
            if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
                Node currentNode = childNodes.item(k);
                String nodeName = currentNode.getNodeName();
                String cleanNodeName = nodeName.replaceAll("-", "");
                NodeList grandChildNodes = currentNode.getChildNodes();

                String currentKeyPrefix;
                if (currentLevel == 1) {
                    currentKeyPrefix = cleanNodeName;
                } else if (currentLevel == 2) {
                    if (cleanNodeName.equals(parentPrefix)) {
                        currentKeyPrefix = parentPrefix;
                    } else {
                        currentKeyPrefix = parentPrefix + cleanNodeName;
                    }
                } else {
                    currentKeyPrefix = parentPrefix + cleanNodeName;
                }

                String textValue = getNodeTextValue(grandChildNodes);
                // 修复：空文本但有子元素时仍递归（避免漏解析深层节点）
                if (StringUtils.isNotBlank(textValue) || hasChildElements(grandChildNodes)) {
                    if (StringUtils.isNotBlank(textValue)) {
                        String finalKey = generateUniqueKey(currentKeyPrefix, keyCounter);
                        map.put(finalKey, textValue);
                    }
                    if (hasChildElements(grandChildNodes)) {
                        Map<String,String> childMap = xmlDataDispose(grandChildNodes, document, currentKeyPrefix, currentLevel + 1, keyCounter);
                        map.putAll(childMap);
                    }
                }
            }
        }
        return map;
    }

    /**
     * 提取节点有效文本值（仅保留非空白文本）
     */
    private String getNodeTextValue(NodeList childNodes) {
        StringBuilder text = new StringBuilder();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node child = childNodes.item(i);
            // 修复1：新增CDATA节点处理（数电票核心字段多为CDATA包裹）
            if (child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE) {
                // 修复2：先拼接原始值，最后统一trim（避免中间有效换行/空格被过滤）
                text.append(child.getNodeValue());
            }
        }
        // 仅首尾trim，保留中间有效文本（如Remark里的换行转义后内容）
        return StringUtils.trim(text.toString());
    }

    /**
     * 判断是否有子元素节点
     */
    private boolean hasChildElements(NodeList childNodes) {
        for (int i = 0; i < childNodes.getLength(); i++) {
            if (childNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
                return true;
            }
        }
        return false;
    }

    /**
     * 生成不重复key（同名节点加序号，避免覆盖）
     */
    private String generateUniqueKey(String keyPrefix, Map<String, Integer> keyCounter) {
        // 修复：先获取当前计数（初始为0），再判断是否需要加序号
        int count = keyCounter.getOrDefault(keyPrefix, 0);
        if (count == 0) {
            // 首次出现：直接返回前缀，计数置为1
            keyCounter.put(keyPrefix, 1);
            return keyPrefix;
        } else {
            // 重复出现：计数+1，返回前缀+序号（如SellerName2）
            keyCounter.put(keyPrefix, count + 1);
            return keyPrefix + count;
        }
    }

    @ApiOperation("处理数电发票数据中的购买方名称信息")
    @GetMapping("/disposeElectronicEngineeringInvoice")
    public Map<String,String> disposeElectronicEngineeringInvoice(@RequestParam List<String> attachmentIdList, @RequestParam String type){
        //首先获取所有数电发票报销信息
        Map<String, String> map = ossService.disposeElectronicEngineeringInvoice(attachmentIdList, type);

        return map;
    }

    @ApiOperation("获取数电发票数据中的发票号信息")
    @GetMapping("/disposeElectronicEngineeringInvoiceNumber")
    public Map<String,String> disposeElectronicEngineeringInvoiceNumber(@RequestParam List<String> attachmentIdList, @RequestParam String type){
        //首先获取所有数电发票报销信息
        Map<String, String> map = ossService.disposeElectronicEngineeringInvoiceNumber(attachmentIdList, type);

        return map;
    }

    /**
     * 根据发票号查询是否已经被报销
     */
    @ApiOperation("根据发票号查询是否已经被报销")
    @GetMapping("/isUsedByInvoiceNumber")
    public Boolean isUsedByInvoiceNumber(@RequestParam String invoiceNumber){
        Boolean data = ossService.isUsedByInvoiceNumber(invoiceNumber);
        return data;
    }


    /**
     * 用户选择资料库文件重新上传
     */
    @ApiOperation("用户选择资料库文件重新上传")
    @PostMapping("/downloadAndUploadToOSS")
    public String downloadAndUploadToOSS(@RequestBody DownToOssDTO downToOssDTO){
        String  filePath = ossClientService.downloadAndUploadToOSS(downToOssDTO.getUrl(),downToOssDTO.getFileName(),downToOssDTO.getDir());
        return filePath;
    }

    @RequestMapping(value = "/downBytesByStream", method = RequestMethod.POST)
    public  byte[] downBytesByStream(String key, String fileName){
        return     ossClientService.downBytesByStream(key, fileName);
    }



    /**
     * 根据ids查询附件信息（list）
     * @return
     */
    @PostMapping("getByAttachmentIdListAndFlag")
    public List<WorkAttachmentInfo> getByAttachmentIdListAndFlag(@RequestParam List<String> ids){
        return ossService.getByAttachmentIdListAndFlag(ids);
    }
}
