package com.jeeplus.human.depart.handover.service;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.flowable.feign.IFinanceApi;
import com.jeeplus.flowable.feign.IFlowableApi;
import com.jeeplus.human.depart.handover.domain.*;
import com.jeeplus.human.depart.handover.mapper.HandoverMapper;
import com.jeeplus.human.enrollment.enrollmentRegistration.utils.HunamFreemarkerUtil;
import com.jeeplus.human.signature.entity.*;
import com.jeeplus.human.signature.utils.*;
import com.jeeplus.sys.domain.WorkAttachmentInfo;
import com.jeeplus.sys.feign.IPostApi;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.feign.IWorkAttachmentApi;
import com.jeeplus.sys.service.dto.PostDTO;
import com.jeeplus.sys.service.dto.UserDTO;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
import org.apache.pdfbox.util.Matrix;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.util.*;

/**
 * @author 王强
 * @version 1.0
 * @date 2023-10-27 9:04
 */
@Service
@Transactional
public class HandoverService extends ServiceImpl<HandoverMapper, Handover> {

    private static final String HTTPTOP = Global.getConfig("signature_http_top");

    /**
     * 离职盖章流程id
     */
    private static String DIMISSIONID  = Global.getConfig("dimission_id");


    private static final String DIRECTORY  = Global.getConfig("directory");

    /**
     * 会计公司印章
     */
    private static String COMPANYROUNDSEALFINANCEID  = Global.getConfig("company_round_seal_finance_id");

    /**
     * 评估公司印章
     */
    private static String COMPANYROUNDSEALASSESSID  = Global.getConfig("company_round_seal_assess_id");

    @Resource
    private HandoverMapper mapper;

    @Resource
    private HandoverDraftService draftService;

    @Resource
    private HandoverComputerService handoverComputerService;

    @Resource
    private HandoverAccountsService handoverAccountsService;

    @Resource
    private HandoverSocialSecurityService handoverSocialSecurityService;

    @Resource
    private HandoverImprestService handoverImprestService;

    public void deleteByRegistrationId(String id){
        QueryWrapper<Handover> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("registration_id",id);
        mapper.delete(queryWrapper);
    }

    public void updateStatusById(Handover dto) {
        mapper.updateStatusById(dto.getId(), dto.getType());
    }

    public Handover findById(String id) {
        // 查询基础信息表
        Handover info = mapper.getById(id);
        return info;
    }

    public Handover saveRegistration(Handover handover) throws Exception {
        if (StringUtils.isNotEmpty(handover.getId())){

            Handover report = mapper.getById(handover.getId());
            handover.setCreateById(report.getCreateById());
            if (report != null){
                return update(handover);
            }
        }
        return add(handover);
    }

    /**
     * 修改
     */
    @Transactional(rollbackFor = Exception.class)
    public Handover update(Handover reportData) throws Exception{
        //获取当前登录人信息
        UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken ( ));

        Handover report = new Handover();
        BeanUtils.copyProperties(reportData, report);
        report.setUpdateById(userDTO.getId());
        report.setUpdateTime(new Date());
        mapper.updateById(report);

