package com.seeyon.apps.src_hxinvoice.node;


import cn.hutool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.collaboration.po.ColSummary;
import com.seeyon.apps.common.config.ICstConfigApi;
import com.seeyon.apps.common.plugin.vo.ConfigVo;
import com.seeyon.apps.common.workflow.constants.WorkFlowType;
import com.seeyon.apps.common.workflow.node.ACommonSuperNode;
import com.seeyon.apps.ext.workflow.vo.FieldDataVo;
import com.seeyon.apps.ext.workflow.vo.FormDataVo;
import com.seeyon.apps.ext.workflow.vo.SuperNodeContext;
import com.seeyon.apps.src_hxinvoice.constants.HxinvoiceConstants;
import com.seeyon.apps.src_hxinvoice.dao.IHxinvoiceDao;
import com.seeyon.apps.src_hxinvoice.util.*;
import com.seeyon.apps.src_hxinvoice.vo.HxinvoiceResponse;
import com.seeyon.cap4.form.api.FormDataApi4Cap4;
import com.seeyon.cap4.form.bean.FormDataMasterBean;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.SystemEnvironment;
import com.seeyon.ctp.common.po.filemanager.Attachment;
import com.seeyon.ctp.util.UUIDLong;
import com.seeyon.ctp.util.json.JSONUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 功能描述:<br>
 * <pre>
 *
 * </pre>
 *
 * @Author: HuangZhengguo
 * @Date: 2024/4/28
 */
public class OrderToFastRedInvoiceFileNode extends ACommonSuperNode {

    private static Log log = Log.get(OrderToFastRedInvoiceFileNode.class);

    public String getMethod() {
        return "/sims-api/invoice/api/v6/QueryFastRedInvoiceResult";
    }

    protected ICstConfigApi cstConfigApi = (ICstConfigApi) AppContext.getBean("cstConfigApi");

    @Override
    public String getNodeId() {
        return "OrderToFastRedInvoiceFileNode";
    }

    @Override
    public String getNodeName() {
        return "数电订单快捷冲红返回结果获取超级节点";
    }

    public ConfigVo getHxinvoiceConfig() {
        return cstConfigApi.getConfig(getPluginId());
    }

    @Override
    public String getPluginId() {
        return HxinvoiceConstants.getPluginId();
    }

    @Override
    public String getFormParse()  {
        return "json";
    }

    @Override
    public WorkFlowType[] getTypes()  {
        return new WorkFlowType[] {WorkFlowType.superNode};
    }

    protected FormDataApi4Cap4 formDataApi4Cap4;

    public void setFormDataApi4Cap4(FormDataApi4Cap4 formDataApi4Cap4) {
        this.formDataApi4Cap4 = formDataApi4Cap4;
    }

    private IHxinvoiceDao hxinvoiceDao;
    public void setHxinvoiceDao(IHxinvoiceDao hxinvoiceDao) {this.hxinvoiceDao = hxinvoiceDao;}
    public IHxinvoiceDao getHxinvoiceDao() {
        if (this.hxinvoiceDao == null) {this.hxinvoiceDao = ((IHxinvoiceDao) AppContext.getBean("hxinvoiceDao"));}return hxinvoiceDao;
    }

