package com.wechat.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONObject;
import com.beust.jcommander.internal.Maps;
import com.wechat.common.utils.MessageUtils;
import com.wechat.common.utils.SSLClient;
import com.wechat.common.utils.StringsUtils;
import com.wechat.model.dbEntity.MdeTrends;
import com.wechat.model.dto.AuzAccesTokenDto;
import com.wechat.model.dto.AuzUserInfoDto;
import com.wechat.model.dto.LinkedInTokenDto;
import com.wechat.model.dto.LinkedUserInfo;

/**
 * 网页授权获取用户信息
 */
@Service
public class AuthorizedService {

	private static final Log log = LogFactory.getLog(AuthorizedService.class);

	// 用户唯一凭证 pc端(网页版)
	@Value("#{configProperties['weixin.open.appid']}")
	private String appIdPc;

	// 用户唯一凭证秘钥 pc端(网页版)
	@Value("#{configProperties['weixin.open.secret']}")
	private String appSecretPc;

	// 用户唯一凭证 手机端
	@Value("#{configProperties['weixin.appid']}")
	private String appIdMobile;

	// 用户唯一凭证秘钥 手机端
	@Value("#{configProperties['weixin.secret']}")
	private String appSecretMobile;

	// 请求授权access_token路径
	@Value("#{configProperties['weixin.authorization.tokenUrl']}")
	private String wxAuzTokenUrl;

	// 拉取用户信息路径 pc端
	@Value("#{configProperties['weixin.authorization.userinfo']}")
	private String wxAuzUserinfoUrlPc;

	// 拉取用户信息路径 手机端
	@Value("#{configProperties['weixin.userinfo']}")
	private String wxAuzUserinfoUrlMobile;

	// 重新获取access_token时间
	@Value("#{configProperties['weixin.reTime']}")
	private String reTime;

	// 用户唯一凭证
	@Value("#{configProperties['linkedIn.clientId']}")
	private String linkedInAppId;

	// 用户唯一凭证秘钥
	@Value("#{configProperties['linkedIn.clientSecret']}")
	private String linkedInSecret;

	// 请求授权access_token路径
	@Value("#{configProperties['linkedIn.TokenUrl']}")
	private String linkedInTokenUrl;

	@Value("#{configProperties['linkedIn.UserURl']}")
	private String linkedUserUrl;

	@Value("#{configProperties['linkedIn.grantType']}")
	private String authorizationCode;

	@Value("#{configProperties['linkedIn.redirect_url']}")
	private String redirectUrl;
	
	@Resource
	private WeiXinService wxservice;

	/**
	 * pc端token获取 注：appId，appSecret 是pc端申请返回 微信获取access_token类型的属性
	 * 
	 * @return
	 */
	public AuzAccesTokenDto getAccessTokenDto(String code, String loginModel) {
		// 获取accessToken的url
		String url = "";
		if (loginModel.equals("0")) {
			// pc 端登录
			url = MessageUtils.getText(wxAuzTokenUrl, appIdPc, appSecretPc, code);
		} else {
			// 手机端登录
			url = MessageUtils.getText(wxAuzTokenUrl, appIdMobile, appSecretMobile, code);
		}
		AuzAccesTokenDto auzAccesTokenDto = getRemoteResponseAsJson(url, AuzAccesTokenDto.class);

		// 基本token 及openid
		if (null != auzAccesTokenDto) {
			if (StringsUtils.isEmpty(auzAccesTokenDto.getOpenid())) {
				log.error("通过code换取网页授权access_token异常！ code:【" + code + "】");
				log.error("errcode:【" + auzAccesTokenDto.getErrorCode() + "】");
				log.error("errmsg:【" + auzAccesTokenDto.getErrorMsg() + "】");
				return null;
			}
		}
		return auzAccesTokenDto;
	}

	/**
	 * 微信拉取用户信息
	 * 
	 * @param code
	 * @param loginModel
	 *            登录来源0.pc 1.移动端
	 * @return
	 */
	public AuzUserInfoDto getUserInfoDetail(String code, String loginModel) {
		// 获取accessToken
		AuzAccesTokenDto auzAccesTokenDto = getAccessTokenDto(code, loginModel);
		// 用户基本信息
		AuzUserInfoDto auzUserInfoDto = null;
		String userInfoUrl = "";
		if (null != auzAccesTokenDto) {
			// 拉取用户信息
			if (loginModel.equals("0")) {
				// pc端
				userInfoUrl = MessageUtils.getText(wxAuzUserinfoUrlPc, auzAccesTokenDto.getAccessToken(),
						auzAccesTokenDto.getOpenid());
			} else {
				// 手机端 
				userInfoUrl = MessageUtils.getText(wxAuzUserinfoUrlMobile, wxservice.getAccessToken(),
						auzAccesTokenDto.getOpenid());
			}

			auzUserInfoDto = getRemoteResponseAsJson(userInfoUrl, AuzUserInfoDto.class);

			if (auzUserInfoDto != null) {
				if (StringsUtils.isEmpty(auzUserInfoDto.getOpenid())) {
					log.error("拉取用户信息异常！");
					log.error("errcode:【" + auzAccesTokenDto.getErrorCode() + "】");
					log.error("errmsg:【" + auzAccesTokenDto.getErrorMsg() + "】");
					return null;
				}
			}

		}
		return auzUserInfoDto;
	}

