package com.yihu.jw.hospital.prescription.service.entrance.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yihu.jw.entity.base.org.BaseOrgDO;
import com.yihu.jw.entity.base.patient.BasePatientDO;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionDO;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionExpressageDO;
import com.yihu.jw.entity.hospital.prescription.WlyyPrescriptionInfoDO;
import com.yihu.jw.hospital.prescription.dao.PrescriptionInfoDao;
import com.yihu.jw.hospital.prescription.service.PrescriptionService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import sun.misc.BASE64Encoder;

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 顺丰速递接口相关的一些公用方法
 * @author huangwenjie 2017.8.2
 */
@Component
public class SFUtils {

    private static Logger logger = LoggerFactory.getLogger(SFUtils.class);

    @Autowired
    private PrescriptionService prescriptionService;
    @Autowired
    private PrescriptionInfoDao prescriptionInfoDao;

    /**
     * 生成接口校验码
     * 1.先把XML报文与checkword前后连接。
     * 2.把连接后的字符串做 MD5(16位) 编码。
     * 3.把MD5编码后的数据进行 Base64 编码，此时编码后的字符串即为校验码。
     * @param xml   xml报文
     * @param sf_check_word  接口check_word
     * @return
     */
    public String verifyCodeSFXmlStr(String xml,String sf_check_word){

        String verifyCode = xml+sf_check_word;
        verifyCode = md5EncryptAndBase64(verifyCode);
        return verifyCode;

    }

    /**
     * 查询派送地址是否属于顺丰的派送范围
     * @param d_address     派送地址
     * @param sf_code       顺丰接口接入码
     * @param orderid       订单ID
     * @param j_tel         寄方电话
     * @param j_address     寄方地址
     * @param d_tel         收方电话
     * @return
     */
    public String getSFOrderFilterXml(String d_address,String sf_code,String orderid,String j_tel,String j_address,String d_tel){

        //head 传入接口接入码
        StringBuilder xml = new StringBuilder("<Request service='OrderFilterService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<OrderFilter filter_type='1' ");

        //订单号
        if(StringUtils.isNotBlank(orderid)){
            xml.append("orderid='"+orderid+"' ");
        }

        //派送地址，必填
        xml.append("d_address='"+d_address+"'/>");

        //如果扩张字段有不为空的，则增加扩张字段参数
        if(StringUtils.isNotBlank(j_tel) ||
                StringUtils.isNotBlank(j_address)||
                    StringUtils.isNotBlank(d_tel)){
            xml.append("<OrderFilterOption ");
            //寄方电话
            if(StringUtils.isNotBlank(j_tel)){
                xml.append("j_tel='"+j_tel+"' ");
            }

            //寄方地址
            if(StringUtils.isNotBlank(j_address)){
                xml.append("j_address='"+j_address+"' ");
            }

            //收方电话
            if(StringUtils.isNotBlank(d_tel)){
                xml.append("d_tel='"+d_tel+"' ");
            }

            xml.append("/></OrderFilter>");
        }

        xml.append("</Body></Request>");

        return xml.toString();
    }


