package com.prolog.cs.biz.outbound.service.impl.print;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.prolog.cs.basic.common.model.print.PrintInfo;
import com.prolog.cs.basic.common.model.print.PrintParam;
import com.prolog.cs.basic.item.model.BaseMtlItemMst;
import com.prolog.cs.biz.outbound.dao.OmsDoBillDMapper;
import com.prolog.cs.biz.outbound.dao.OmsDoBillHMapper;
import com.prolog.cs.biz.outbound.dao.PickTaskDMapper;
import com.prolog.cs.biz.outbound.model.OmsDoBillHDO;
import com.prolog.cs.biz.outbound.model.PickTaskD;
import com.prolog.cs.biz.outbound.model.constant.DoPrintConstant;
import com.prolog.cs.biz.outbound.model.entity.OmsDoBillDDO;
import com.prolog.cs.biz.outbound.resource.CommonClient;
import com.prolog.cs.biz.outbound.resource.ItemClient;
import com.prolog.cs.biz.outbound.service.DoPringService;
import com.prolog.cs.biz.outbound.service.PrintLogService;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.restriction.FieldSelector;
import com.prolog.framework.utils.CollectionUtils;
import com.prolog.framework.utils.DateUtils;
import com.prolog.framework.utils.MapUtils;
import com.prolog.framework.utils.ObjectUtils;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Service
@Slf4j
public class DoPringServiceImpl implements DoPringService {

    @Resource
    private CommonClient commonClient;

    @Autowired
    private PickTaskDMapper pickTaskDMapper;

    @Autowired
    private OmsDoBillHMapper omsDoBillHMapper;

    @Autowired
    private OmsDoBillDMapper omsDoBillDMapper;

    @Autowired
    private ItemClient itemClient;
    @Autowired
    private PrintLogService printLogService;


    @Override
    public Object printNull(String warehouseId, String consignorId,String billId, String printBillCode) {
        PrintParam printParam = new PrintParam();
        printParam.setPrintBillCode(printBillCode);
        printParam.setParams(MapUtils.put("billId", billId).getMap());

        //printParamList.add(printParam);

        log.info("打印出库清单入参：{}", JSON.toJSONString(printParam));
        RestMessage<?> restMessage = commonClient.getPrintInfo(printParam);
        if(!restMessage.isSuccess()) {
            throw new RuntimeException("打印失败:" + restMessage.getMessage());
        }
        log.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessage));
        return restMessage;
    }

    /**
     * @Description  出库打印清单
     * Company: 湖北普罗格科技股份有限公司
     * @author chengxiang
     * @date 2023/10/26 10:56
     */