	/**
	 * 获取领英令牌access_token
	 * 
	 * @param code
	 * @param state
	 */
	public LinkedInTokenDto getLinkedInTokenDto(String code) {
		Map<String, String> maps = Maps.newHashMap();
		maps.put("client_id", linkedInAppId);
		maps.put("client_secret", linkedInSecret);
		maps.put("code", code);
		maps.put("grant_type", authorizationCode);
		maps.put("redirect_uri", redirectUrl);

		String json = doPost(linkedInTokenUrl, maps, "UTF-8");
		// 获取accessToken信息
		net.sf.json.JSONObject fromObject = net.sf.json.JSONObject.fromObject(json);
		if (fromObject.containsKey("access_token") && fromObject.containsKey("expires_in")) {
			String accessToken = fromObject.getString("access_token");
			String expiresInStr = fromObject.getString("expires_in");
			LinkedInTokenDto linked = new LinkedInTokenDto();
			linked.setAccessToken(accessToken);
			linked.setExpiresIn(expiresInStr);
			return linked;
		}
		return null;
	}

	/**
	 * 获取领英用户基本信息
	 * 
	 * @param linkedInTokenDto
	 * @return
	 */
	public LinkedUserInfo getLinkedUserInfo(LinkedInTokenDto linkedInTokenDto) {
		// 用accessToken 获取用户信息
		String accessToken = linkedInTokenDto.getAccessToken();
		String result = doGet(linkedUserUrl, "Bearer " + accessToken);
		LinkedUserInfo linkedUserInfo = JSONObject.parseObject(result, LinkedUserInfo.class);
		return linkedUserInfo;

	}

	/**
	 * 该方法强制设置 TLSv1.2
	 * 
	 * @param url
	 *            领英token地址
	 * @param map
	 *            参数
	 * @param charset
	 *            utf-8
	 * @return
	 */
	public String doPost(String url, Map<String, String> map, String charset) {
		HttpPost httpPost = null;
		String result = null;
		try {
			SSLClient httpClient = new SSLClient();
			httpPost = new HttpPost(url);
			// 设置参数
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			Iterator iterator = map.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
				list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
			}
			if (list.size() > 0) {
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
				entity.setContentType("application/x-www-form-urlencoded");
				httpPost.setEntity(entity);
			}
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					result = EntityUtils.toString(resEntity, charset);
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return result;
	}

	public String doGet(String strURL, String authorizationStr) {
		try {
			SSLClient client = new SSLClient();
			// 发送get请求
			HttpGet request = new HttpGet(strURL);
			request.setHeader("Authorization", authorizationStr);
			HttpResponse response = client.execute(request);

			/** 请求发送成功，并得到响应 **/
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				/** 读取服务器返回过来的json字符串数据 **/
				String strResult = EntityUtils.toString(response.getEntity());

				return strResult;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 通过HTTP Get请求外部数据,以JSON格式直接返回
	 * 
	 * @param url
	 *            要访问的地址
	 * @param classofResp需要格式化的目标类型
	 * @return 将远端返回的JSON格式化后输出
	 */
	static <T> T getRemoteResponseAsJson(String url, Class<T> classofResp) {
		try {
			URL obj = new URL(url);
			HttpURLConnection con = (HttpURLConnection) obj.openConnection();

			// add reuqest header
			con.setRequestMethod("GET");
			con.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");

			// Send post request
			con.setDoOutput(true);

			BufferedReader in = new BufferedReader(
					new InputStreamReader(con.getInputStream(), Charset.forName("UTF-8")));
			String inputLine;
			StringBuffer response = new StringBuffer();

			while ((inputLine = in.readLine()) != null) {
				response.append(inputLine);
			}
			in.close();
			log.info("Get response: " + response.toString());
			return JSONObject.parseObject(response.toString(), classofResp);
		} catch (Exception ex) {
			log.error("Network error.", ex);
			return null;
		}
	}
	/**
	 * 分享动态到领英
	 * @param linkedInTokenDto
	 * @param trend
	 */
	public void shareTrendToLinkedIn(LinkedInTokenDto linkedInTokenDto, MdeTrends trend) {
		// TODO Auto-generated method stub
		
	}
	public String sendContentToLinkedIn(String url,Map<String, Object> map,String accessToken) {
		HttpPost httpPost = null;
		String result = null;
		String charset = "UTF-8";
		try {
			@SuppressWarnings("resource")
			SSLClient httpClient = new SSLClient();
			httpPost = new HttpPost(url);
			// 设置用户授权
			httpPost.setHeader("Authorization", "Bearer " + accessToken);
			httpPost.setHeader("Content-type", "application/json; charset=utf-8");// 必填
			httpPost.setHeader("x-li-format", "json");// 必填
			
			// 设置参数
			// 构建消息实体
	        StringEntity entity = new StringEntity(JSONUtils.toJSONString(map), Charset.forName(charset));
	        entity.setContentEncoding("UTF-8");
	        // 发送Json格式的数据请求
	        entity.setContentType("application/json");
	        httpPost.setEntity(entity);
	        
	        /*List<NameValuePair> list = new ArrayList<NameValuePair>();
			for(Entry<String, String> entry : map.entrySet()){
				list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
	        }*/
			
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					result = EntityUtils.toString(resEntity, charset);
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return result;
	}
}
