package weaver.interfaces.htsc.payment.common.pdfprocess;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.engine.htsc.meeting.util.Common;
import com.engine.htsc.payment.log.PaymentLogger;
import com.engine.htsc.payment.log.PaymentLoggerFactory;
import com.engine.htsc.payment.util.AssertUtil;
import com.engine.htsc.payment.util.CommonAPI;
import com.engine.htsc.payment.util.PayUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
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.util.EntityUtils;
import weaver.conn.RecordSet;
import weaver.conn.RecordSetTrans;
import weaver.general.GCONST;
import weaver.general.Util;
import weaver.interfaces.htsc.comInfo.PropBean;
import weaver.interfaces.htsc.cus.HTUtil;
import weaver.interfaces.htsc.cus.webservices.FileInfoEntity;
import weaver.interfaces.htsc.cus.webservices.UploadfileEntity;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Created on 2022/4/14.
 *
 * @author K1810012
 */
public class PDFBizProcessorImpl implements PDFBizProcessor {
  private static final PaymentLogger LOGGER = PaymentLoggerFactory.getLogger(PDFBizProcessorImpl.class);
  private final String table = "uf_syncgalaxy";

  @Override
  public List<SyncPdf> queryUnSyncPdfList() {
    List<SyncPdf> pdfs = new ArrayList<>();
    //默认前10条，按requestid倒序
    List<Map<String, String>> queryList = CommonAPI.query(
        "select t.id,t.requestid,t.lcbh from " + table + " t where sfytb is null and rownum <= 10 order by requestid  desc"
    );
    for (Map<String, String> result : queryList) {
      SyncPdf syncPdf = map2dto(result);
      if (AssertUtil.isNotEmpty(syncPdf)) {
        pdfs.add(syncPdf);
      }
    }
    return pdfs;
  }

  @Override
  public List<SyncPdf> queryUnSyncPdfList(int size) {
    List<SyncPdf> pdfs = new ArrayList<>();
    List<Map<String, String>> queryList = CommonAPI.query(
        "select t.id,t.requestid,t.lcbh from " + table + " t where syncstatus is null and rownum <= " + size + " order by requestid  desc"
    );
    for (Map<String, String> result : queryList) {
      SyncPdf syncPdf = map2dto(result);
      if (AssertUtil.isNotEmpty(syncPdf)) {
        pdfs.add(syncPdf);
      }
    }
    return pdfs;
  }

  @Override
  public void modifySyncStatus(PdfStatusEnum status, String ids) {
    RecordSetTrans rst = new RecordSetTrans();
    try {
      rst.setAutoCommit(false);
      rst.executeUpdate("update " + table + " set syncstatus = '" + status.toString() + "' where id in ('" + ids + "')");
      rst.commit();
    } catch (Exception e) {
      rst.rollback();
      LOGGER.error("pdf 更新 uf_syncgalaxy 状态失败，" + e.getMessage());
      LOGGER.error("pdf 更新 uf_syncgalaxy 状态失败，" + e);
    }
  }

  @Override
  public void handle(List<SyncPdf> pdfs) {
    LOGGER.info(JSONObject.toJSONString(pdfs) + "===> 开始消费");
    try {
      RecordSet rs = new RecordSet();
      for (SyncPdf pdf : pdfs) {
        String requestid = pdf.getRequestid();
        HTUtil utils = new HTUtil();
        String tableName = utils.getTableNameByRequestid(requestid, "0");
        int workflowid = 0;
        String sql = "select workflowid from WORKFLOW_REQUESTBASE where requestid = " + requestid;
        rs.executeQuery(sql);
        if (rs.next()) {
          workflowid = Util.getIntValue(rs.getString("workflowid"));
        }
        sql = "select t1.workflowid,t3.lcbh as requestmark ,t2.workcode from workflow_requestbase t1\n" +
            "left join hrmresource t2 " +
            "on t1.creater = t2.id " +
            "left join " + tableName + " t3 " +
            "on t1.requestid = t3.requestid " +
            "where t1.requestid =?";
        Map<String, String> paramsProtoType = CommonAPI.querySingleRow(sql, requestid);
        Map<String, String> pdfParams = copy(paramsProtoType);
        pdfParams.put("requestid", requestid);
        pdfParams.put("modeid", printModeId(workflowid));
        //sendPDF
        if (sendPDF(pdfParams)) {
          modifySyncStatus(PdfStatusEnum.SYNCED, pdf.getId());
        }

      }
      LOGGER.info(Thread.currentThread().getName() + "===> 消费结束");
    } catch (Exception e) {
      LOGGER.error("pdf to Galaxy 出错，" + e.getMessage());
      LOGGER.error("pdf to Galaxy 出错，" + e);
    }
  }