    @Override
    public SuperNodeContext proceed(String request, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) throws Exception {
        ConfigVo configVo = getHxinvoiceConfig();
        SuperNodeContext context = new SuperNodeContext();
        FileUtil fileUtil = new FileUtil();
        String localPath = SystemEnvironment.getApplicationFolder();
        try {
//    		secretKey
            String secretKey = configVo.getParamVal(HxinvoiceConstants.secretKey.name());
//    		secretId
            String secretId = configVo.getParamVal(HxinvoiceConstants.secretId.name());
//    		请求类型
            String requestType  = "POST";
//    		接口地址
            String ipport = configVo.getParamVal(HxinvoiceConstants.ipport.name());
//            获取冲红接口地址
            String url = ipport+getMethod();
            context.setUrl(url);
//    		设置自定义字段
            String dataExchangeId = UUIDLong.longUUID()+"";
            System.out.println("设置冲红基础参数");
//            ProtUtil protUtil = new ProtUtil();
            String password =secretKey.substring(0,24);
//    		压缩工具类
            GzipUtils gzipUtils = new GzipUtils();
//    		加解密工具类
            TripleDesUtil tripleDesUtil = new TripleDesUtil();
            ParamUtil paramUtil = new ParamUtil();
//            System.out.println("获取参数");
            log.info("处理前参数："+request);
            String contentParam =request;
            context.setRequest(contentParam);
            context.setNeedSave(true);
            byte[] src = contentParam.getBytes(StandardCharsets.UTF_8);
//    		判断是否需要加密
            String encryptCode = "1";//固定为1进行加密
            byte[] bys = {};
            if("1".equals(encryptCode)){
                //		进行加密
                bys = tripleDesUtil.encryptMode(password,src);
            }
//    		判断是否需要压缩
            String zipCode = "1";//固定为1进行压缩
            byte[] gzis = bys;
            if("1".equals(zipCode)){
                //		进行压缩
                gzis = gzipUtils.compress(bys);
            }
//            System.out.println("加密完成");
//    		进行baes64加密
            String base64Encoded = Base64.encodeBase64URLSafeString(gzis);
            log.info("base64Encoded:"+base64Encoded);
//    		设置签名参数
            TreeMap<String ,String> treeMap = new TreeMap<>();
            treeMap.put("content",base64Encoded);
            treeMap.put("dataExchangeId",dataExchangeId);
            treeMap.put("encryptCode",encryptCode);
            treeMap.put("secretId",secretId);
            treeMap.put("zipCode",zipCode);
            StringBuilder contentStr = new StringBuilder();

            for (String key : treeMap.keySet()) {
                contentStr.append(key+"="+treeMap.get(key)+"&");
            }
//            System.out.println("准备签名完成");
            String content = contentStr.toString();
            content = content.substring(0,content.length()-1);
            String[] urls = url.split("/");
            String uri = urls[0];
            String fuwu = "/" +urls[1];
            String path = "/"+urls[2]+"/"+urls[3]+"/";
            String banben = urls[4];
            String method = "/"+urls[5];
            String srcStr = requestType+uri+fuwu+path+banben+method+"?"+content;
//    		进行签名
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(keySpec);
            byte[] signBytes = mac.doFinal(srcStr.getBytes("UTF-8"));
//    		签名转换成字符串
            String signStr = Base64.encodeBase64URLSafeString(signBytes);
//            System.out.println("signStr:"+signStr);
//    		设置参数
            JSONObject jsonGenerateQdInvoice = new JSONObject();
            jsonGenerateQdInvoice.put("secretId",secretId);
            jsonGenerateQdInvoice.put("dataExchangeId",dataExchangeId);
            jsonGenerateQdInvoice.put("encryptCode",encryptCode);
            jsonGenerateQdInvoice.put("zipCode",zipCode);
            jsonGenerateQdInvoice.put("content",base64Encoded);
            jsonGenerateQdInvoice.put("signature",signStr);
//            System.out.println("准备调用");
//            JSONObject res = protUtil.doPost(jsonGenerateQdInvoice.toString(),"http://"+url);
            String response = HxinvoiceHttpUtil.doPost("http://"+url, jsonGenerateQdInvoice.toString());
//            System.out.println(response);
            JSONObject resjson = JSON.parseObject(response);
//            System.out.println("调用完成");
            String con = resjson.getString("content");
            byte[] decodedBytes = Base64.decodeBase64(con);
            String iszipCode = resjson.getString("zipCode");
            String isencryptCode = resjson.getString("encryptCode");
//            是否需要进行解压
            byte[] dec = decodedBytes;
            if("1".equals(iszipCode)){
                dec = gzipUtils.decompress(decodedBytes);
            }
//            是否需要进行解密
            byte[] d= dec;
            if("1".equals(isencryptCode)){
                d = tripleDesUtil.decryptMode(password,dec);
            }
            String str = new String(d,"UTF-8");
            context.setResponse(str);
            JSONObject object = JSONUtil.parseJSONString(str, JSONObject.class);
            HxinvoiceResponse hxinvoiceResponse = new HxinvoiceResponse(object,getMethod());
            if(hxinvoiceResponse.isSuccess()) {
                JSONObject ret = JSONObject.parseObject(str);
//                获取返回附件
                JSONObject HZFPXX = ret.getJSONObject("HZFPXX");
                JSONObject DDFPXX = HZFPXX.getJSONObject("DDFPXX");
                JSONArray FILEITEMLISTS = HZFPXX.getJSONArray("FILEITEMLIST");
                List<String> fileNames = new ArrayList<String>();
                log.info("进行文件处理");
                for(int n = 0 ; n < FILEITEMLISTS.size() ; n++){
                    JSONObject FILEITEMLIST = FILEITEMLISTS.getJSONObject(n);
//                获取后缀
                    String WJLX = FILEITEMLIST.getString("WJLX");
                    String FILECONTENT = FILEITEMLIST.getString("FILECONTENT");
//                bese64解密
                    byte[] fileBytes = Base64.decodeBase64(FILECONTENT);
                    try {
//                    判断文件路径是否存在
                        String DDQQLSH = DDFPXX.getString("DDQQLSH");
                        fileUtil.isFilePath(localPath+"/invoiceDate/CH_"+DDQQLSH);
                        String GMFMC = DDFPXX.getString("GMFMC");
                        String DDSJ = DDFPXX.getString("DDSJ");
                        String FPHM = DDFPXX.getString("FPHM");
                        String newKPRQStr = DDSJ.replace("-", "").replace(" ", "").replace(":", "");
                        String fileInvoiceName = "dzch_"+FPHM+"_"+GMFMC+"_"+newKPRQStr;
                        String fileName = localPath+"/invoiceDate/CH_"+DDQQLSH+"/"+fileInvoiceName+"."+WJLX;
                        log.info("将文件保存在指定地址"+fileName);
                        FileOutputStream fos = new FileOutputStream(fileName);
                        int bufferSize = 1024; // 每次写入的块大小为1KB
                        for (int t = 0; t < fileBytes.length; t += bufferSize) {
                            int length = Math.min(bufferSize, fileBytes.length - t);
                            fos.write(fileBytes, t, length);
                        }
                        fos.close();
                        fileNames.add(fileName);
                        log.info("保存文件成功");
                    } catch (IOException e) {
//                        System.out.println("保存文件时出错：" + e.getMessage());
                        log.info("保存文件时出错：" + e.getMessage());
                    }
                }
                ColSummary colSummary = formDataVo.getColSummary();
                long summaryId =  colSummary.getId();
//                附件上传到系统
                List<Attachment> attachments = fileUtil.fileUpload(fileNames,summaryId+"",AppContext.currentUserId(),AppContext.currentAccountId());
                log.info("调用方法上传附件成");
                String id = attachments.get(0).getSubReference()+"";
                log.info("上传附件ID为"+id);
//                设置返回信息
                formDataVo.getNewFieldDataMap().put("红字发票附件", id);
                String DDZT = DDFPXX.getString("DDZT");
                //  "030000","订单开票成功""031000","订单未开票""031999","订单开票失败""032000","订单开票中""032999","订单无效"
//                查询枚举想信息
                String stateEnumId = configVo.getParamVal(HxinvoiceConstants.stateEnumId.name());
                Map<String,String> stateEnum = hxinvoiceDao.getCtpEnumItemsByEnumId(stateEnumId);
                String DDZTXX = DDFPXX.getString("DDZTXX");
                Map<String ,String> map = new HashMap<>();
                switch(DDZT){
                    case "030000":
                        map.put("订单状态",stateEnum.get("订单开票成功"));
                        map.put("开票事项说明","开票成功："+DDZTXX);
                        break;
                    case "031000":
                        map.put("订单状态",stateEnum.get("订单未开票"));
                        map.put("开票事项说明","未开票："+DDZTXX);
                        break;
                    case "031999":
                        map.put("订单状态",stateEnum.get("订单开票失败"));
                        map.put("开票事项说明","开票失败："+DDZTXX);
                        break;
                    case "032000":
                        map.put("订单状态",stateEnum.get("订单开票中"));
                        map.put("开票事项说明","开票中："+DDZTXX);
                        break;
                    case "032999":
                        map.put("订单状态",stateEnum.get("订单无效"));
                        map.put("开票事项说明","无效："+DDZTXX);
                    break;
                }
                formDataVo.getNewFieldDataMap().put("订单状态",map.get("订单状态") );
                formDataVo.getNewFieldDataMap().put("订单状态描述", map.get("开票事项说明"));
                formDataVo.getNewFieldDataMap().put("电子税票系统返回结果", map.get("开票事项说明"));
//                context.setException(true);
                context.success("冲红结果查询成功:" +hxinvoiceResponse.getMsg(), false);
            }else{
                context.setErrMsg(hxinvoiceResponse.getMsg());
                context.setException(true);
                context.back("冲红结果查询失败：" +hxinvoiceResponse.getData()+ hxinvoiceResponse.getMsg());
            }
        }catch (Exception e) {
            e.printStackTrace();
            context.setException(true);
            context.back("冲红结果查询失败：OA处理异常：" + e.getMessage());
            return context;
        }
        return context;
    }
}