        if (report.getType().equals("5")){

            //发起底稿归档检查流程
            Map map = SpringUtil.getBean(IFlowableApi.class).getByNameForFen("底稿归档检查");
            String procDefId = map.get("id")+"";
            HandoverDraft draft = new HandoverDraft();
            String uid = UUID.randomUUID().toString().replace("-", "");
            draft.setId(uid);
            draft.setCreateById(report.getCreateById());
            draft.setUpdateById(report.getUpdateById());
            draft.setProcessDefinitionId(procDefId);
            draft.setHandoverId(report.getId());
            draftService.save(draft);

            Map<String ,Map<String,String >>  allMap = new HashMap<>();

            String procDefKey = map.get("key")+"";
            String businessTable = "human_resources_depart_handover_draft";
            String businessId = uid;
            String title = report.getName() + "-离职申请-底稿归档检查";
            String assignee = report.getDraftAdministrator();
            String recordType = "";
            String userId = report.getCreateById();
            Map<String, String> newMap = pingMap(procDefId, procDefKey, businessTable, businessId, title, assignee, recordType, userId);

            allMap.put("底稿",newMap);

//            SpringUtil.getBean(IFlowableApi.class).startForFenNew(allMap);

            //发起电脑欠款回收流程
            Map computerMap = SpringUtil.getBean(IFlowableApi.class).getByNameForFen("电脑欠款回收");
            String computerProcDefId = computerMap.get("id")+"";
            HandoverComputer computer = new HandoverComputer();
            String computerId = UUID.randomUUID().toString().replace("-", "");
            computer.setId(computerId);
            computer.setCreateById(report.getCreateById());
            computer.setUpdateById(report.getUpdateById());
            computer.setProcessDefinitionId(computerProcDefId);
            computer.setHandoverId(report.getId());
            handoverComputerService.save(computer);

            String computerProcDefKey = computerMap.get("key")+"";
            String computerBusinessTable = "human_resources_depart_handover_computer";
            String computerBusinessId = computerId;
            String computerTitle = report.getName() + "的离职申请 - 电脑欠款回收";
            //根据角色查用户信息
            PostDTO computerRoleInfo = SpringUtil.getBean(IPostApi.class).getPostDTOByName("电脑款项审查员");
            String computerAssignee = getAssignee(computerRoleInfo.getId());

            String computerRecordType = "";
            Map<String, String> computerNewMap = pingMap(computerProcDefId, computerProcDefKey,
                    computerBusinessTable, computerBusinessId, computerTitle, computerAssignee, computerRecordType,userId);

            allMap.put("电脑",computerNewMap);

//            SpringUtil.getBean(IFlowableApi.class).startForFenNew(allMap);

            //应收账款流程发起
            Map accountsMap = SpringUtil.getBean(IFlowableApi.class).getByNameForFen("应收账款检查");
            String accountsProcDefId = accountsMap.get("id")+"";
            HandoverAccounts accounts = new HandoverAccounts();
            String accountsId = UUID.randomUUID().toString().replace("-", "");
            accounts.setId(accountsId);
            accounts.setCreateById(report.getCreateById());
            accounts.setUpdateById(report.getUpdateById());
            accounts.setProcessDefinitionId(accountsProcDefId);
            accounts.setHandoverId(report.getId());
            handoverAccountsService.save(accounts);

            String accountsProcDefKey = accountsMap.get("key")+"";
            String accountsBusinessTable = "human_resources_depart_handover_accounts";
            String accountsBusinessId = accountsId;
            String accountsTitle = report.getName() + "的离职申请 - 应收账款检查";
            //根据角色查用户信息
            PostDTO accountsRoleInfo = SpringUtil.getBean(IPostApi.class).getPostDTOByName("应收账款审查员");

            String accountsAssignee = getAssignee(accountsRoleInfo.getId());

            String accountsRecordType = "";
            Map<String, String> accountsNewMap = pingMap(accountsProcDefId, accountsProcDefKey,
                    accountsBusinessTable, accountsBusinessId, accountsTitle, accountsAssignee, accountsRecordType,userId);

            allMap.put("应收账款",accountsNewMap);
//            SpringUtil.getBean(IFlowableApi.class).startForFenNew(allMap);

            //社保款项检查流程发起
            Map socialSecurityMap = SpringUtil.getBean(IFlowableApi.class).getByNameForFen("社保款项检查");
            String socialSecurityProcDefId = socialSecurityMap.get("id")+"";
            HandoverSocialSecurity socialSecurity = new HandoverSocialSecurity();
            String socialSecurityId = UUID.randomUUID().toString().replace("-", "");
            socialSecurity.setId(socialSecurityId);
            socialSecurity.setCreateById(report.getCreateById());
            socialSecurity.setUpdateById(report.getUpdateById());
            socialSecurity.setProcessDefinitionId(socialSecurityProcDefId);
            socialSecurity.setHandoverId(report.getId());
            handoverSocialSecurityService.save(socialSecurity);

            String socialSecurityProcDefKey = socialSecurityMap.get("key")+"";
            String socialSecurityBusinessTable = "human_resources_depart_handover_social_security";
            String socialSecurityBusinessId = socialSecurityId;
            String socialSecurityTitle = report.getName() + "的离职申请 - 社保款项检查";
            //根据角色查用户信息
            PostDTO socialSecurityRoleInfo = SpringUtil.getBean(IPostApi.class).getPostDTOByName("社保欠款审查员");

            String socialSecurityAssignee = getAssignee(socialSecurityRoleInfo.getId());

            String socialSecurityRecordType = "";
            Map<String, String> socialSecurityNewMap = pingMap(socialSecurityProcDefId, socialSecurityProcDefKey,
                    socialSecurityBusinessTable, socialSecurityBusinessId, socialSecurityTitle, socialSecurityAssignee, socialSecurityRecordType,userId);

            allMap.put("社保欠款",socialSecurityNewMap);

//            SpringUtil.getBean(IFlowableApi.class).startForFenNew(allMap);

            //发起备用金检查流程  handoverImprestService
            Map handoverImprestMap = SpringUtil.getBean(IFlowableApi.class).getByNameForFen("备用金检查");
            String handoverImprestProcDefId = handoverImprestMap.get("id")+"";
            HandoverImprest handoverImprest = new HandoverImprest();
            String handoverImprestId = UUID.randomUUID().toString().replace("-", "");
            handoverImprest.setId(handoverImprestId);
            handoverImprest.setCreateById(report.getCreateById());
            handoverImprest.setUpdateById(report.getUpdateById());
            handoverImprest.setProcessDefinitionId(handoverImprestProcDefId);
            handoverImprest.setHandoverId(report.getId());
            handoverImprestService.save(handoverImprest);

            String handoverImprestProcDefKey = handoverImprestMap.get("key")+"";
            String handoverImprestBusinessTable = "human_resources_depart_handover_imprest";
            String handoverImprestBusinessId = handoverImprestId;
            String handoverImprestTitle = report.getName() + "的离职申请 - 备用金检查";
            //根据角色查用户信息
            PostDTO postInfo = SpringUtil.getBean(IPostApi.class).getPostDTOByName("备用金审查员");
            String handoverImprestAssignee = getAssignee(postInfo.getId());

            String handoverImprestRecordType = "";
            Map<String, String> handoverImprestNewMap = pingMap(handoverImprestProcDefId, handoverImprestProcDefKey,
                    handoverImprestBusinessTable, handoverImprestBusinessId, handoverImprestTitle, handoverImprestAssignee, handoverImprestRecordType,userId);

            allMap.put("备用金",handoverImprestNewMap);

            draft.setType("2");
            draftService.saveOrUpdate(draft);
            computer.setType("2");
            handoverComputerService.saveOrUpdate(computer);
            accounts.setType("2");
            handoverAccountsService.saveOrUpdate(accounts);
            socialSecurity.setType("2");
            handoverSocialSecurityService.saveOrUpdate(socialSecurity);
            handoverImprest.setType("2");
            handoverImprestService.saveOrUpdate(handoverImprest);

            //将交接人添加到离职人员所有项目的项目组中
            //查出所有的项目id
            List<String> ids = SpringUtil.getBean(IFinanceApi.class).getCwProjectData(report.getCreateById());

            ids.forEach(id->{
                //根据id查出项目组成员信息
                List<String> membersIdList = SpringUtil.getBean(IFinanceApi.class).getMembersId(id);
                if (!membersIdList.contains(report.getProjectManager())) {
                    //将这个项目经理加入到项目组成员中
                    SpringUtil.getBean(IFinanceApi.class).insertMembers(id,report.getProjectManager(),userDTO.getId());
                }
            });

            SpringUtil.getBean(IFlowableApi.class).startForFenNew(allMap);


        }

