package cn.hmsoft.pay.impl;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.hmsoft.application.SpringHelper;
import cn.hmsoft.frame.exception.BusinessException;
import cn.hmsoft.helper.LocalDateHelper;
import cn.hmsoft.helper.SecureHelper;
import cn.hmsoft.helper.StringHelper;
import cn.hmsoft.log.LogHelper;
import cn.hmsoft.pay.constants.BillProcessResult;
import cn.hmsoft.pay.constants.PayBillStatus;
import cn.hmsoft.pay.data.dao.PayBillDao;
import cn.hmsoft.pay.data.model.PayBill;
import cn.hmsoft.pay.impl.fudan.QueryResult;
import cn.hmsoft.pay.service.PayAbstractService;
import cn.hmsoft.pay.util.HttpClientHelper;
import cn.hmsoft.pay.util.PayParamUtil;

/******************************
 * 
 * @ 复旦支付渠道
 */
public class PayFuDanChannelImpl extends PayChannelAbstract {
	static String XMLMode = "<?xml version=\"1.0\" encoding=\"GBK\"?><billinfo><version>1.0.0.2</version><billno>#billno</billno><orderinfono>#orderinfono</orderinfono><orderinfoname>#orderinfoname</orderinfoname><returnURL>#returnURL</returnURL><billdtl><feeitemid>#feeitemid</feeitemid><feeord>1</feeord><amt>#amt</amt></billdtl></billinfo>";
	
	@Override
	protected boolean init() throws Exception {
		if (StringHelper.isEmpty(this.channel.getPay_url())) {
			return error("支付网关未配置");
		}
		return true;
	}

	@Override
	public String makeBillNo(PayBill bill) {
		String v = StringHelper.leftPadding(bill.getBusiness_id(), 8, '0');
		String times = LocalDateHelper.formatLongNoSplit(LocalDateTime.now());
		times = times.substring(4, times.length());
		return "FD_" + bill.getBusiness_type() + "_" + times + "_" + v;
	}