  private SyncPdf map2dto(Map<String, String> queryResult) {
    try {
      return JSON.parseObject(JSON.toJSONString(queryResult), SyncPdf.class);
    } catch (Exception e) {
      LOGGER.error("map2dto convert error：" + e.getMessage());
      LOGGER.error("map2dto convert error：数据库查询map：" + JSON.toJSONString(queryResult));
      LOGGER.error("map2dto convert error：" + e);
      return null;
    }
  }

  public static void main(String[] args) {
    GCONST.setRootPath("");
    GCONST.setServerName("ecology");

    PDFBizProcessor bizProcessor = new PDFBizProcessorImpl();
    LinkedBlockingDeque<Runnable> runnables = new LinkedBlockingDeque<>(10);
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        10, 20, 5L, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(10),
        new ThreadPoolExecutor.CallerRunsPolicy());
    //2:1
    for (int i = 0; i < 5; i++) {
      try {
        runnables.put(new PdfConsumer(bizProcessor, runnables));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    PdfProducer producer = new PdfProducer(bizProcessor, runnables, threadPoolExecutor);
    new Thread(producer).start();

  }

  //业务逻辑代码
  private Map<String, String> copy(Map<String, String> prototype) {
    return new HashMap<>(prototype);
  }

  private boolean sendPDF(Map<String, String> params) throws Exception {
    LOGGER.info("ToGalaxy开始同步审批单 params" + JSON.toJSONString(params));
    AssertUtil.isEmpty(params.get("requestmark"), "requestmark为空");
    AssertUtil.isEmpty(params.get("workcode"), "workcode为空");
    AssertUtil.isEmpty(params.get("modeid"), "modeid为空");
    AssertUtil.isEmpty(params.get("requestid"), "requestid为空");
    //生成审批单PDF
    String path = Common.saveProcessPDFWithReturnFilePath(params.get("modeid"), params.get("requestid"), params.get("requestmark"));
    LOGGER.info("生成审批单PDF path" + path);
    //浪潮
    String filetype = "0";//文件类型 0：非票据  1：票据
    UploadfileEntity uploadfileEntity = new UploadfileEntity();
    uploadfileEntity.setBillID(params.get("requestmark"));
    uploadfileEntity.setFileType(filetype);
    uploadfileEntity.setUserCode(params.get("workcode"));
    LOGGER.info("send image request: " + JSON.toJSONString(uploadfileEntity));
    FileInfoEntity[] fileInfoEntities = new FileInfoEntity[1];
    String fileTypeID = Util.null2String(new PropBean().getPropName("cft.image.type.png"));
    int i = 0;
    InputStream inputstream = getInputStreamFromPath(path);
    FileInfoEntity fileInfoEntity = new FileInfoEntity();
    fileInfoEntity.setFileName(params.get("requestmark") + ".pdf"); //文件名称=流程编号.pdf
    fileInfoEntity.setContent(InputStream2Byte(inputstream));
    fileInfoEntity.setFileTypeID(fileTypeID);
    fileInfoEntities[i] = fileInfoEntity;
    uploadfileEntity.setFileInfoEntityArr(fileInfoEntities);
    Map<String, String> headers = new HashMap<String, String>();
    String url = Util.null2String(new PropBean().getPropName("toGalaxy"));
    String langChaoResponse = sendPostNew(url, JSONObject.toJSONString(uploadfileEntity), headers);
    LOGGER.info(String.format("sendPDF Galaxy out: %s", JSON.toJSONString(langChaoResponse)));
    LOGGER.info("ToGalaxy开始审批单结束");

    JSONObject jsonObject = JSONObject.parseObject(langChaoResponse);
    return 0 == jsonObject.getIntValue("retCode");
}

  private String printModeId(int workflowid) throws Exception {
    String sql = " select t2.unnumber,t1.modeid from workflow_printset t1\n" +
        "    left join workflow_nodebase t2\n" +
        "    on t1.nodeid = t2.id\n" +
        "    where type =1\n" +
        "    and printenable =1\n" +
        "    and t2.nodename = '办结'\n" +
        "    and t1.isactive = 1\n" +
        "    and t1.orderid = 0\n" +
        "    and t2.unnumber = ?";
    try {
      Map<String, String> pa = CommonAPI.querySingleRow(sql,
          PayUtil.getUnNumberByWorkFlowId(workflowid) + "_bj");
      return pa.get("modeid");
    } catch (Exception e) {
      throw new IllegalArgumentException(String.format("workflowid:%s,没有对应的办结打印模板 ", workflowid));
    }

  }

  /**
   * 获取文件流, by path
   *
   * @param filePath
   * @return
   * @throws FileNotFoundException
   */
  private InputStream getInputStreamFromPath(String filePath) throws FileNotFoundException {
    try {
      File thefile = new File(filePath);
      return new BufferedInputStream(new FileInputStream(thefile));
    } catch (FileNotFoundException e) {
      LOGGER.info(String.format("filePath:%s, file not  found", filePath));
      throw new FileNotFoundException(String.format("filePath:%s, file not  found", filePath));
    }
  }

  /**
   * 转换成 byte []
   *
   * @param inputStream 附件转的流
   * @return byte
   */
  public byte[] InputStream2Byte(InputStream inputStream) {
    byte[] result;
    try {
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      byte[] buffer = new byte[1024];
      int len = 0;
      while ((len = inputStream.read(buffer)) != -1) {
        bos.write(buffer, 0, len);
      }
      inputStream.close();
      bos.flush();
      result = bos.toByteArray();
    } catch (Exception e) {
      LOGGER.info("字节流转换出错！");
      return null;
    }
    return result;
  }

  /***
   *
   * @param url
   * @param params
   * @param headsMap
   * @return
   */
  public String sendPostNew(String url, String params, Map<String, String> headsMap) {
    //BaseBean bb = new BaseBean();
    String body = "";
    String encoding = "UTF-8";
    //创建httpclient对象
    CloseableHttpClient client = HttpClients.createDefault();
    //创建post方式请求对象
    HttpPost httpPost = new HttpPost(url);


    //设置参数到请求对象中
    StringEntity strEntity = new StringEntity(params, encoding);//解决中文乱码问题
    strEntity.setContentEncoding(encoding);
    strEntity.setContentType("application/json");
    httpPost.setEntity(strEntity);

    //设置header信息
    //指定报文头【Content-type】、【User-Agent】
    httpPost.setHeader("Content-type", "application/json");
    httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

    if (headsMap != null && !headsMap.isEmpty()) {
      headsMap.forEach((key, value) -> {
        //bb.writeLog("key:"+key+" value:"+value);
        httpPost.addHeader(key, value);
      });
    }
    //执行请求操作，并拿到结果（同步阻塞）
    CloseableHttpResponse response = null;
    try {
      response = client.execute(httpPost);
      //获取结果实体
      HttpEntity entity = response.getEntity();
      if (entity != null) {
        //按指定编码转换结果实体为String类型
        body = EntityUtils.toString(entity, encoding);
      }
      EntityUtils.consume(entity);
      //释放链接
      response.close();
    } catch (IOException e) {
      System.out.println("OrganizationSyn-e:" + e);
      e.printStackTrace();
    }
    return body;
  }

}