    /**
     * 向顺丰快递下订单--V1
     * @param sfexpress_obj
     * @param hospital
     * @return
     */
    public String postSFOrderService(WlyyPrescriptionExpressageDO sfexpress_obj, BaseOrgDO hospital, String sf_code) {
        //head 传入接口接入码
        StringBuilder xml = new StringBuilder("<Request service='OrderService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<Order ");
        //订单号(快递业务号作为订单号"SF开头的为顺丰快递")
        xml.append("orderid='"+sfexpress_obj.getId()+"' ");
        /**
         * --------寄方参数------
         */
        //寄件方公司名称
        if(StringUtils.isNotBlank(hospital.getName())){
            xml.append("j_company='"+hospital.getName()+"' ");
        }
        //寄方联系人
        if(StringUtils.isNotBlank(hospital.getName())){
            xml.append("j_contact='"+hospital.getName()+"' ");
        }
        //寄件方联系电话
        if(StringUtils.isNotBlank(hospital.getMobile())){
            xml.append("j_tel='"+hospital.getMobile()+"' ");
            xml.append("j_mobile='"+hospital.getMobile()+"' ");
        }
        //寄方所在省份
        if(StringUtils.isNotBlank(hospital.getProvinceName())){
            xml.append("j_province='"+hospital.getProvinceName()+"' ");
        }
        //寄方所在城市
        if(StringUtils.isNotBlank(hospital.getCityName())){
            xml.append("j_city='"+hospital.getCityName()+"' ");
        }
        //寄方所在县/区
        if(StringUtils.isNotBlank(hospital.getTownName())){
            xml.append("j_county='"+hospital.getTownName()+"' ");
        }
        //寄件方详细地址,包括省市县/区
        if(StringUtils.isNotBlank(hospital.getAddress())){
            xml.append("j_address='"+hospital.getAddress()+"' ");
        }
        /**
         * --------收方参数------
         */
        //派送地址，必填
        xml.append("d_address='"+sfexpress_obj.getAddress()+"' ");
        //到件方单位名称，因为接口不能为空，这里默认放到件方联系人
        xml.append("d_company='"+sfexpress_obj.getName()+"' ");
        //到件方联系人
        xml.append("d_contact='"+sfexpress_obj.getName()+"' ");
        //到件方联系电话
        xml.append("d_tel='"+sfexpress_obj.getPhone()+"' ");
        //到件方手机
        if(StringUtils.isNotBlank(sfexpress_obj.getMobile())){
            xml.append("d_mobile='"+sfexpress_obj.getMobile()+"' ");
        }
        xml.append("d_province='"+sfexpress_obj.getProvinceName()+"' ");
        xml.append("d_city='"+sfexpress_obj.getCityName()+"' ");
        xml.append("d_county='"+sfexpress_obj.getTownName()+"' ");
        //是否要求通过是否手持终端;通知顺丰收派员收件:1:要求,其它为不要求
        xml.append("is_docall='1' ");
        //快件产品类别:11,医药常温,1：顺丰标快
        //付款方式：1:寄方付，2:收方付 3:第三方付
        xml.append("express_type='1' pay_method='2' >");
//        xml.append("express_type='11' pay_method='1' custid='9999999999'>");

        //根据快递物流获取门诊信息，根据门诊信息获取处方订单的药品详情
        List<WlyyPrescriptionDO> prescriptionDOList = prescriptionService.findByField("outpatientId",sfexpress_obj.getOutpatientId());
        if(CollectionUtils.isEmpty(prescriptionDOList)){

        }

        Set<String> prescriptionIdSet = new HashSet<>();
        prescriptionDOList.forEach(
               onePrescription -> {
                   prescriptionIdSet.add(onePrescription.getId());
                }
        );
        List<WlyyPrescriptionInfoDO> prescriptionInfolist = prescriptionInfoDao.queryAllByPrescriptionIdInAndDel(prescriptionIdSet,1);

        if(!prescriptionInfolist.isEmpty()){
            for (int i = 0; i < prescriptionInfolist.size(); i++) {
                xml.append("<Cargo name='"+prescriptionInfolist.get(i).getDrugName()+"' count='"+prescriptionInfolist.get(i).getQuantity()+"'></Cargo>");
            }
        }
        xml.append("</Order></Request>");
        return xml.toString();

    }


    /**
     * 订单确认/取消
     * @param sf_code
     * @param orderid
     * @param mailno
     * @param dealtype
     * @return
     */
    public String SFOrderConfirmXml(String sf_code,String orderid ,String mailno,int dealtype){

        //head 传入接口接入码
        StringBuilder xml = new StringBuilder("<Request service='OrderConfirmService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<OrderConfirm ");

        //订单号
        if(StringUtils.isNotBlank(orderid)){
            xml.append("orderid='"+orderid+"' ");
        }
        //派送订单号，必填
        xml.append("mailno='" + mailno + "'/> ");
        xml.append("dealtype='" + dealtype + "'/>");
        xml.append("/></OrderConfirm>");
        xml.append("</Body></Request>");
        return xml.toString();
    }

    /**
     * 顺丰路由查询
     * @param sfexpress_obj
     * @param sf_code
     * @return
     */
    public String getRoutInfos(WlyyPrescriptionExpressageDO sfexpress_obj, String sf_code) {
        //head 传入接口接入码
        StringBuilder xml = new StringBuilder("<Request service='RouteService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<RouteRequest tracking_type='1' method_type='1' ").append("tracking_number='"+sfexpress_obj.getMailno()+"' />");
        xml.append("</Body></Request>");
        return xml.toString();
    }

