package com.cesgroup.cesmonitor.service.weixin;

import java.io.IOException;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 微信接口工具类
 *
 * @author zhang.erwei
 * @version 1.0.0 2017年5月24日
 */
public class WxUtil {

    /*@Value("${weixin.templateId}")
    private String templateId;*/

    /** 微信获取access_token的调用接口 */
    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";

    //    /** 微信发送客服消息的调用接口 */
    //    private static final String SEND_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={0}";

    /** 微信获取关注用户信息的调用接口 */
    private static final String SUBSCRIBE_USERS_URL = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={0}&next_openid={1}";

    /** 微信获取用户基本信息的调用接口 */
    private static final String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN";
    //https://api.weixin.qq.com/sns/userinfo

    /** 微信模板消息调用接口 */
    private static final String TEMPLATE_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={0}";

    private static WxUtil wxUtil = new WxUtil();

    private String accessToken = null;

    private String appid = null;

    private String appsecret = null;

    private CloseableHttpClient client = HttpClients.createDefault();

    private WxUtil() {
        client = HttpClients.custom().addInterceptorFirst(new HttpRequestInterceptor() {

            @Override
            public void process(final HttpRequest request, final HttpContext context)
                throws HttpException, IOException {
                //request.addHeader("Content-Type", "text/html;charset=UTF-8");
            }
        }).addInterceptorLast(new HttpResponseInterceptor() {

            @Override
            public void process(final HttpResponse response, final HttpContext context)
                throws HttpException, IOException {

            }
        }).build();
    }

    /**
     * 获取微信发送工具实例
     *
     * @param appId
     *            微信appId
     * @param appsecret
     *            微信appsecret
     * @return 微信发送工具实例
     */
    public static WxUtil getInstance(final String appId, final String appsecret) {
        wxUtil.appid = appId;
        wxUtil.appsecret = appsecret;
        return wxUtil;
    }

    /**
     * 从微信获取access_token
     */
    @SuppressWarnings("unchecked")
    private synchronized void loadAccessToken(final String url) {
        try {
            String json = httpGet(url);
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Object> map = mapper.readValue(json, Map.class);
            accessToken = (String) map.get("access_token");
            Integer expiresIn = (Integer) map.get("expires_in");
            if (accessToken != null && expiresIn != null) {
                //定时获取下次
                if (expiresIn > 100) {
                    Timer timer = new Timer();
                    timer.schedule(new TimerTask() {

                        @Override
                        public void run() {
                            loadAccessToken(url);
                        }
                    }, (expiresIn - 100) * 1000);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取微信连接的access_token
     *
     * @return access_token
     */
    public String getAccessToken() {
        if (accessToken == null) {
            String url = MessageFormat.format(ACCESS_TOKEN_URL, appid, appsecret);
            loadAccessToken(url);
        }
        return accessToken;
    }

    /**
     * 发送报警信息
     *
     * @param openId
     *            用户openId
     * @param subject
     *            主题
     * @param content
     *            内容
     * @param time
     *            时间
     * @return 微信发送消息返回值，格式json
     */
    public synchronized String sendAlertMessage(final String openId, final String subject, final String content,
        final String time) {
        TemplateMessage message = new TemplateMessage();
        message.setTouser(openId);
        message.setTemplate_id("IkmNc6TYSLpSh9sUtJbGsQBsmaGgTK9Zve7EjqnknKU");
        // message.setTemplate_id("awkM_ToBvByadv80zdxcto__B9w63xaYae3evSR5M2Q");
        //message.setTemplate_id(templateId);
        message.addValue("first", subject);
        if (content != null) {
            message.addValue("content", content);
        } else {
            message.addValue("content", subject);
        }

        message.addValue("occurtime", time);
        message.addValue("remark", "");
        return this.sendTemplateMessage(message);
    }

    /**
     * 发送模板信息
     *
     * @param message
     *            模板消息
     * @return 微信发送消息返回值，格式json
     */
    public String sendTemplateMessage(final TemplateMessage message) {
        String json = null;
        String url = MessageFormat.format(TEMPLATE_MESSAGE_URL, getAccessToken());
        try {
            json = httpPost(url, message.toJson());
        } catch (Exception e) {
            throw new RuntimeException("微信发送消息失败", e);
        }

        return json;
    }

    /**
     * 通过HTTP的GET方式获取数据
     *
     * @param url
     *            url地址
     * @return hppt请求返回的字符串
     */
    private String httpGet(final String url) {
        String body = null;
        CloseableHttpResponse response = null;
        try {
            HttpGet request = new HttpGet(url);
            // 发送请求
            response = client.execute(request);
            // 获取返回数据
            HttpEntity entity = response.getEntity();
            body = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                    response = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return body;
    }

    /**
     * 通过HTTP的POST方式获取数据
     *
     * @param url
     *            url地址
     * @param json
     *            json数据
     * @return hppt请求返回的字符串
     */
    private String httpPost(final String url, final String json) {
        String body = null;
        CloseableHttpResponse response = null;
        try {
            HttpPost request = new HttpPost(url);
            // 构造参数
            StringEntity requestEntity = new StringEntity(json, ContentType.create("application/json", "UTF-8"));
            request.setEntity(requestEntity);
            // 发送请求
            response = client.execute(request);
            // 获取返回数据
            HttpEntity entity = response.getEntity();
            body = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                    response = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return body;
    }

    /**
     * 获取微信用户信息
     *
     * @param openid
     *            用户openId
     * @return 用户
     */
    public WxUser getWxUser(final String openid) {
        String url = MessageFormat.format(USER_INFO_URL, getAccessToken(), openid);
        String ret = httpGet(url);
        ObjectMapper mapper = new ObjectMapper();
        WxUser user = new WxUser();
        user.setId(openid);
        try {
            user = mapper.readValue(ret, WxUser.class);
            user.setId(user.getOpenid());
            user.setSubscribeTime(new Timestamp(user.getSubscribe_time() * 1000));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }

    /**
     * 获取微信用户信息
     *
     * @return 所有用户
     */
    public List<WxUser> getUsers() {
        List<WxUser> users = new ArrayList<WxUser>();
        String next = "";
        int total = 0;
        int count = 0;
        try {
            do {
                String url = MessageFormat.format(SUBSCRIBE_USERS_URL, getAccessToken(), next);
                String ret = httpGet(url);
                ObjectMapper mapper = new ObjectMapper();
                Map<String, Object> json = mapper.readValue(ret, Map.class);
                total = (Integer) json.get("total");
                count += (Integer) json.get("count");
                List idList = (List) ((Map) json.get("data")).get("openid");
                next = (String) json.get("next_openid");
                for (int i = 0; i < idList.size(); i++) {
                    String id = (String) idList.get(i);
                    WxUser user = getWxUser(id);
                    users.add(user);
                }
            }
            while (total > count && !(next == null || "".equals(next)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return users;
    }
}
