package com.cftech.mp.custservice.Utils;

import com.cftech.core.util.StringUtils;
import com.cftech.mp.custservice.Utils.trustmanager.CFX509TrustManager;
import net.sf.json.JSONObject;
import org.mp.api.core.common.WxstoreUtils;
import org.mp.api.custservice.multicustservice.JwMultiCustomerAPI;
import org.springframework.stereotype.Component;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Date;

/**
 * Created by Strive on 2017/4/19.
 */
@Component
public class CustserviceWXAPIUtils {

    private static String SUCCEED = "ok";

    /**
     * 调微信接口获取客户基础信息
     *
     * @param accessToken
     * @return
     */
    public String byWXAPIFindCustserviceListInfo(String accessToken) {
        String reqUrl = JwMultiCustomerAPI.GET_CUSTSERVICE_INFO_LIST_URL.replace("ACCESS_TOKEN", accessToken);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "GET", null);
        return String.valueOf(result);
    }

    /**
     * 调用微信接口创建多客服
     *
     * @param accessToken
     * @param kf_account  完整客服账号，格式为：账号前缀@公众号微信号，账号前缀最多10个字符，必须是英文或者数字字符。
     * @param nickname    客服昵称，最长6个汉字或12个英文字符
     * @param password    客服账号登录密码，格式为密码明文的32位加密MD5值
     * @return JSON String
     */
    public boolean byWXAPICreateCustservice(String accessToken, String kf_account, String nickname, String password) {
        //封装JSON数据
        JSONObject reqObj = new JSONObject();
        reqObj.put("kf_account", kf_account);
        reqObj.put("nickname", nickname);
        reqObj.put("password", password);

        String reqUrl = JwMultiCustomerAPI.ADD_CUSTSERVICE_ACCOUNT_URL.replace("ACCESS_TOKEN", accessToken);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "POST", String.valueOf(reqObj));
        return retResult(result);
    }

    /**
     * 调用微信接口更新客服信息
     *
     * @oaram @return 同上 byWXAPICreateCostService
     */
    public boolean byWXAPIUpdateCustservice(String accessToken, String kf_account, String nickname, String password) {
        JSONObject reqObj = new JSONObject();
        reqObj.put("kf_account", kf_account);
        reqObj.put("nickname", nickname);
        reqObj.put("password", password);
        String reqUrl = JwMultiCustomerAPI.UPDATE_CUSTSERVICE_INFO_URL.replace("ACCESS_TOKEN", accessToken);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "POST", String.valueOf(reqObj));
        return retResult(result);
    }

    /**
     * 上传客服头像
     *
     * @param accessToken
     * @param kf_account
     * @param media
     */
    public String byWXAPIUploadCustserviceAvatar(String accessToken, String kf_account, String fileName, InputStream media){
        //定义返回值
        String result = null;
        String reqUrl = JwMultiCustomerAPI.UPLOAD_HANDAVATAR_URL.replace("ACCESS_TOKEN", accessToken)//
            .replace("KFACCOUNT", kf_account);
        try {
            //安全证书
            SSLSocketFactory ssf = CFX509TrustManager.getSSFactory();

            URL url = new URL(reqUrl);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

            connection.setSSLSocketFactory(ssf);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);// post方式提交表单不能使用缓存
            connection.setRequestMethod("POST");// 使用post提交，默认get

            //设置请求头
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Charset", "UTF-8");
            //设置边界
            String boundary = "----------" + System.currentTimeMillis();
            connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

            //请求正文信息
            StringBuilder sb = new StringBuilder();
            sb.append("--"); //必须多两道线
            sb.append(boundary);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"media\",;filename=\"" + fileName + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");

            byte[] head = sb.toString().getBytes("utf-8");
            //获得输出流
            OutputStream out = new DataOutputStream(connection.getOutputStream());
            out.write(head);//输出表头

            //文件正文部分    把文件以流文件的方式,推入到url中
            DataInputStream in = new DataInputStream(media);
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            in.close();

            //结尾部分 最后数据分割线
            byte[] foot = ("\r\n--" + boundary + "--\r\n").getBytes("utf-8");
            out.write(foot);
            out.flush();
            out.close();

            //读取URL响应
            StringBuffer buffer = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }

            //返回数据
            if (result == null) {
                result = buffer.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 删除客服账号
     *
     * @param kf_account 客服账号
     * @return
     */
    public boolean byWXAPIDelCustservice(String accessToken, String kf_account) {
        JSONObject reqObj = new JSONObject();
        reqObj.put("kf_account", kf_account);
        String reqUrl = JwMultiCustomerAPI.DEL_CUSTSERVICE_INFO_URL.replace("ACCESS_TOKEN", accessToken);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "POST", String.valueOf(reqObj));
        return retResult(result);
    }

    /**
     * 创建多客服会话
     *
     * @param accessToken
     * @param kf_account  完整客服账号
     * @param openid      客户openid
     * @param text        附加信息，文本会展示在客服人员的多客服客户端（非必须）
     * @return
     */
    public boolean byWXAPICreateSession(String accessToken, String kf_account, String openid, String text) {
        JSONObject reqObj = new JSONObject();
        reqObj.put("kf_account", kf_account);
        reqObj.put("openid", openid);
        if (StringUtils.isNotBlank(text))
            reqObj.put("text", text);

        String reqUrl = JwMultiCustomerAPI.CREATE_CUSTSERVICE_SESSION_URL.replace("ACCESS_TOKEN", accessToken);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "POST", String.valueOf(reqObj));
        return retResult(result);
    }

    /**
     * 关闭多客服会话
     *
     * @param @return 同上
     */
    public boolean byWXAPICloseSession(String accessToken, String kf_account, String openid, String text) {
        JSONObject reqObj = new JSONObject();
        reqObj.put("kf_account", kf_account);
        reqObj.put("openid", openid);
        if (StringUtils.isNotBlank(text))
            reqObj.put("text", text);

        String reqUrl = JwMultiCustomerAPI.CLOSE_CUSTSERVICE_SESSION_URL.replace("ACCESS_TOKEN", accessToken);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "POST", String.valueOf(reqObj));
        return retResult(result);
    }

    /**
     * 获取客户的会话状态
     *
     * @param accessToken
     * @param openid
     * @return createtime 会话接入时间; errcode 错误码; kf_account 正在接待的客服，为空表示没有人在接待
     */
    public String byWXAPIFindSessionStatus(String accessToken, String openid) {
        String reqUrl = JwMultiCustomerAPI.GET_CUSTSERVCIE_SESSIONSTATUS_URL.replace("ACCESS_TOKEN", accessToken)//
                .replace("OPENID", openid);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "GET", null);
        return String.valueOf(result);
    }

    /**
     * 获取客服会话列表
     *
     * @param accessToken
     * @param kf_account
     * @return sessionlist 会话列表; sessionlist.createtime 会话创建时间，UNIX时间戳; sessionlist.openid 客户ipenid
     */
    public String byWXAPIFindSessionList(String accessToken, String kf_account) {
        String reqUrl = JwMultiCustomerAPI.GET_CUSTSERVCIE_SESSION_LIST_URL.replace("ACCESS_TOKEN", accessToken)//
                .replace("KFACCOUNT", kf_account);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "GET", null);
        return String.valueOf(result);
    }

    /**
     * 获取未接入会话列表
     *
     * @param accessToken
     * @return count 未接入会话数量; waitcaselist 未接入会话列表,最多返回100条;
     * waitcaselist.openid 客户openid; waitcaselist.kf_account 指定接待的客服,未空表示未指定; waicaselist.createtime 用户来访时间
     */
    public String byWXAPIFindSessionWaitcase(String accessToken) {
        String reqUrl = JwMultiCustomerAPI.GET_NOACCESS_SESSION_LIST_URL.replace("ACCESS_TOKEN", accessToken);
        JSONObject result = WxstoreUtils.httpRequest(reqUrl, "GET", null);
        return String.valueOf(result);
    }

    /**
     * 封装微信接入会话Xml
     * @param touser
     * @param fromuser
     * @param createTime
     * @param msgType
     * @param event
     * @param kfAccount
     * @return
     */
    public String joinUpSessionXml(String touser, String fromuser, String createTime, String msgType, String event, String kfAccount) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        sb.append("<ToUserName><![CDATA[" + touser + "]]></ToUserName>");
        sb.append("<FromUserName><![CDATA[" + fromuser + "]]></FromUserName>");
        sb.append("<CreateTime>" + new Date().getTime() + "</CreateTime>");
        sb.append("<MsgType><![CDATA[" + msgType + "]]></MsgType>");
        sb.append("<Event><![CDATA[" + event + "]]></Event>");
        sb.append("<KfAccount><![CDATA[" + kfAccount + "]]></KfAccount>");
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 封装微信关闭会话Xml
     * @param touser
     * @param fromuser
     * @param msgType
     * @param event
     * @param kf_close_session
     * @param kfAccount
     * @return
     */
    public String closeSessionXml(String touser, String fromuser, String msgType, String event, String kf_close_session, String kfAccount) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        sb.append("<ToUserName><![CDATA[" + touser + "]]></ToUserName>");
        sb.append("<FromUserName><![CDATA[" + fromuser + "]]></FromUserName>");
        sb.append("<CreateTime>" + new Date().getTime() + "</CreateTime>");
        sb.append("<MsgType><![CDATA[" + msgType + "]]></MsgType>");
        sb.append("<Event><![CDATA[" + kf_close_session + "]]></Event>");
        sb.append("<KfAccount><![CDATA[" + kfAccount + "]]></KfAccount>");
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 封装微信转接会话Xml
     * @param touser
     * @param fromuser
     * @param msgType
     * @param event
     * @param fromKfAccount
     * @param toKfAccount
     * @return
     */
    public String transpondSessionXml(String touser, String fromuser, String msgType, String event, String fromKfAccount, String toKfAccount) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        sb.append("<ToUserName><![CDATA[" + touser + "]]></ToUserName>");
        sb.append("<FromUserName><![CDATA[" + fromuser + "]]></FromUserName>");
        sb.append("<CreateTime>" + new Date().getTime() + "</CreateTime>");
        sb.append("<MsgType><![CDATA[" + msgType + "]]></MsgType>");
        sb.append("<Event><![CDATA[" + event + "]]></Event>");
        sb.append("<FromKfAccount><![CDATA[" + fromKfAccount + "]]></FromKfAccount>");
        sb.append("<ToKfAccount><![CDATA[" + toKfAccount + "]]></ToKfAccount>");
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * @param result
     * @return boolean
     */
    public boolean retResult(JSONObject result) {
        if (result.getInt("errcode") == 0 && StringUtils.equals(result.getString("errmsg"), SUCCEED))
            return true;
        return false;
    }

}
