package nccloud.web.sscivm.ivsale.sale.action;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.net.URLEncoder;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import nc.bs.framework.common.NCLocator;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.processor.MapProcessor;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import com.yonyou.cloud.utils.StringUtils;

import nc.bs.trade.business.HYSuperDMO;
import nc.util.mmf.framework.base.MMValueCheck;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.sscivm.invoice.IVMInvoiceHeadVO;
import nc.vo.sscivm.ivsale.IVApplicationHeadVO;
import nc.vo.sscivm.ivsale.IVApplogVO;
import nccloud.framework.core.io.WebFile;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.itf.sscivm.ivsale.service.IVSaleQueryService;
import nccloud.pubitf.platform.attachment.IAttachmentService;
import java.io.ByteArrayOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class InvoiceDownloadAction implements ICommonAction {

    IAttachmentService ncservice = ServiceLocator.find(IAttachmentService.class);

    @Override
    public Object doAction(IRequest request) {
        Map<String, String[]> params_1 = request.readParameters();
        String[] pks = params_1.get("pk"); // 获取所有 pk
        String[] arrInvoiceTypes = params_1.get("arrInvoiceTypes");
        String isdoc = "z";
        WebFile file = null;

        try {
            // 创建内存中的 ZIP 输出流
            ByteArrayOutputStream zipOut = new ByteArrayOutputStream();
            ZipOutputStream zipStream = new ZipOutputStream(zipOut);
            String zipName = "";
            // 遍历所有 pk
            for (String pk : pks) {
                List<IVMInvoiceHeadVO> headVOList = ServiceLocator.find(IVSaleQueryService.class).queryIVMInvoiceHeadVOsByPks(new String[]{pk});
                IVMInvoiceHeadVO headVO = headVOList.get(0);

                // 获取旗舰版的token
                String appKey = "8c9eb1ea1ba54b3f9683a8b355f8e615";
                String appSecret = "999e15c2a13ee4eab480534be4bf52fdf9032a6d";
                String tokenUrl = "https://c2.yonyoucloud.com/iuap-api-auth/open-auth/selfAppAuth/getAccessToken";
                String getbsfileUrl = "https://c2.yonyoucloud.com/iuap-api-gateway/yonbip/tax/output-tax/api/einvoice/getbsfile?access_token=";

                Map<String, String> params = new HashMap<>();
                params.put("appKey", appKey);
                String timestamp = String.valueOf(System.currentTimeMillis());
                params.put("timestamp", timestamp);

                // 计算签名
                Map<String, String> treeMap = new TreeMap<>(params);
                StringBuilder stringBuilder = new StringBuilder();
                for (Map.Entry<String, String> entry : treeMap.entrySet()) {
                    stringBuilder.append(entry.getKey()).append(entry.getValue());
                }
                Mac mac = Mac.getInstance("HmacSHA256");
                mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
                byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
                String base64String = Base64.getEncoder().encodeToString(signData);
                String signature = URLEncoder.encode(base64String, "UTF-8");
                params.put("signature", signature);

                String responseString = doGet(tokenUrl, params);
                Gson gson = new Gson();
                Map result = gson.fromJson(responseString, Map.class);

                if (StringUtils.equals("00000", result.get("code").toString())) {
                    Map<String, Object> tokenInfo = (Map<String, Object>) result.get("data");
                    String access_token = (String) tokenInfo.get("access_token");

                    Map<String, Object> map = new HashMap<>();
                    map.put("fplx", headVO.getInvoice_type());
                    map.put("slfphm", headVO.getFphm());
                    map.put("yypdf", "0");
                    map.put("taxpdf", Arrays.asList(arrInvoiceTypes).contains("1") ? "1" : "0");
                    map.put("taxxml", Arrays.asList(arrInvoiceTypes).contains("2") ? "1" : "0");
                    map.put("taxofd", Arrays.asList(arrInvoiceTypes).contains("3") ? "1" : "0");

                    String resString = doPost(getbsfileUrl + access_token, map);
                    gson = new Gson();
                    Map resultMap = gson.fromJson(resString, Map.class);

                    if (StringUtils.equals("200", resultMap.get("code").toString())) {
                        Map<String, Object> infoMap = (Map<String, Object>) resultMap.get("data");
                        String pdfData = (String) infoMap.get("taxpdf");
                        String xmlData = (String) infoMap.get("taxxml");
                        String ofdData = (String) infoMap.get("taxofd");

                        if (MMValueCheck.isEmpty(pdfData) && MMValueCheck.isEmpty(xmlData) && MMValueCheck.isEmpty(ofdData)) {
//                            throw new Exception("未查询到发票信息");
                            continue;
                        }

                        String ctcode = "";
                        HYSuperDMO dmo = new HYSuperDMO();
                        IVApplogVO[] ivApplogVO = (IVApplogVO[]) dmo.queryByWhereClause(IVApplogVO.class, "fphm='" + headVO.getFphm() + "' and dr=0 ");
                        if (ivApplogVO != null && ivApplogVO.length > 0) {
                            IVApplicationHeadVO ivApplicationHeadVO = (IVApplicationHeadVO) dmo.queryByPrimaryKey(IVApplicationHeadVO.class, ivApplogVO[0].getLyid());
//							ctcode = ivApplicationHeadVO.getDef2(); // 合同号
                            String operationSql = "SELECT bd.NAME name  from bd_defdoc bd LEFT join bd_defdoclist bdl ON bd.pk_defdoclist=bdl.pk_defdoclist WHERE bdl.code ='zdy-001'\n" +
                                    "AND  bd.pk_defdoc =  '" + ivApplicationHeadVO.getDef2().toString()  + "' ";
//            List<Map<String,Object>> operationresult = (List<Map<String,Object>>) getQueryService().executeQuery(operationSql, new ArrayListProcessor());
                            Map<String, Object> valList = (Map<String, Object>) getQueryService().executeQuery(operationSql, new MapProcessor());
                            if(!valList.isEmpty()){
                                ctcode = (String) valList.get("name"); // 合同号
                            }else{
                                ctcode =ivApplicationHeadVO.getDef2();
                            }
                        }
                        if(!ctcode.equals("") && !ctcode.equals("/") ){
                            ctcode=ctcode+"_";
                        }
                        // 添加 PDF
                        if (!MMValueCheck.isEmpty(pdfData)) {
                            byte[] pdfBytes = DatatypeConverter.parseBase64Binary(pdfData);
                            zipStream.putNextEntry(new ZipEntry(ctcode + headVO.getGmfmc() + "_" + headVO.getFphm() + "_" + String.valueOf(headVO.getJshj().toDouble()) + ".pdf"));
                            zipStream.write(pdfBytes);
                            zipStream.closeEntry();
                        }

                        // 添加 XML
                        if (!MMValueCheck.isEmpty(xmlData)) {
                            byte[] xmlBytes = DatatypeConverter.parseBase64Binary(xmlData);
                            zipStream.putNextEntry(new ZipEntry(ctcode + headVO.getGmfmc() + "_" + headVO.getFphm() + "_" + String.valueOf(headVO.getJshj().toDouble()) + ".xml"));
                            zipStream.write(xmlBytes);
                            zipStream.closeEntry();
                        }

                        // 添加 OFD
                        if (!MMValueCheck.isEmpty(ofdData)) {
                            byte[] ofdBytes = DatatypeConverter.parseBase64Binary(ofdData);
                            zipStream.putNextEntry(new ZipEntry(ctcode +  headVO.getGmfmc() + "_" + headVO.getFphm() + "_" + String.valueOf(headVO.getJshj().toDouble()) + ".ofd"));
                            zipStream.write(ofdBytes);
                            zipStream.closeEntry();
                        }
                        zipName=ctcode + headVO.getGmfmc() + "_" + headVO.getFphm() + "_" + String.valueOf(headVO.getJshj().toDouble());
                    } else {
                        throw new Exception("获取发票信息失败");
                    }
                } else {
                    throw new Exception("获取access_token失败");
                }
            }

            zipStream.finish();
            zipStream.close();
            if(pks.length >  1){
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
                zipName = "发票下载_" + sdf.format(new Date());
            }
            // 构造 WebFile 返回 ZIP 文件
            InputStream ins = new ByteArrayInputStream(zipOut.toByteArray());
            file = new WebFile(zipName+".zip", ins);

        } catch (BusinessException e) {
            ExceptionUtils.wrappException(e);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return file;
    }


    private String doPost(String requestUrl, Map<String, Object> param) throws IOException {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(500);
        cm.setDefaultMaxPerRoute(50);

        RequestConfig globalConfig = RequestConfig.custom().setConnectionRequestTimeout(5000) // 连接池获取连接超时
                .setConnectTimeout(5000) // 连接建立超时
                .setSocketTimeout(20000) // 等待响应超时
                .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();

        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm)
                .setDefaultRequestConfig(globalConfig).build();
        HttpPost post = new HttpPost(requestUrl);
        post.setHeader("Content-Type", "application/json;charset=UTF-8");
        post.setEntity(new StringEntity(JSONObject.toJSONString(param), "utf-8"));
        String responseString = httpClient.execute(post, response -> EntityUtils.toString(response.getEntity()));
        return responseString;

    }


    private String doGet(String requestUrl, Map<String, String> paramMap) throws IOException {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(5000);
        cm.setDefaultMaxPerRoute(500);

        RequestConfig globalConfig = RequestConfig.custom().setConnectionRequestTimeout(50000) // 连接池获取连接超时
                .setConnectTimeout(50000) // 连接建立超时
                .setSocketTimeout(200000) // 等待响应超时
                .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();

        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm)
                .setDefaultRequestConfig(globalConfig).build();
        StringBuilder param = new StringBuilder("?");
        if (paramMap != null) {
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                param.append(entry.getKey());
                param.append("=");
                param.append(entry.getValue());
                param.append("&");
            }
            param.deleteCharAt(param.length() - 1);
        }
        String url = requestUrl + param;
        HttpGet get = new HttpGet(url);
        String responseString = httpClient.execute(get, response -> EntityUtils.toString(response.getEntity()));
        get.releaseConnection();
        return responseString;
    }
    public IUAPQueryBS getQueryService() {
        return NCLocator.getInstance().lookup(IUAPQueryBS.class);
    }

}
