package cn.hmsoft.pay.service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

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

import cn.hmsoft.application.SpringHelper;
import cn.hmsoft.frame.exception.BusinessException;
import cn.hmsoft.frame.util.FrameAssertUtil;
import cn.hmsoft.helper.StringHelper;
import cn.hmsoft.log.LogHelper;
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.PayChannelAbstract;
import cn.hmsoft.pay.util.PayModuleConfig;
import cn.hmsoft.pay.util.PayParamUtil;

/******************************
 * 
 * @note 订单处理
 * @author revisit@126.com
 * @Company: www.hmsoft.cn
 * @create 2017年8月22日 下午3:43:10
 * @version 4.0.0
 */
@Service
public class PayBillService {
	
	
	
	@Autowired
	private PayBillDao daoBill;
	
	public void optrBill(PayBill bill) {
		if(bill.getBill_id()==null)
			this.daoBill.insert(bill);
		else 
			this.daoBill.update(bill);
	}

	/******************************
	 * 生成订单
	 * 
	 * @param merchant_id 商户编号
	 * @param channel_id 渠道编号
	 * @param customer_id 客户编号
	 * @param detail_id 学年
	 * @param order_amount 订单金额
	 * @param business_type 业务类型
	 * @param business_id 业务编号
	 * @param bill_no 订单编号
	 * @param bill_param 订单参数
	 * @return
	 */
	public String order(String merchant_id, String channel_id, String customer_id, String detail_id, int order_amount,
			String business_type, String business_id, String bill_no, String bill_param) {
		// 订单金额必须大于0
		if (order_amount <= 0)
			throw new BusinessException("订单金额必须大于0");
		// 商户号、渠道、客户编号、业务编号不允许为空
		FrameAssertUtil.checkParam(merchant_id, channel_id, customer_id, business_id);
		PayChannelAbstract payImpl = PayModuleConfig.getPayImpl(merchant_id, channel_id);
		FrameAssertUtil.isNotNull(payImpl, "该商户指定的支付渠道未能成功加载，请联系技术部门");

		PayBill bill = null;
		// 如果传递的参数有订单编号，查询订单
		if (StringHelper.isNotEmpty(bill_no)) {
			List<PayBill> billArray = this.daoBill.listByBillNo(merchant_id, channel_id, bill_no);
			if (billArray.size() > 1)
				throw new BusinessException("订单号[" + bill_no + "]对应了多个多个订单，请联系系统管理员");
			if (billArray.size() == 1)
				bill = billArray.get(0);
			// 判断是不是同一个的订单
			FrameAssertUtil.isEqual(customer_id, bill.getCustomer_id(), "订单号[" + bill_no + "]已经存在，订单所属客户不一致，请联系系统管理员");
			if (bill.getBill_amount() - order_amount != 0)
				throw new BusinessException("订单号[" + bill_no + "]已经存在，原有金额与本次金额不一致，请联系系统管理员");
		}
		if (bill == null) {
			bill = new PayBill();
			bill.setBill_amount(order_amount);
//			bill.setBill_id(this.daoBill.getNextSequence(PaySeqName.PayBillId));
			bill.setBill_param(bill_param);
			bill.setBill_status(PayBillStatus.Request);
			bill.setBill_time(LocalDateTime.now());
			bill.setBusiness_id(business_id);
			bill.setBusiness_type(business_type);
			bill.setChannel_id(channel_id);
			bill.setCustomer_id(customer_id);
			bill.setDetail_id(detail_id);
			bill.setMerchant_id(merchant_id);
			// 最后生成订单号
			bill.setBill_no(payImpl.makeBillNo(bill));
			this.daoBill.insert(bill);
		}

		// 生成请求订单
		String type = payImpl.getChannelParamMap().get("OwnerSubmit");
		if ("true".equalsIgnoreCase(type)) {
			return payImpl.makeRequestString(bill);
		} else {
			Map<String, String> requestMap = payImpl.makeRequestAttr(bill);

			StringBuilder sb = new StringBuilder(
					"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><form name=\"form1\" method=\"post\" action=\""
							+ payImpl.getChannel().getPay_url() + "\">");
			for (String key : requestMap.keySet()) {
				String value = requestMap.get(key);
				sb.append("<input type=\"hidden\" id=\"" + key + "\" name=\"" + key + "\" value='"
						+ (value == null ? "" : value) + "'>");
			}
			sb.append(
					"</form></body><script type=\"text/javascript\">window.onload = function(){document.form1.submit();}</script></html>");
			return sb.toString();
		}
	}

	public PayBill reply(Integer bill_id, HttpServletRequest request) {
		return reply(bill_id, request, null);
	}

	/****************************
	 * 处理银行回复支付信息
	 * 
	 * @param bill_id 订单编号
	 * @param request
	 * @return
	 */
	public PayBill reply(Integer bill_id, HttpServletRequest request, Map<String, Object> paramMap) {
		// 商户号、渠道
		FrameAssertUtil.checkParam(bill_id);
		final PayBill bill = this.daoBill.find(bill_id);
		FrameAssertUtil.isNotNull(bill, "未找到内部编号为[" + bill_id + "]的订单");
		if (!bill.getBill_status().equals(PayBillStatus.Complete)) {
			PayChannelAbstract payImpl = PayModuleConfig.getPayImpl(bill.getMerchant_id(), bill.getChannel_id());
			if (payImpl == null)
				LogHelper.error("该商户[" + bill.getMerchant_id() + "]指定的支付渠道[" + bill.getChannel_id() + "]未能成功加载，请联系技术部门");
			payImpl.processReply(this.daoBill, bill, request, paramMap);
			LogHelper.info("1-- in PayBillService.reply---------:" + bill.getBill_status());
		}
		if (bill.getBill_status().equals(PayBillStatus.Complete)) {
			// 订单完成，银行多次返回,使用线程模式
			new Thread() {
				public void run() {
					LogHelper.info("2-- thread-------:" + bill.getBusiness_type());
					PayAbstractService pay = SpringHelper.getBean(PayParamUtil.PayCallbackService);
					pay.pay(bill);
				}
			}.start();
		}
		return bill;

	}

	/****************************
	 * 手动查询订单
	 */
	public PayBill queryBill(int bill_id) {
		// 商户号、渠道
		PayBill bill = this.daoBill.findByBillId(bill_id);
		if (bill == null)
			return null;

		PayChannelAbstract payImpl = PayModuleConfig.getPayImpl(bill.getMerchant_id(), bill.getChannel_id());
		FrameAssertUtil.isNotNull(payImpl, "该商户指定的支付渠道未能成功加载，请联系技术部门");

		return payImpl.queryBill(this.daoBill, bill);
	}
	
	public PayBill checkBill(int bill_id) {
		// 商户号、渠道
		PayBill bill = this.daoBill.findByBillId(bill_id);
		if (bill == null)
			return null;

		PayChannelAbstract payImpl = PayModuleConfig.getPayImpl(bill.getMerchant_id(), bill.getChannel_id());
		FrameAssertUtil.isNotNull(payImpl, "该商户指定的支付渠道未能成功加载，请联系技术部门");

		return payImpl.queryBill(this.daoBill, bill);
	}

}