        return report;
    }



    public String getAssignee(String roleId){
        List<UserDTO> userDTOS = SpringUtil.getBean(IUserApi.class).findListFlowAbleByPostId(roleId);
        StringJoiner idJoiner = new StringJoiner(",");
        for (UserDTO user : userDTOS) {
            idJoiner.add(String.valueOf(user.getId()));
        }

        return idJoiner.toString();
    }

    public Map<String,String> pingMap(String procDefId,String procDefKey,String businessTable,
                                      String businessId,String title,String assignee,String recordType,String userId){
        Map<String,String> map = new HashMap();
        map.put("procDefId", procDefId);
        map.put("procDefKey", procDefKey);
        map.put("businessTable", businessTable);
        map.put("businessId", businessId);
        map.put("title", title);
        map.put("assignee", assignee);
        map.put("recordType", recordType);
        map.put("userId", userId);
        return map;
    }


    /**
     * 新增
     */
    @Transactional(rollbackFor = Exception.class)
    public Handover add(Handover reportData) throws Exception{

        UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken ( ));

        Handover report = new Handover();
        BeanUtils.copyProperties(reportData, report);
        report.setCreateById(userDTO.getId());
        report.setCreateTime(new Date());
        report.setUpdateById(userDTO.getId());
        report.setUpdateTime(new Date());

        //设置底稿管理员

        PostDTO accountsRoleInfo = SpringUtil.getBean(IPostApi.class).getPostDTOByName("底稿管理员");
        String accountsAssignee = getAssignee(accountsRoleInfo.getId());
        report.setDraftAdministrator(accountsAssignee);

        mapper.insert(report);

        //根据freemarker模板生成离职证明XML文件
        String xmlFilePath = getXmlByFreeMarker(report.getId());
        report.setXmlFilePath(xmlFilePath);

//        String pdfFilePath = convertToPDF(report);
        //xml转word文档（不可复用）
        String wordPath = convertToWord(report);