    /**
     * 订单结果查询接口
     * @param sfexpress_objCode
     * @param sf_code
     * @return
     */
    public String sfOrderSearchService(String sfexpress_objCode, String sf_code) {
        StringBuilder xml = new StringBuilder("<Request service='OrderSearchService' lang='zh-cn'><Head>"+sf_code+"</Head><Body>");
        xml.append("<OrderSearch orderid='"+sfexpress_objCode+"'/>");
        xml.append("</Body></Request>");
        return xml.toString();
    }


    //-----------顺丰快递验证码加密的相关方法------------------START
    public static String loadFile(String fileName) {
        InputStream fis;
        try {
            fis = new FileInputStream(fileName);
            byte[] bs = new byte[fis.available()];
            fis.read(bs);
            String res = new String(bs);
            fis.close();
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String md5EncryptAndBase64(String str) {
        return encodeBase64(md5Encrypt(str));
    }

    private static byte[] md5Encrypt(String encryptStr) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(encryptStr.getBytes("utf8"));
            return md5.digest();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String encodeBase64(byte[] b) {
        BASE64Encoder base64Encode = new BASE64Encoder();
        String str = base64Encode.encode(b);
        return str;
    }

    public static void main(String[] args) {
        String xml = "<Request service='OrderSearchService' lang='zh-cn'><Head>SDDF</Head><Body><OrderSearch orderid='6daa6baec5fd4b65a1b023a8b60e2e76'/></Body></Request>";
        String check_word = "ttzlgGyOQu4L";
        System.out.println(md5EncryptAndBase64(xml + check_word));
//        System.out.println(md5EncryptAndBase64("abc"));
//        System.out.println(md5EncryptAndBase64("中"));
    }

    //-----------顺丰快递验证码加密的相关方法------------------END
    
    
    
    /**
     * 组装顺丰快递下订单参数--V2
     * @param sfexpress_obj
     * @param hospital
     * @return
     */
    public JSONObject postSFOrderServiceV2(WlyyPrescriptionExpressageDO sfexpress_obj, BaseOrgDO hospital,  BasePatientDO basePatientDO) {
    
        JSONObject params = new JSONObject();//请求参数
        JSONArray orders = new JSONArray();//订单集合
        JSONObject order = new JSONObject();//单个订单
        order.put("bspOrderNo",sfexpress_obj.getId());
        order.put("payMethod",2);//付款方式到付
        order.put("expressType",1);//使用顺丰标快
        order.put("patientName",basePatientDO.getName());
        order.put("patientPhone",basePatientDO.getMobile());
        order.put("patientIdentityCardNo",basePatientDO.getIdcard());
    
        order.put("srcName",hospital.getName());
        order.put("srcPhone",hospital.getMobile());
        order.put("srcProvince",hospital.getProvinceName());
        order.put("srcCity",hospital.getCityName());
        order.put("srcDistrict",hospital.getTownName());
        order.put("srcAddress",hospital.getAddress());
        
        order.put("destName",sfexpress_obj.getName());
        order.put("destPhone",sfexpress_obj.getMobile());
        order.put("destProvince",sfexpress_obj.getProvinceName());
        order.put("destCity",sfexpress_obj.getCityName());
        order.put("destDistrict",sfexpress_obj.getTownName());
        order.put("destAddress",sfexpress_obj.getStreetName()+sfexpress_obj.getAddress());
        
        order.put("packagesNo",1);
        order.put("depositumInfo","药品");
        order.put("productCode","OTHER");

        
        //根据快递物流获取门诊信息，根据门诊信息获取处方订单的药品详情
        List<WlyyPrescriptionDO> prescriptionDOList = prescriptionService.findByField("outpatientId",sfexpress_obj.getOutpatientId());
        
        Set<String> prescriptionIdSet = new HashSet<>();
        prescriptionDOList.forEach(
                onePrescription -> {
                    prescriptionIdSet.add(onePrescription.getId());
                }
        );
        List<WlyyPrescriptionInfoDO> prescriptionInfolist = prescriptionInfoDao.queryAllByPrescriptionIdInAndDel(prescriptionIdSet,1);
        
        if(!prescriptionInfolist.isEmpty()){
            order.put("depositumNo",prescriptionInfolist.size());
        }else{
            order.put("depositumNo",1);
        }
        
        orders.add(order);
        params.put("orderThirds",orders);
        return params;
    }
}
