package io.renren.modules.lianlian.service.impl;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import io.renren.common.constant.LLianPayConstant;
import io.renren.common.utils.DateUtils;
import io.renren.common.utils.HttpClientUtil;
import io.renren.common.vo.trans.LianLianResp;
import io.renren.common.vo.trans.ReceiptReq;
import io.renren.modules.lianlian.service.ReceiptService;
import io.renren.modules.lianlian.vo.ReceiptDownloadParams;
import io.renren.modules.lianlian.vo.ReceiptDownloadResult;
import io.renren.modules.lianlian.vo.ReceiptProduceParams;
import io.renren.modules.lianlian.vo.ReceiptProduceResult;
import io.renren.modules.loan.dao.LReceiptDao;
import io.renren.modules.loan.entity.LReceiptEntity;

@Service
public class ReceiptServiceImpl implements ReceiptService {
	
	@Autowired
	private LLianPayConstant constant;
	
	@Autowired
	private LReceiptDao receiptDao;

	@Override
	public LianLianResp receiptGenerate(ReceiptReq req) throws Exception {
		LianLianResp resp = new LianLianResp();
		ReceiptProduceParams params = new ReceiptProduceParams();
        String timestamp = DateUtils.getTimestamp();
        params.setTimestamp(timestamp);
        params.setOid_partner(constant.getOidPartner());
        params.setTxn_seqno(DateUtils.getCurrentTime());
        params.setTxn_time(timestamp);
        params.setTrade_accp_txno(req.getTradeAccpTxno());
        params.setTrade_bill_type(req.getTradeBillType());
        params.setTotal_amount(req.getTotalAmount());

        String resultJsonStr = HttpClientUtil.sendRequest(constant.getReceiptProduce(), JSON.toJSONString(params),constant.getPrivateKey(),constant.getPublicKey());
        ReceiptProduceResult result = JSON.parseObject(resultJsonStr, ReceiptProduceResult.class);
        if(!LLianPayConstant.RET_CODE.equals(result.getRetCode())) {
        	throw new Exception("调用连连【电子回单生成】接口失败："+result.getRetMsg());
        }
        
        LReceiptEntity entity = new LReceiptEntity();
        BeanUtils.copyProperties(result, entity);
		receiptDao.insert(entity);
        
        BeanUtils.copyProperties(result, resp);
		return resp;
	}
	
	@Override
	public void receiptDownload(HttpServletResponse response,ReceiptReq req) throws Exception {
		LReceiptEntity entity = receiptDao.selectOne(new QueryWrapper<LReceiptEntity>().lambda().eq(LReceiptEntity::getTradeAccpTxno, req.getTradeAccpTxno())
				.eq(LReceiptEntity::getTradeBillType, req.getTradeBillType())
				.eq(LReceiptEntity::getTotalAmount, req.getTotalAmount()));
		
		if(null == entity) {
			throw new Exception("请先生成电子回单");
		}
		if("SUCCESS".equals(entity.getReceiptStatus())) {
			downloadLocal(response, entity.getReceiptSumFile(), entity.getReceiptAccpTxno().concat(".zip"));
			return;
		}
		
		ReceiptDownloadParams params = new ReceiptDownloadParams();
        params.setTimestamp(DateUtils.getTimestamp());
        params.setOid_partner(constant.getOidPartner());
        params.setToken(entity.getToken());
        params.setReceipt_accp_txno(entity.getReceiptAccpTxno());

        String resultJsonStr = HttpClientUtil.sendRequest(constant.getReceiptDownload(), JSON.toJSONString(params),constant.getPrivateKey(),constant.getPublicKey());
		ReceiptDownloadResult receiptDownloadResult = JSON.parseObject(resultJsonStr, ReceiptDownloadResult.class);
        
		BeanUtils.copyProperties(receiptDownloadResult, entity);
		receiptDao.updateById(entity);
		
		// 保存对账单到本地
        //base64ToFile(receiptDownloadResult.getReceipt_sum_file(), constant.getFilePath());
        //generateFile(receiptDownloadResult.getReceipt_sum_file(), constant.getFilePath());
		
	}
	
	/**
     * 原base64压缩文件转文件
     *
     * @param base64 原Base64压缩文件
     * @param path   文件保存路径
     * @throws RuntimeException
     */
    public static void base64ToFile(String base64, String path) throws RuntimeException {
        System.out.println("解压文件地址" + path);
        try {
            byte[] byteBase64 = Base64.getDecoder().decode(base64);
            ByteArrayInputStream byteArray = new ByteArrayInputStream(byteBase64);
            ZipInputStream zipInput = new ZipInputStream(byteArray);
            ZipEntry entry = zipInput.getNextEntry();
            File fout = null;
            File filePath = new File(path);
            if (!filePath.exists()) {
                filePath.mkdirs();
            }
            while (entry != null && !entry.isDirectory()) {
                System.out.println("文件名称: " + entry.getName());
                fout = new File(filePath, entry.getName());
                if (!fout.exists()) {
                    (new File(fout.getParent())).mkdirs();
                }
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fout));
                int offo = -1;
                byte[] buffer = new byte[1024];
                while ((offo = zipInput.read(buffer)) != -1) {
                    bos.write(buffer, 0, offo);
                }
                bos.close();
                // 获取 下一个文件
                entry = zipInput.getNextEntry();
            }
            zipInput.close();
            byteArray.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("解压流出现异常", e);
        }
    }

	public void downloadLocal(HttpServletResponse response,String base64,String fileName) throws Exception {
        byte[] byt = Base64.getDecoder().decode(base64);
        for (int i = 0; i < byt.length; i++) {
            //调整异常数据
            if(byt[i] < 0){
                byt[i] += 256;
            }
        }
        InputStream inStream = new ByteArrayInputStream(byt);
        
        // 设置输出的格式
        response.reset();
        response.setContentType("bin");
        response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        // 循环取出流中的数据
        byte[] b = new byte[100];
        int len;
        try {
            while ((len = inStream.read(b)) > 0){
                response.getOutputStream().write(b, 0, len);
            }
            inStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

	public void generateFile(String base64, String path) throws Exception {
    	byte[] byt = Base64.getDecoder().decode(base64);
        //base64解码 对字节数组字符串进行base64解码并生成文件
        for (int i = 0; i < byt.length; i++) {
            //调整异常数据
            if(byt[i] < 0){
                byt[i] += 256;
            }
        }
        OutputStream out = null;
        InputStream input = new ByteArrayInputStream(byt);
        try {
            //生成指定格式的文件
            out = new FileOutputStream(path);
            byte[] buff = new byte[1024];
            int len = 0;
            while((len = input.read(buff)) != -1){
                out.write(buff,0,len);
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
        }

    }
	

}