//        report.setPdfFilePath(pdfFilePath);
        report.setWordFilePath(wordPath);

        //根据当前登录人隶属公司，判定是否进行签章 目前仅支持：会计公司、评估公司员工进行离职操作
        if("10003".equals(userDTO.getTenantDTO().getId()) || "10001".equals(userDTO.getTenantDTO().getId())){
            uploadDimissionProveFile(wordPath,report,userDTO);
            report.setSignatureFlag("0");
        } else{
            //对离职证明进行盖章操作
            Map<String, Object> signatureContractIdMap = createSignatureContractId(wordPath, userDTO);
            boolean success = (boolean) signatureContractIdMap.get("success");
            if(success){
                report.setSignatureContractId(signatureContractIdMap.get("contractId").toString());
                report.setSignatureFlag("1");
            }else{
                uploadDimissionProveFile(wordPath,report,userDTO);
                report.setSignatureFlag("0");
            }
        }



        mapper.updateById(report);
        return report;
    }

    /**
     * 上传离职证明文件
     * @param wordPath
     * @param report
     * @param userDTO
     * @return
     * @throws Exception
     */
    private void uploadDimissionProveFile(String wordPath,Handover report, UserDTO userDTO) throws Exception{
        //将未盖章的文件进行上传到oss中，并进行标记（）
        File file = new File(wordPath);
        String filepath = "";
        //取得上传文件
        //将文件上传到oss云盘中
        MultipartFile cMultiFile = new MockMultipartFile("file", file.getName(), null, new FileInputStream(file));
        if (!cMultiFile.isEmpty()) {
            // 文件保存路径
            String realPath =DIRECTORY.replace("/","")+"/human_dimission_file"+SpringUtil.getBean ( IWorkAttachmentApi.class ).datePath()+"/"+ System.currentTimeMillis();
            //文件原名称
            String newName = cMultiFile.getOriginalFilename();
            if(StringUtils.isNotBlank(newName)){
                SpringUtil.getBean ( IWorkAttachmentApi.class ).uploadFileSignatureOSS(file.getPath(),realPath,newName);
                filepath = "/" + realPath + newName;
            }
        }
        //截取文件后缀名
        String substring = file.getName().substring(file.getName().lastIndexOf(".")+1, file.getName().length());

        String newFileName = file.getName();
        //将签章完成的附件进行保存到附件表中
        WorkAttachmentInfo workattachment = new WorkAttachmentInfo();
        workattachment.setDelFlag(0);
        workattachment.setUrl(filepath);
        workattachment.setType(substring);
        workattachment.setAttachmentName(newFileName);
        workattachment.setAttachmentFlag("dimission_file_signature");
        workattachment.setFileSize(String.valueOf(file.length()));
        workattachment.setAttachmentId(report.getId());
        workattachment.setAttachmentType("");
        String id = UUID.randomUUID().toString().replace("-", "");
        workattachment.setId(id);
        workattachment.setCreateTime(new Date());
        workattachment.setUpdateTime(new Date());
        //先查询数据库中是否已经对数据进行保存
        //若未保存，则进行保存，否则直接跳过
        List<WorkAttachmentInfo> byAttachmentIdAndUrl = SpringUtil.getBean ( IWorkAttachmentApi.class ).selectListByAttachmentId(workattachment.getAttachmentId());
        if(byAttachmentIdAndUrl.size() == 0){
            Map<String,String> map = new HashMap<>();
            String workAttachment = JSON.toJSONString((workattachment));
            String userDTOInfo = JSON.toJSONString((userDTO));
            map.put("workAttachment",workAttachment);
            map.put("userDTO",userDTOInfo);
            SpringUtil.getBean ( IWorkAttachmentApi.class ).insertWorkAttachment(map);
        }else{
            SpringUtil.getBean ( IWorkAttachmentApi.class ).deleteByAttachmentId(report.getId());
            Map<String,String> map = new HashMap<>();
            String workAttachment = JSON.toJSONString((workattachment));
            String userDTOInfo = JSON.toJSONString((userDTO));
            map.put("workAttachment",workAttachment);
            map.put("userDTO",userDTOInfo);
            SpringUtil.getBean ( IWorkAttachmentApi.class ).insertWorkAttachment(map);
        }
    }

    /**
     * 生成并保存签章contractId 信息
     * @param filePath 临时文件路径（需盖章文件）
     * @return
     */
    public Map<String,Object> createSignatureContractId(String filePath, UserDTO userDTO){
        Map<String,Object> map = new HashMap<String,Object>();

        //获取文件生成的documentId
        List<String> documentList = Lists.newArrayList();

        try{
            //将下载下来的文件转换为file文件
            File srcFile = new File(filePath);
            //截取文件后缀名
            String substring = srcFile.getName().substring(srcFile.getName().lastIndexOf(".")+1, srcFile.getName().length());
            if(!"doc".equals(substring.toLowerCase()) && !"docx".equals(substring.toLowerCase()) && !"pdf".equals(substring.toLowerCase())){
                map.put("success",false);
                map.put("message","请上传doc、docx或者pdf的文件进行签章操作");
                return map;
            }
            //获取真签单的documentId
            HashMap hashMap = new SignaturePostUtil().getDocument(srcFile);
            String code = hashMap.get("code").toString();
            String documentId = "";
            if("0".equals(code)){
                String result = hashMap.get("result").toString();
                HashMap documentIdMap = JSON.parseObject(result, HashMap.class);
                documentId =  documentIdMap.get("documentId").toString();
                if("".equals(documentId)){
                    map.put("success",false);
                    map.put("message","离职证明文件创建失败");
                    return map;
                }
            }else{
                String message = hashMap.get("message").toString();
                map.put("success",false);
                map.put("message",message);
                return map;
            }

            documentList.add(documentId);

        }catch (Exception e){

        }finally {
            if(StringUtils.isNotBlank(filePath)){
                //根据路径创建文件对象
                File file = new File(filePath);
                //路径是个文件且不为空时删除文件
                if(file.isFile()&&file.exists()){
                    file.delete();
                }
            }
        }

        //根据项目id 和 documentId生成合同id
        HashMap contractIdHashMap = this.getSignatureContractIdByPageSign(documentList, userDTO);
        String contractIdCode = contractIdHashMap.get("code").toString();
        String contractId = "";
        if("0".equals(contractIdCode)){
            contractId = contractIdHashMap.get("contractId").toString();
            map.put("contractId",contractId);
            if("".equals(contractId)){
                map.put("success",false);
                map.put("message","签章文件创建失败");
                return map;
            }

        }else{
            map.put("success",false);
            map.put("message",contractIdHashMap.get("message").toString());
            return map;
        }

        map.put("success",true);
        map.put("message","生成签章contractId成功");
        return map;
    }

    /**
     * 根据项目报告id 和 documentId生成合同id(页面签署生成)
     * 个人签字章功能
     * @param documentList
     * @return
     */
    public HashMap getSignatureContractIdByPageSign( List<String> documentList, UserDTO userDTO){

        HashMap hashMap = new HashMap();
        Set<String> serialIdSet = new HashSet<>();
        //创建签署方信息
        List<Action> actions = Lists.newArrayList();
        Action companyAction = new Action();
        companyAction.setType("CORPORATE");
        companyAction.setName("公司印章");
        companyAction.setSerialNo("1");
        //添加盖章位置
        List<Location> locations = Lists.newArrayList();
        Location location = new Location();
        location.setDocumentId(documentList.get(0));

        if("10003".equals(userDTO.getTenantDTO().getId())){ //会计公司
            location.setSealId(COMPANYROUNDSEALFINANCEID);
        }else if("10001".equals(userDTO.getTenantDTO().getId())) {
            location.setSealId(COMPANYROUNDSEALASSESSID); //评估公司
        }

        location.setRectType("SEAL_CORPORATE");
        location.setKeyword("单位盖章");
        location.setKeywordIndex(1);
        locations.add(location);

        List<String> serialIdList = new ArrayList<String>(serialIdSet);
        companyAction.setSealIds("[" + String.join(",", serialIdList) + "]");
        //判定该action是否采用自动签署
        companyAction.setAutoSign("true");
        companyAction.setLocations(locations);
        actions.add(companyAction);
        //创建签署方信息表
        List<SignatorieInfo> signatories = Lists.newArrayList();
        SignatorieInfo signatorieInfo1 = new SignatorieInfo();
        signatorieInfo1.setSerialNo("1");
        signatorieInfo1.setTenantName("江苏兴光项目管理有限公司");
        signatorieInfo1.setTenantType("COMPANY");
        signatorieInfo1.setActions(actions);
        signatories.add(signatorieInfo1);
        SignatureContract signatureContract = new SignatureContract();
        signatureContract.setDocuments(documentList);
        //离职证明用印流程id
        signatureContract.setCategoryId(DIMISSIONID);
        signatureContract.setSend(true);
        signatureContract.setSignatories(signatories);
        signatureContract.setSn("");
        signatureContract.setSubject("" + "离职证明");//添加项目名称
        net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(signatureContract);
        System.out.println(json.toString());
        long s5=System.currentTimeMillis();
        System.out.println(json.toString());
        String contractIdMapStr = SignaturePostUtil.sendPostApplicationJson(HTTPTOP + "/contract/createbycategory", json.toString());
        long s6=System.currentTimeMillis();
        System.out.println("获取合同id获取时间：" + (s6 - s5));
        hashMap = JSON.parseObject(contractIdMapStr, HashMap.class);

        return hashMap;
    }


    /**
     * 根据id获取离职用户信息
     * @param handoverId
     * @return
     */
    public Handover getUserInfoById(String handoverId) {
        return mapper.getUserInfoById(handoverId);
    }


    public String getXmlByFreeMarker(String handoverId){

        //根据离职交接表id查询出  离职的员工名称，到岗日期，申请的预定离职日期，
        Handover handover = mapper.getUserInfoById(handoverId);

        Map data = new HashMap();
        data.put("userName",handover.getName());
        String arrivalDate = handover.getArrivalDate();
        String departResignationDate = handover.getDepartResignationDate();
        String[] departParts = departResignationDate.split("\\s+");
        String departTime = departParts[0]; // 日期部分
        String[] departDatePart = departParts[0].split("-"); // 日期部分

        // 根据空格分割日期和时间
        String[] parts = arrivalDate.split("\\s+");
        String arrivalTime = parts[0]; // 日期部分
        String[] datePart = parts[0].split("-"); // 日期部分
        //拆分出年月日
        String year = datePart[0];
        String month = datePart[1];
        String day = datePart[2];

        //进入单位时间
        data.put("year",year);
        data.put("month",month);
        data.put("day",day);

        LocalDate currentDate = LocalDate.of(Integer.parseInt(departDatePart[0]), Integer.parseInt(departDatePart[1]), Integer.parseInt(departDatePart[2])).plusDays(1);
        int nextDayYear = currentDate.getYear(); // 加一天后的年份
        int nextDayMonth = currentDate.getMonthValue(); // 加一天后的月份
        int nextDay = currentDate.getDayOfMonth(); // 加一天后的天数

        data.put("year2",nextDayYear+"");
        data.put("month2",nextDayMonth+"");
        data.put("day2",nextDay+"");

        LocalDate nowDate = LocalDate.now(); // 获取当前日期

        int nowYear = nowDate.getYear(); // 当前年份
        int nowMonth = nowDate.getMonthValue(); // 当前月份
        int nowDay = nowDate.getDayOfMonth(); // 当前日期

        data.put("year3",nowYear+"");
        data.put("month3",nowMonth+"");
        data.put("day3",nowDay+"");

        data.put("completeDay",arrivalTime);
        data.put("completeDay2",departTime);

        //模板对象
        Template template=null;
        //下载文件地址
        String filePath = null;
        if(System.getProperty("os.name").toLowerCase().contains("win")){
            filePath = this.getClass().getResource("/").getPath()+"/freemarker";
        }else{
            filePath = "/mnt/project/cloud/freemarker";
        }
        //freemaker模板路径
        File path = new File(filePath);

        Configuration cfg = new Configuration();

        String fileName = handover.getName() + "离职证明";
        try {
            cfg.setDirectoryForTemplateLoading(path);
            //选择对应的ftl文件
            template = cfg.getTemplate("departProve.ftl","UTF-8");

            File docFile = new File(fileName);

            //本地保存文件地址
            String fileSavePath = null;
            if(System.getProperty("os.name").toLowerCase().contains("win")){
                fileSavePath = "D:/attachment-file/";
            }else{
                fileSavePath = "/attachment-file/";
            }

            HunamFreemarkerUtil.generateFile(data,template,docFile);

            File destinationFolder = new File(fileSavePath);
            Path targetPath = Paths.get(destinationFolder.getPath(), docFile.getName());
            Files.move(docFile.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING);

            return targetPath.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            if(System.getProperty("os.name").toLowerCase().contains("win")){
                //获取tomcat的路径
                String tomcatFilePath=System.getProperty("catalina.home");
                //删除tomcat目录下的处理后的文件信息
                File tomcatFile = new File(tomcatFilePath+"/bin/"+fileName);
                if (tomcatFile.isFile()) {
                    tomcatFile.delete();
                }
            }else{
                //删除目录下的处理后的文件信息
                File tomcatFile = new File("/mnt/project/cloud/"+fileName);
                if (tomcatFile.isFile()) {
                    tomcatFile.delete();
                }
            }
        }
        return "";
    }

    public static String convertToWord(Handover report) {
        try {
            String filePath = report.getXmlFilePath();
            // 解析 XML 文件
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File(filePath)); // 输入的 XML 文件

            // 生成 Word 文档
            XWPFDocument doc = new XWPFDocument();

            //本地保存文件地址
            String fileSavePath = null;
            if(System.getProperty("os.name").toLowerCase().contains("win")){
                fileSavePath = "D:/attachment-file/";
            }else{
                fileSavePath = "/attachment-file/";
            }
            String fileSaveName = report.getName() + "离职证明.docx";
            FileOutputStream out = new FileOutputStream(fileSavePath + fileSaveName); // 输出的 Word 文件

            // 遍历 XML 文件内容并将其写入 Word 文档
            NodeList nodeList = document.getDocumentElement().getChildNodes();
            String textContent = "";
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element element = (Element) node;

                    // 获取 XML 元素的文本内容
                    textContent = element.getTextContent().replaceAll("\\s+", "");

                }
            }
            String[] paragraphs = null;
            List<String> valueLines = new ArrayList<>();
            if (StringUtils.isNotBlank(textContent)) {

                // 使用句号分割文本
                paragraphs = textContent.split("。");

            }
            if (null != paragraphs && paragraphs.length>0) {
                String firstLine = paragraphs[0].substring(0,paragraphs[0].indexOf("劳动合同的证明"));
                valueLines.add(firstLine);
                valueLines.add("劳动合同的证明");
                String threeLine = paragraphs[0].substring(paragraphs[0].indexOf("劳动合同的证明")+7) + "。" + paragraphs[1] + "。";
                valueLines.add(threeLine);
                String sevenLine = paragraphs[2] + "。";
                valueLines.add(sevenLine);
                String eightLine = paragraphs[3].substring(0,paragraphs[3].indexOf("章")+1);
                valueLines.add(eightLine);
                String nineLine = paragraphs[3].substring(paragraphs[3].indexOf("章")+1);
                valueLines.add(nineLine);
            }
            paragraphs = valueLines.toArray(new String[0]);
            if (null != paragraphs && paragraphs.length>0) {
                for (int i = 0; i < paragraphs.length; i++) {

                    // 当 i 等于 0 时设置特定样式
                    if (i == 0 || i == 1) {
                        if (i == 0) {
                            // 创建空段落
                            XWPFParagraph paragraph1 = doc.createParagraph();
                            XWPFRun run1 = paragraph1.createRun();
                            run1.setText("\u200B");
                            run1.setFontSize(14); // 三号字体
                            run1.setFontFamily("宋体"); // 黑体字体
                        }

                        // 创建段落
                        XWPFParagraph paragraph = doc.createParagraph();
                        XWPFRun run = paragraph.createRun();

                        // 将 XML 元素的文本内容写入 Word 文档
                        run.setText(paragraphs[i]);

                        run.setFontSize(18); // 小二
                        run.setBold(true); // 加粗
                        run.setFontFamily("黑体"); // 黑体字体
                        // 设置段落对齐方式为居中
                        paragraph.setAlignment(ParagraphAlignment.CENTER);
                        // 设置行距为单倍行距（240）
                        paragraph.setSpacingBetween(1d, LineSpacingRule.AUTO);
                    }
                    if (i==2){
                        // 创建空段落
                        XWPFParagraph paragraph1 = doc.createParagraph();
                        XWPFRun run1 = paragraph1.createRun();
                        run1.setText("\u200B");
                        run1.setFontSize(16); // 三号字体
                        run1.setFontFamily("黑体"); // 黑体字体

                        // 创建段落
                        XWPFParagraph paragraph = doc.createParagraph();
                        XWPFRun run = paragraph.createRun();

                        // 将 XML 元素的文本内容写入 Word 文档
//                        run.setText(paragraphs[i]);

                        run.setFontSize(14); // 四号字体
                        run.setFontFamily("宋体"); // 黑体字体
                        // 设置行距为32磅固定值
                        paragraph.setSpacingBetween(32, LineSpacingRule.EXACT);
                        // 设置首行缩进两个字符
                        paragraph.setIndentationFirstLine(600);

                        String text = paragraphs[i];
                        // 找到日期范围的起始和结束位置
                        int startIndex = text.indexOf("合同为")+3;
                        int endIndex = text.indexOf("。现因个人原因");

                        int startIndex2 = text.indexOf("，自") + 2;
                        int endIndex2 = text.indexOf("起与");
                        if (startIndex != -1 && endIndex != -1) {
                            // 在日期范围内添加下划线
                            String beforeText = text.substring(0, startIndex);
                            String underlinedText = text.substring(startIndex, endIndex);
//                            String afterText = text.substring(endIndex);

                            String beforeText2 = text.substring(endIndex,startIndex2);
                            String underlinedText2 = text.substring(startIndex2, endIndex2);
                            String afterText2 = text.substring(endIndex2);

                            XWPFRun runBefore = paragraph.createRun();
                            runBefore.setFontSize(14); // 四号字体
                            runBefore.setFontFamily("宋体"); // 黑体字体
                            runBefore.setText(beforeText);

                            XWPFRun runUnderlined = paragraph.createRun();
                            runUnderlined.setText(underlinedText);
                            runUnderlined.setFontSize(14); // 四号字体
                            runUnderlined.setFontFamily("宋体"); // 宋体字体
                            runUnderlined.setUnderline(UnderlinePatterns.SINGLE);

                            XWPFRun runBefore2 = paragraph.createRun();
                            runBefore2.setFontSize(14); // 四号字体
                            runBefore2.setFontFamily("宋体"); // 黑体字体
                            runBefore2.setText(beforeText2);

                            XWPFRun runUnderlined2 = paragraph.createRun();
                            runUnderlined2.setText(underlinedText2);
                            runUnderlined2.setFontSize(14); // 四号字体
                            runUnderlined2.setFontFamily("宋体"); // 宋体字体
                            runUnderlined2.setUnderline(UnderlinePatterns.SINGLE);

                            XWPFRun runAfter = paragraph.createRun();
                            runAfter.setFontSize(14); // 四号字体
                            runAfter.setFontFamily("宋体"); // 黑体字体
                            runAfter.setText(afterText2);
                        } else {
                            // 如果没有找到指定的日期范围，直接将文本添加到文档中
                            run.setText(text);
                        }

                    }
                    if (i==3){
                        // 创建空段落
                        XWPFParagraph paragraph1 = doc.createParagraph();
                        XWPFRun run1 = paragraph1.createRun();
                        run1.setText("\u200B");
                        run1.setFontSize(14); // 四号字体
                        run1.setFontFamily("宋体"); // 黑体字体

                        // 创建段落
                        XWPFParagraph paragraph = doc.createParagraph();
                        XWPFRun run = paragraph.createRun();

                        // 将 XML 元素的文本内容写入 Word 文档
                        run.setText(paragraphs[i]);

                        run.setFontSize(14); // 四号字体
                        run.setFontFamily("宋体"); // 黑体字体
                        // 设置行距为32磅固定值
                        paragraph.setSpacingBetween(32, LineSpacingRule.EXACT);
                        // 设置首行缩进两个字符
                        paragraph.setIndentationFirstLine(600);
                    }
                    if (i==4){
                        // 创建空段落
                        XWPFParagraph paragraph1 = doc.createParagraph();
                        XWPFRun run1 = paragraph1.createRun();
                        run1.setText("\u200B");
                        run1.setFontSize(14); // 四号字体
                        run1.setFontFamily("仿宋"); // 黑体字体

                        // 创建空段落
                        XWPFParagraph paragraph2 = doc.createParagraph();
                        XWPFRun run2 = paragraph2.createRun();
                        run2.setText("\u200B");
                        run2.setFontSize(14); // 四号字体
                        run2.setFontFamily("仿宋"); // 黑体字体

                        // 创建段落
                        XWPFParagraph paragraph = doc.createParagraph();
                        XWPFRun run = paragraph.createRun();

                        // 将 XML 元素的文本内容写入 Word 文档
                        run.setText(paragraphs[i]);

                        run.setFontSize(14); // 四号字体
                        run.setFontFamily("仿宋"); // 黑体字体
                        // 设置行距为25磅固定值
                        paragraph.setSpacingBetween(25, LineSpacingRule.EXACT);
                        // 设置首行缩进19个字符的宽度
                        paragraph.setIndentationFirstLine(4800);
                    }
                    if (i == 5) {

                        // 创建段落
                        XWPFParagraph paragraph = doc.createParagraph();
                        XWPFRun run = paragraph.createRun();

                        // 将 XML 元素的文本内容写入 Word 文档
                        run.setText(paragraphs[i]);

                        run.setFontSize(14); // 四号字体
                        run.setFontFamily("仿宋"); // 黑体字体
                        // 设置行距为25磅固定值
                        paragraph.setSpacingBetween(25, LineSpacingRule.EXACT);
                        // 设置首行缩进19个字符的宽度
                        paragraph.setIndentationFirstLine(5400);
                    }
                }
            }

            // 将文档内容写入文件
            doc.write(out);
            out.close();
            doc.close();
            return fileSavePath + fileSaveName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    //生成pdf文件
    public String convertToPDF(Handover handover) {

//        Handover handover = mapper.getById(handoverId);

        Path inputFile = Paths.get(handover.getXmlFilePath());


        //本地保存文件地址
        String fileSavePath = null;
        if(System.getProperty("os.name").toLowerCase().contains("win")){
            fileSavePath = "D:/attachment-file/";
        }else{
            fileSavePath = "/attachment-file/";
        }

        fileSavePath = fileSavePath + handover.getName() +  "离职证明.pdf";

        Path outputFile = Paths.get(fileSavePath);

        try (PDDocument document = new PDDocument()) {
            // 设置页面大小（例如A4）和边距
            PDRectangle pageSize = PDRectangle.A4;
            PDPage page = new PDPage(pageSize);
            // 设置页边距
            page.setMediaBox(new PDRectangle(pageSize.getWidth(), pageSize.getHeight()));
            document.addPage(page);

            try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                renderXMLToPDF(inputFile, contentStream,document);
            }

            document.save(String.valueOf(outputFile));
            System.out.println("文件转换为 PDF 成功：" + outputFile);
            return fileSavePath;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     *读取XML内容，并解析，提取<w:t>标签里面的文本内容，目前所知并没有直接将 XML 标记转换为 PDF 样式的简单方法，字体样式等无法直接转为PDF
     * @param reader
     * @param builder
     * @return
     * @throws IOException
     * @throws SAXException
     */
    public static List<String> getValueList(BufferedReader reader, DocumentBuilder builder) throws IOException, SAXException {
        StringBuilder xmlContent = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {

            xmlContent.append(line);
        }
        // 解析XML内容
        Document xmlDoc = builder.parse(new InputSource(new StringReader(xmlContent.toString())));
        // 提取XML文档中的内容
        NodeList textNodes = xmlDoc.getElementsByTagName("w:t");
        StringBuilder extractedText = new StringBuilder();

        for (int i = 0; i < textNodes.getLength(); i++) {
            Node node = textNodes.item(i);
            extractedText.append(node.getTextContent()).append("\n");

        }

        String[] lines = extractedText.toString().split("\n"); // 按换行符分割文本
        return getList(lines,"为",4,"中华人民共和国劳动合同法",7);
    }

    /**
     * 根据条件及在xml中相关联的文本内容所占行数拼接获取word中每行的文本信息  即完整的一行文本<w:r>标签个数  默认0开始
     * @param lines
     * @param name1
     * @param num1
     * @param name2
     * @param num2
     * @return
     */
    public static List<String> getList (String[] lines,String name1,int num1,String name2,int num2){
        List<String> strings = new ArrayList<>();
        String test = "";
        int num = 0;
        for (int i=0;i<lines.length;i++){
            if (lines[i].equals(name1)){
                for (int j=0;j<=num1;j++){
                    if (j==0){
                        test += lines[i+j] + " ";
                    }else {
                        test += lines[i+j];
                    }

                }
//                test = lines[i] + " " + lines[i+1] + lines[i+2] + lines[i+3] + " " + lines[i+4];
                strings.add(test);
                test = "";
                num = i+num1;
            }else if (lines[i].contains(name2)){
                for (int j=0;j<=num2;j++){
                    test += lines[i+j];
                }
//                test = lines[i] + lines[i+1] + lines[i+2] + lines[i+3] + lines[i+4] + lines[i+5] + lines[i+6] + lines[i+7];
                strings.add(test);
                test = "";
                num = i+num2;
            }else if (num == 0){
                strings.add(lines[i]);
            } else if ( num != 0 & i>num){
                strings.add(lines[i]);
                num = 0;
            }
        }
        return strings;
    }

    /**
     * 将从XML文件中解析出来的文本信息，渲染到PDF中，并进行样式调整
     * @param document
     * @param strings
     * @param font
     * @param contentStream
     * @param yCoordinate
     * @param lineSpacing
     * @throws IOException
     */
    public static void contentStreamSet(PDDocument document, List<String> strings, PDType0Font font, PDPageContentStream contentStream, float yCoordinate, float lineSpacing) throws IOException {
        //用于文本居中显示
        PDPage page = document.getPage(0); // 获取第一页（索引从0开始）
        PDRectangle mediaBox = page.getMediaBox();
        float pageWidth = mediaBox.getWidth(); // 获取页面宽度

        // 手动绘制每一行文本到 PDF
        for (String currentLine : strings) {
            float textWidth = font.getStringWidth(currentLine) * 24 / 1000f;
            contentStream.setFont(font, 18);
            contentStream.setRenderingMode(RenderingMode.FILL);
            float startX = (pageWidth - textWidth) / 2;
            if (currentLine.contains("关于与")) {

                contentStream.setFont(font, 24);
                contentStream.setRenderingMode(RenderingMode.FILL_STROKE);
                //设置文本显示位置
                contentStream.setTextMatrix(Matrix.getTranslateInstance(startX, yCoordinate));
                contentStream.showText(currentLine);
                yCoordinate -= lineSpacing +10; // 换行显示第二个数据
            } else if (currentLine.contains("劳动合同的证明")){
                contentStream.setFont(font, 24);
                contentStream.setRenderingMode(RenderingMode.FILL_STROKE);
                contentStream.setTextMatrix(Matrix.getTranslateInstance(startX, yCoordinate));
                contentStream.showText(currentLine);
                yCoordinate -= lineSpacing + 20; // 换行显示第二个数据
            } else if (currentLine.contains("最后一期")){
                String indentedText = "    " + currentLine;
                contentStream.setTextMatrix(Matrix.getTranslateInstance(60, yCoordinate));
                contentStream.showText(indentedText);
                yCoordinate -= lineSpacing; // 换行显示第二个数据
            } else if (currentLine.contains("解除劳动合同")){
                contentStream.setTextMatrix(Matrix.getTranslateInstance(60, yCoordinate));
                contentStream.showText(currentLine);
                yCoordinate -= lineSpacing + 20; // 换行显示第二个数据
            } else if (currentLine.contains("仲裁委员会")){
                String indentedText = "    " + currentLine;
                contentStream.setTextMatrix(Matrix.getTranslateInstance(60, yCoordinate));
                contentStream.showText(indentedText);
                yCoordinate -= lineSpacing + 20; // 换行显示第二个数据
            } else if (currentLine.contains("单位盖章")){
                String indentedText = "                                " + currentLine;
                contentStream.setTextMatrix(Matrix.getTranslateInstance(60, yCoordinate));
                contentStream.showText(indentedText);
                yCoordinate -= lineSpacing + 10; // 换行显示第二个数据
            } else if (currentLine.equals(strings.get(strings.size()-1))){
                String indentedText = "                                    " + currentLine;
                contentStream.setTextMatrix(Matrix.getTranslateInstance(60, yCoordinate));
                contentStream.showText(indentedText);
                yCoordinate -= lineSpacing; // 换行显示第二个数据
            } else {
                contentStream.setTextMatrix(Matrix.getTranslateInstance(60, yCoordinate));
                contentStream.showText(currentLine);
                yCoordinate -= lineSpacing; // 换行显示第二个数据
            }
            contentStream.newLineAtOffset(0, -15);
        }
    }

    // XML解析
    private static void renderXMLToPDF(Path inputFile, PDPageContentStream contentStream, PDDocument document) throws IOException {
        try (BufferedReader reader = Files.newBufferedReader(inputFile, StandardCharsets.UTF_8)) {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();

            List<String> strings = getValueList(reader,builder);

            float lineSpacing = 25;  //行间距
            float yCoordinate = 800; // 起始y坐标

            contentStream.beginText();
            contentStream.newLineAtOffset(60, yCoordinate);

            String fileSavePath = null;
            if(System.getProperty("os.name").toLowerCase().contains("win")){
                fileSavePath = "C:/Windows/Fonts/";
            }else{
                fileSavePath = "/Library/Application Support/WPS Office/Fonts";
            }

            PDType0Font font = PDType0Font.load(document, new File(fileSavePath + "simfang.ttf"));

            contentStreamSet(document,strings,font,contentStream,yCoordinate,lineSpacing);

            contentStream.endText();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public Handover queryByContractId(String contractId){
        Handover reportData = mapper.queryByContractId(contractId);
        return reportData;
    }

    public void updateSignatureUrl(Handover handover){
        mapper.updateSignatureUrl(handover);
    }
}