/*    @Override
    public void outDetailedPrint(String warehouseId, String consignorId, String billId, String printBillCode) {
        //List<PrintParam> printParamList = new ArrayList<>();

        PrintParam printParam = new PrintParam();
        printParam.setConsignorId(consignorId);
        printParam.setPrintBillCode(printBillCode);
        printParam.setWarehouseId(warehouseId);
        printParam.setParams(MapUtils.put("billId", billId).getMap());

        //printParamList.add(printParam);

        log.info("打印出库清单入参：{}", JSON.toJSONString(printParamList));
        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
        if(!restMessage.isSuccess()) {
            throw new RuntimeException("打印失败:" + restMessage.getMessage());
        }
        log.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessage));
    }*/



    @Override
    public Object outDetailedPrint(String warehouseId, String consignorId, String billId, String printBillCode) {
        //List<PrintParam> printParamList = new ArrayList<>();

        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("srcId", billId).getMap(), PickTaskD.class);
        if(pickTaskDList.isEmpty()) {
            throw new PrologException("当前订单未生成任务，没有打印数据");
        }
        /**
         * 1. 出库单在青牛系统下发至WMS时指定了打印方案【oms_do_bill_h.attr_str7】(
         *      目前是3种 分别为：1、通用版；2、折后单价版；3：商品分类版；4：牛币商品出库单版)
         *
         * 2. 在打印出库单时，需要取该字段区分打印那种方案，
         *      1为目前已有的模版。
         *      2在现有模版增加折后单价字段即可；
         *      3是根据订单中的所有商品分类汇总去打印，若有N种商品种类，则打印N张，模版为通用版，
         *      4为牛币商品出库版(模版待客户提供，)
         */

        /*OmsDoBillHDO byId = omsDoBillHMapper.findById(billId, OmsDoBillHDO.class);
        String flag = "";
        if (ObjectUtils.isNotNull(byId)) {
            flag = byId.getAttrStr7();
        }
        if ("2".equals(flag)) {
            printBillCode = "OutBillQn-ZH";
        } else if ("3".equals(flag)) {
            List<PrintParam> ypPrintParamList = new ArrayList<>();
            PrintParam printParamYp = new PrintParam();
            printParamYp.setConsignorId(consignorId);
            printParamYp.setPrintBillCode("OutBillYM-YP");
            printParamYp.setWarehouseId(warehouseId);
            printParamYp.setParams(MapUtils.put("billId", billId).getMap());
            ypPrintParamList.add(printParamYp);
            log.info("打印出库清单-药品入参：{}",JSON.toJSONString(ypPrintParamList));
            RestMessage<?> restMessageYp = commonClient.executePrint(ypPrintParamList);
            log.info("打印出库清单-药品返回结果：{}", JSON.toJSONString(restMessageYp));
            //保存打印记录
            printLogService.save(billId,printBillCode,restMessageYp.isSuccess());


            List<PrintParam> qxPrintParamList = new ArrayList<>();
            PrintParam printParamQx = new PrintParam();
            printParamQx.setConsignorId(consignorId);
            printParamQx.setPrintBillCode("OutBillYM-QX");
            printParamQx.setWarehouseId(warehouseId);
            printParamQx.setParams(MapUtils.put("billId", billId).getMap());
            qxPrintParamList.add(printParamQx);
            log.info("打印出库清单-器械入参：{}",JSON.toJSONString(qxPrintParamList));
            RestMessage<?> restMessageQx = commonClient.executePrint(qxPrintParamList);
            log.info("打印出库清单-器械返回结果：{}", JSON.toJSONString(restMessageQx));
            //保存打印记录
            printLogService.save(billId,printBillCode,restMessageQx.isSuccess());


            List<PrintParam> spPrintParamList = new ArrayList<>();
            PrintParam printParamSp = new PrintParam();
            printParamSp.setConsignorId(consignorId);
            printParamSp.setPrintBillCode("OutBillYM-SP");
            printParamSp.setWarehouseId(warehouseId);
            printParamSp.setParams(MapUtils.put("billId", billId).getMap());
            spPrintParamList.add(printParamSp);
            log.info("打印出库清单-食品入参：{}",JSON.toJSONString(spPrintParamList));
            RestMessage<?> restMessageSp = commonClient.executePrint(spPrintParamList);
            log.info("打印出库清单-食品返回结果：{}", JSON.toJSONString(restMessageSp));
            //保存打印记录
            printLogService.save(billId,printBillCode,restMessageSp.isSuccess());
            return new RestMessage<>();
        } else if (("4".equals(flag))){
            printBillCode = "OutBillQn-NB";
        } else {
            printBillCode = "OutBillQnCg";
        }*/

        PrintParam printParam = new PrintParam();
        printParam.setPrintBillCode(printBillCode);
        printParam.setParams(MapUtils.put("billId", billId).getMap());

        //printParamList.add(printParam);
        log.info("打印出库清单入参：{}", JSON.toJSONString(printParam));
        RestMessage<?> restMessage = commonClient.getPrintInfo(printParam);
        //保存打印记录
        printLogService.save(billId,printBillCode,restMessage.isSuccess());
        if(!restMessage.isSuccess()) {
            throw new RuntimeException("打印失败:" + restMessage.getMessage());
        }
        log.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessage));

        return restMessage;
    }


    @Override
    public void outDetailedDownload(String warehouseId, String consignorId, String billId, String printBillCode, HttpServletResponse response,HttpServletRequest request) {
        //List<PrintParam> printParamList = new ArrayList<>();

        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("srcId", billId).getMap(), PickTaskD.class);
        if(pickTaskDList.isEmpty()) {
            throw new PrologException("当前订单未生成任务，没有打印数据");
        }
        /**
         * 1. 出库单在青牛系统下发至WMS时指定了打印方案【oms_do_bill_h.attr_str7】(
         *      目前是3种 分别为：1、通用版；2、折后单价版；3：商品分类版；4：牛币商品出库单版)
         *
         * 2. 在打印出库单时，需要取该字段区分打印那种方案，
         *      1为目前已有的模版。
         *      2在现有模版增加折后单价字段即可；
         *      3是根据订单中的所有商品分类汇总去打印，若有N种商品种类，则打印N张，模版为通用版，
         *      4为牛币商品出库版(模版待客户提供，)
         */

        PrintParam printParam = new PrintParam();
        printParam.setPrintBillCode(printBillCode);
        printParam.setParams(MapUtils.put("billId", billId).getMap());
        printParam.setProcessType(2);
        //printParamList.add(printParam);

        log.info("打印出库清单入参：{}", JSON.toJSONString(printParam));
        RestMessage<PrintInfo> restMessage = commonClient.executePrintSingle(printParam);
        if(restMessage==null || !restMessage.isSuccess() || restMessage.getData()==null) {
            throw new PrologException("打印失败:" + restMessage.getMessage());
        }
        log.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessage));

        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        PrintInfo data = restMessage.getData();
        List<String> pdfUrl = data.getPdfUrl();
        if(CollectionUtil.isNotEmpty(pdfUrl)){
            download(response, request,pdfUrl.get(0));

            //toDownload(pdfUrl.get(0), response);
        }else {
            throw new PrologException("下载文件失败，文件生成异常");
        }

    }



    @Override
    public String outDetailedDownloadExtends(String type, String warehouseId, String consignorId, String billId, String printBillCode, HttpServletResponse response,HttpServletRequest request) {
        //List<PrintParam> printParamList = new ArrayList<>();

        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("srcId", billId).getMap(), PickTaskD.class);
        if(pickTaskDList.isEmpty()) {
            throw new PrologException("当前订单未生成任务，没有打印数据");
        }

        PrintParam printParam = new PrintParam();
        printParam.setPrintBillCode(printBillCode);
        printParam.setParams(MapUtils.put("billId", billId).getMap());
        printParam.setProcessType(2);
        //printParamList.add(printParam);

        log.info("打印出库清单入参：{}", JSON.toJSONString(printParam));
        RestMessage<PrintInfo> restMessage = commonClient.executePrintSingle(printParam);
        if(restMessage==null || !restMessage.isSuccess() || restMessage.getData()==null) {
            throw new PrologException("打印失败:" + restMessage.getMessage());
        }
        log.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessage));

        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        PrintInfo data = restMessage.getData();
        List<String> pdfUrl = data.getPdfUrl();
        if(CollectionUtil.isEmpty(pdfUrl)){
            throw new PrologException("下载文件失败，文件生成异常");
        }

        if("url".equalsIgnoreCase(type)){
            return pdfUrl.get(0);
        }else if ("file".equalsIgnoreCase(type)){
            download(response, request,pdfUrl.get(0));
        }else{
            throw new PrologException("参数type异常，必须为url/file");
        }
        return null;
    }


    public static void download(HttpServletResponse response, HttpServletRequest request, String path){
        try {
            //获取文件名称
            //String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
            String ext = path.substring(path.lastIndexOf(".") + 1).toLowerCase();
            //文件名
            String pdfName;
            try {
                pdfName = path.split("/")[4];
            } catch (Exception e) {
                pdfName = DateUtils.format(new Date(),"yyyyMMddHHmmss") +ext;
            }


            // 浏览器
            String browser = request.getHeader("User-Agent").toUpperCase();

            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment;filename=" + pdfName);
            //开始下载
            @Cleanup
            BufferedInputStream is = new BufferedInputStream(new URL(path).openStream());
            @Cleanup
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            byte[] buff = new byte[1024];
            int len;
            while ((len = is.read(buff, 0, buff.length)) != -1) {
                out.write(buff, 0, len);
            }
            is.close();
            out.close();
        } catch (Exception e){
            log.error("DownLoadUtil-download: 异常，{}", e.getMessage());
            throw new PrologException("生成pdf文件异常");
        }
    }




    public void toDownload(String path, HttpServletResponse response)  {
        ServletOutputStream out = null;
        InputStream inputStream = null;

        try {
            //路径
            // 取得文件的后缀名。
            String ext = path.substring(path.lastIndexOf(".") + 1).toLowerCase();
            //文件名
            String pdfName;
            try {
                pdfName = path.split("/")[4];
            } catch (Exception e) {
                pdfName = DateUtils.format(new Date(),"yyyyMMddHHmmss") +ext;
            }

            // 获取外部文件流
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(3 * 1000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            inputStream = conn.getInputStream();
            /**
             * 输出文件到浏览器
             */
            int len = 0;
            // 输出 下载的响应头，如果下载的文件是中文名，文件名需要经过url编码
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(pdfName, "UTF-8"));
            response.setHeader("Cache-Control", "no-cache");
            out = response.getOutputStream();
            byte[] buffer = new byte[1024];
            while ((len = inputStream.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            out.flush();
        } catch (Exception e) {

            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e) {
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                }
            }
        }
    }




    /**
     * @Description 出库打印发票
     * Company: 湖北普罗格科技股份有限公司
     * @author chengxiang
     * @date 2023/10/26 10:56
     */
    @Override
    public void receiptPrint(String warehouseId, String cargoOwnerId, String billId) {
        List<PrintParam> printParamList = new ArrayList<>();

        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("srcId", billId).getMap(), PickTaskD.class);
        if(pickTaskDList.isEmpty()) {
            throw new RuntimeException("当前订单未生成任务，没有打印数据");
        }
        PrintParam printParam = new PrintParam();
        printParam.setConsignorId(cargoOwnerId);
        printParam.setPrintBillCode(DoPrintConstant.DO_PRINT_INVOICE_PDF);
        printParam.setWarehouseId(warehouseId);
        printParam.setParams(MapUtils.put("orderNo", billId).getMap());

        printParamList.add(printParam);

        log.info("打印发票入参：{}",JSON.toJSONString(printParamList));
        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
        if(!restMessage.isSuccess()) {
            throw new RuntimeException("打印失败:" + restMessage.getMessage());
        }
        log.info("打印发票返回结果：{}", JSON.toJSONString(restMessage));
    }
}