	@Override
	public PayBill processReply(PayBillDao daoBill, PayBill bill, HttpServletRequest request,
			Map<String, Object> paramMap) {
		String sysid = merchantParamMap.get("sysid");
		String subsysid = merchantParamMap.get("subsysid");
		String cert = payMerchantChannel.getPublic_key_path();
		//String sign = paramMap.get("sign").toString();
		String xmlStr = paramMap.get("XmlString").toString();
		String data = null;
		try {
			data = URLEncoder.encode(xmlStr, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		//String checksign = SecureHelper.md5((sysid + subsysid + cert + data)).toLowerCase();
		//if (!checksign.equals(sign))
		//	throw new BusinessException("签名异常");
		
		System.out.println(xmlStr);
		String paidtime = (String) paramMap.get("Paidtime");
		String trade_no = (String) paramMap.get("Trade_no");

		LocalDateTime reply_time = LocalDateTime.now();
		LocalDateTime pay_time = null;
		try {
			pay_time = LocalDateHelper.parseDateTime(paidtime,
					LocalDateHelper.LongDateFormatter);
		} catch (Exception e) {

		}
		bill.setPay_time(pay_time);
		bill.setReply_time(reply_time);
		bill.setBill_status(PayBillStatus.Complete);
		// 首次成交 更新订单
		try {
			LogHelper.info("0--in processReply 改订单日志监控---" + bill.getBill_param() + "," + bill.getBusiness_type());
			daoBill.completeBill(bill.getBill_id(), pay_time, reply_time, trade_no);
			return bill;
		} catch (Exception e) {
			e.printStackTrace();
			this.logReply(bill, BillProcessResult.DatabaseError, xmlStr, request);
			return null;
		}
	}
	
	@Override
	public Map<String, String> makeRequestAttr(PayBill bill) {
		//String feeid = merchantParamMap.get("feeid");
		//System.out.println(bill.getBill_param());
		LinkedHashMap<String, String> paramMap = StringHelper.toMap(bill.getBill_param());
		String ticket_no = paramMap.get("ticket_no");
		String std_name = paramMap.get("std_name");
		String fee_id = paramMap.get("fee_id");
		//System.out.println(ticket_no + std_name);
		String xmlStr = buildXml(bill.getBill_no(), ticket_no == null ? "" : ticket_no,
				std_name == null ? "" : std_name, payMerchantChannel.getNotice_url(), fee_id, bill.getBill_amount());
		String sysid = merchantParamMap.get("sysid");
		String subsysid = merchantParamMap.get("subsysid");
		String cert = payMerchantChannel.getPublic_key_path();
		String data = null;
		try {
			data = URLEncoder.encode(xmlStr, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		String sign = SecureHelper.md5((sysid + subsysid + cert + xmlStr)).toLowerCase();

		Map<String, String> map = new HashMap<>();
		map.put("sign", sign);
		map.put("sysid", sysid);
		map.put("subsysid", subsysid);
		map.put("data", data);
		return map;
	}

	private String buildXml(String billno, String userno, String username, String returnurl, String feeitemid,
			int amt) {
		return XMLMode.replace("#billno", billno).replace("#orderinfono", userno).replace("#orderinfoname", username)
				.replace("#returnURL", returnurl).replace("#feeitemid", feeitemid).replace("#amt", "" + amt / 100.0);
	}

	private static String QUERY_URL = "http://cwjf.gxu.edu.cn/payment/portal/Query_PayQuery.action";//未参数化，只支持西大
	@Override
	public PayBill queryBill(PayBillDao daoBill, PayBill bill) {
			if (!bill.getBill_status().equals(PayBillStatus.Complete)) {
				String sysid =getMerchantParamMap().get("sysid");
				String subsysid = getMerchantParamMap().get("subsysid");
				String cert = getPayMerchantChannel().getPublic_key_path();
				String billno = bill.getBill_no();
				String sign = SecureHelper.md5(sysid + subsysid + cert + billno).toLowerCase();
				Map<String, Object> params = new HashMap<String, Object>();
				params.put("sign", sign);
				params.put("sysid", sysid);
				params.put("subsysid", subsysid);
				params.put("billno", billno);
				LogHelper.info("查询："+bill.getBill_param() +" bill:"+ bill.getBill_no() +" billtime:"+ bill.getBill_time());
				String result = null;
				try {
					result = HttpClientHelper.post(QUERY_URL, params);
				} catch (IOException e1) {
					LogHelper.info( "请求失败 bill:"+ bill.getBill_no());
					e1.printStackTrace();
				}
				if(!StringHelper.isEmpty(result)) {
					String xmlstr = result.substring(result.indexOf("@") + 1);
					QueryResult entity = null;
					try {
						JAXBContext jc = JAXBContext.newInstance(QueryResult.class);
						Unmarshaller u = jc.createUnmarshaller();
						entity = (QueryResult) u.unmarshal(new StringReader(xmlstr));
					} catch (Exception e) {
						LogHelper.info( "xml解析失败 bill:"+ bill.getBill_no());
						LogHelper.error(e);
					}
					
					if (entity != null) {
						Map<String, String> map = new HashMap<>();
						
						if (entity.getState() != null && entity.getBillinfo() != null
								&& "0000".equals(entity.getState().getReturncode())
								&& "4".equals(entity.getBillinfo().getPaystate())) {
							LogHelper.info("查询到有效订单" );
							map.put("trade_no", entity.getBillinfo().getTrade_no());
							map.put("bill_no", entity.getBillinfo().getBillno());
							Map<String, Object> paramMap = new HashMap<String, Object>();
							paramMap.put("Paidtime", entity.getBillinfo().getPaidtime());
							paramMap.put("Trade_no", entity.getBillinfo().getTrade_no());
							paramMap.put("XmlString", xmlstr);

							ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
									.getRequestAttributes();
							if(requestAttributes==null)
								LogHelper.info("requestAttributes 空" );
							else {
								HttpServletRequest request = requestAttributes.getRequest();
								processReply(daoBill, bill, request, paramMap);
								if (bill.getBill_status().equals(PayBillStatus.Complete)) {
									PayAbstractService pay = SpringHelper.getBean(PayParamUtil.PayCallbackService);
									LogHelper.info("0---------queryBill:" + bill.getBusiness_type());
									pay.pay(bill);
								}
							}
						}
					}
				}
			}
			return bill;
	}
}
