package com.kingdee.eas.custom.webbeisen.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.interfacelog.businessoperationlog.*;
import com.kingdee.eas.custom.interfacelog.enumdata.RequestStatusEnum;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
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.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 提供一些常用的HTTP请求和文件下载的辅助方法。
 */
public class Helper {
	// 上下文对象，用于与Kingdee BOS系统交互
	public Context context;

	/**
	 * 构造函数，初始化上下文对象
	 *
	 * @param context 上下文对象
	 */
	public Helper(Context context) {
		this.context = context;
	}

	/**
	 * 发送HTTP请求并返回JSON格式的响应，同时记录操作日志
	 *
	 * @param url          请求的URL地址
	 * @param header       请求头信息，键值对形式
	 * @param requestBody  请求体，以JSONObject形式表示
	 * @param method       请求方法，支持"GET"、"POST"、"PUT"
	 * @param businessId   业务ID
	 * @param operate      操作名称
	 * @param businessName 业务名称
	 * @return 服务器返回的JSON对象
	 * @throws URISyntaxException      如果URL格式不正确
	 * @throws JSONException           如果JSON解析错误
	 * @throws IOException             如果发生I/O错误
	 * @throws ClientProtocolException 如果HTTP协议错误
	 */
	public JSONObject getURL(String url, Map<String, String> header, JSONObject requestBody, String method,
							 String businessId, String operate, String businessName)
			throws URISyntaxException, JSONException, ClientProtocolException, IOException {
		// 根据业务ID和业务名称获取操作日志信息
		OperateLogInfo operateLogInfo = getOperateLogInfoByBusinessId(businessId, businessName);
		// 获取操作日志的条目集合
		OperateLogEntryCollection entrys = operateLogInfo.getEntrys();
		// 如果条目集合为空，则初始化一个新的集合
		if (entrys == null) {
			entrys = new OperateLogEntryCollection();
		}
		// 创建一个新的操作日志条目
		OperateLogEntryInfo operateLogEntryInfo = new OperateLogEntryInfo();
		// 设置请求的URL
		operateLogEntryInfo.setUrl(url);
		// 将请求体转换为字符串
		String requestBodyString = requestBody.toString();
		// 如果请求体字符串长度超过1500，则截取前1500个字符
		if (requestBodyString.length() > 1500) {
			requestBodyString = requestBodyString.substring(0, 1500);
		}
		// 设置请求体到操作日志条目
		operateLogEntryInfo.setRequestBody(requestBodyString);
		// 将请求头信息转换为JSON字符串
		String jsonString = JSONObject.toJSONString(header);
		// 如果请求头JSON字符串长度超过1500，则截取前1500个字符
		if (jsonString.length() > 1500) {
			jsonString = jsonString.substring(0, 1500);
		}
		// 设置请求头到操作日志条目
		operateLogEntryInfo.setHeaded(jsonString);
		// 设置操作名称到操作日志条目
		operateLogEntryInfo.setOperate(operate);
		// 设置请求方法到操作日志条目
		operateLogEntryInfo.setMethod(method);

		// 用于存储服务器返回的JSON对象
		JSONObject responseJson = new JSONObject();
		HttpResponse response;
		// 创建一个默认的HTTP客户端
		CloseableHttpClient httpClient = HttpClients.createDefault();

		if ("GET".equals(method)) {
			// 创建一个URIBuilder对象，用于构建包含请求参数的URL
			URIBuilder uriBuilder = new URIBuilder(url);
			// 获取请求体中的所有键
			Set<String> strings = requestBody.keySet();
			// 遍历请求体中的键值对，将其添加到URL的查询参数中
			for (String string : strings) {
				String key = string;
				String value = requestBody.getString(key);
				uriBuilder.addParameter(key, value);
			}
			// 创建一个HTTP GET请求
			HttpGet httpGet = new HttpGet(uriBuilder.build());
			// 遍历请求头信息，将其添加到HTTP GET请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpGet.addHeader(entry.getKey(), entry.getValue());
			}
			// 执行HTTP GET请求
			response = httpClient.execute(httpGet);
		} else if ("POST".equals(method)) {
			// 创建一个HTTP POST请求
			HttpPost httpPost = new HttpPost(url);
			// 遍历请求头信息，将其添加到HTTP POST请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpPost.addHeader(entry.getKey(), entry.getValue());
			}
			// 创建一个StringEntity对象，将请求体以UTF-8编码包装
			StringEntity requestEntity = new StringEntity(requestBody.toString(), "UTF-8");
			// 设置请求体到HTTP POST请求中
			httpPost.setEntity(requestEntity);
			// 执行HTTP POST请求
			response = httpClient.execute(httpPost);
		} else if ("PUT".equals(method)) {
			// 创建一个HTTP PUT请求
			HttpPut httpPut = new HttpPut(url);
			// 遍历请求头信息，将其添加到HTTP PUT请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpPut.addHeader(entry.getKey(), entry.getValue());
			}
			// 创建一个StringEntity对象，将请求体以UTF-8编码包装
			StringEntity requestEntity = new StringEntity(requestBody.toString(), "UTF-8");
			// 设置请求体到HTTP PUT请求中
			httpPut.setEntity(requestEntity);
			// 执行HTTP PUT请求
			response = httpClient.execute(httpPut);
		} else {
			// 如果请求方法不支持，设置错误信息和请求状态到操作日志条目
			operateLogEntryInfo.setErrorInfo("Unsupported HTTP method: " + method);
			operateLogEntryInfo.setRequestStatus(RequestStatusEnum.ABNORMAL);
			// 将操作日志条目添加到条目集合中
			entrys.add(operateLogEntryInfo);
			try {
				// 保存操作日志信息
				OperateLogFactory.getLocalInstance(context).save(operateLogInfo);
			} catch (BOSException e) {
				throw new RuntimeException(e);
			} catch (EASBizException e) {
				throw new RuntimeException(e);
			}
			// 抛出不支持的HTTP方法异常
			throw new IllegalArgumentException("Unsupported HTTP method: " + method);
		}

		// 将响应实体转换为字符串
		String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
		// 将响应字符串解析为JSON对象
		responseJson = JSONObject.parseObject(responseBody);
		System.out.println(responseBody);
		// 用于存储响应数据日志
		String dataLog = "";
		// 如果响应体字符串长度超过1500，则截取前1500个字符
		String string = responseJson.toString();
		if (string.length() > 1500) {
			dataLog = string.substring(0, 1500);
		}else {
			dataLog = string.toString();
		}
		// 设置返回值到操作日志条目
		operateLogEntryInfo.setReturnValue(dataLog);
		// 获取响应中的状态码
		String code = responseJson.getString("code");
		// 根据状态码设置请求状态到操作日志条目
		if (code == null || !code.equals("200")) {
			operateLogEntryInfo.setRequestStatus(RequestStatusEnum.ABNORMAL);
		} else {
			operateLogEntryInfo.setRequestStatus(RequestStatusEnum.NORMAL);
		}
		try {
			entrys.add(operateLogEntryInfo);
			// 保存操作日志信息
			OperateLogFactory.getLocalInstance(context).save(operateLogInfo);
		} catch (BOSException e) {
			throw new RuntimeException(e);
		} catch (EASBizException e) {
			throw new RuntimeException(e);
		}
		// 关闭HTTP客户端
		httpClient.close();
		return responseJson;
	}

	/**
	 * 根据业务ID和业务名称获取操作日志信息
	 *
	 * @param businessId   业务ID
	 * @param businessName 业务名称
	 * @return 操作日志信息对象
	 */
	public OperateLogInfo getOperateLogInfoByBusinessId(String businessId, String businessName) throws UnsupportedEncodingException {
		if (businessId != null && !businessId.equals("")) {
			businessId = URLDecoder.decode(businessId,"UTF-8");
			OperateLogCollection operateLogCollection = null;
			try {
				// 获取操作日志集合
				operateLogCollection = OperateLogFactory.getLocalInstance(context).getOperateLogCollection("where businessId='"+businessId+"' ");
				if (operateLogCollection.size() > 0) {
					// 如果集合中有元素，返回第一个元素
					return operateLogCollection.get(0);
				} else {
					// 如果集合为空，创建一个新的操作日志信息对象并设置业务ID和业务名称
					OperateLogInfo operateLogInfo = new OperateLogInfo();
					operateLogInfo.setBusinessId(businessId);
					operateLogInfo.setBusinessName(businessName);
					return operateLogInfo;
				}
			} catch (BOSException e) {
				throw new RuntimeException(e);
			}
		} else {
			// 如果业务ID为空，创建一个新的操作日志信息对象并设置业务名称
			OperateLogInfo operateLogInfo = new OperateLogInfo();
			operateLogInfo.setBusinessName(businessName);
			return operateLogInfo;
		}
	}

	/**
	 * 发送HTTP请求并返回JSON格式的响应，请求体为JSONArray类型
	 *
	 * @param url         请求的URL地址
	 * @param header      请求头信息，键值对形式
	 * @param requestBody 请求体，以JSONArray形式表示
	 * @param method      请求方法，支持"GET"、"POST"、"PUT"
	 * @return 服务器返回的JSON对象
	 * @throws URISyntaxException      如果URL格式不正确
	 * @throws JSONException           如果JSON解析错误
	 * @throws IOException             如果发生I/O错误
	 * @throws ClientProtocolException 如果HTTP协议错误
	 */
	public JSONObject getURL(String url, Map<String, String> header, JSONArray requestBody, String method)
			throws URISyntaxException, JSONException, ClientProtocolException, IOException {
		// 用于存储服务器返回的JSON对象
		JSONObject responseJson = new JSONObject();
		HttpResponse response;
		// 创建一个默认的HTTP客户端
		CloseableHttpClient httpClient = HttpClients.createDefault();

		if ("GET".equals(method)) {
			// 创建一个URIBuilder对象，用于构建包含请求参数的URL
			URIBuilder uriBuilder = new URIBuilder(url);
			// 创建一个列表，用于存储请求参数
			List paramList = new ArrayList();
			// 遍历JSONArray中的元素，将其添加到参数列表中
			for (int i = 0; i < requestBody.size(); i++) {
				paramList.add(requestBody.get(i));
			}
			// 将参数列表添加到URL的查询参数中
			uriBuilder.addParameters(paramList);
			// 创建一个HTTP GET请求
			HttpGet httpGet = new HttpGet(uriBuilder.build());
			// 遍历请求头信息，将其添加到HTTP GET请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpGet.addHeader(entry.getKey(), entry.getValue());
			}
			// 执行HTTP GET请求
			response = httpClient.execute(httpGet);
		} else if ("POST".equals(method)) {
			// 创建一个HTTP POST请求
			HttpPost httpPost = new HttpPost(url);
			// 遍历请求头信息，将其添加到HTTP POST请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpPost.addHeader(entry.getKey(), entry.getValue());
			}
			// 创建一个StringEntity对象，将请求体以UTF-8编码包装
			StringEntity requestEntity = new StringEntity(requestBody.toString(), "UTF-8");
			// 设置请求体到HTTP POST请求中
			httpPost.setEntity(requestEntity);
			// 执行HTTP POST请求
			response = httpClient.execute(httpPost);
		} else if ("PUT".equals(method)) {
			// 创建一个HTTP PUT请求
			HttpPut httpPut = new HttpPut(url);
			// 遍历请求头信息，将其添加到HTTP PUT请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpPut.addHeader(entry.getKey(), entry.getValue());
			}
			// 创建一个StringEntity对象，将请求体以UTF-8编码包装
			StringEntity requestEntity = new StringEntity(requestBody.toString(), "UTF-8");
			// 设置请求体到HTTP PUT请求中
			httpPut.setEntity(requestEntity);
			// 执行HTTP PUT请求
			response = httpClient.execute(httpPut);
		} else {
			// 如果请求方法不支持，抛出不支持的HTTP方法异常
			throw new IllegalArgumentException("Unsupported HTTP method: " + method);
		}

		// 将响应实体转换为字符串
		String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
		// 将响应字符串解析为JSON对象
		responseJson = JSONObject.parseObject(responseBody);
		// 关闭HTTP客户端
		httpClient.close();
		return responseJson;
	}

	/**
	 * 发送编码后的HTTP请求并返回JSON格式的响应
	 *
	 * @param url         请求的URL地址
	 * @param header      请求头信息，键值对形式
	 * @param requestBody 请求体，以JSONObject形式表示
	 * @param method      请求方法，支持"GET"、"POST"、"PUT"
	 * @return 服务器返回的JSON对象
	 * @throws URISyntaxException      如果URL格式不正确
	 * @throws JSONException           如果JSON解析错误
	 * @throws IOException             如果发生I/O错误
	 * @throws ClientProtocolException 如果HTTP协议错误
	 */
	public JSONObject getURLEncoded(String url, Map<String, String> header, JSONObject requestBody, String method)
			throws URISyntaxException, JSONException, ClientProtocolException, IOException {
		// 用于存储服务器返回的JSON对象
		JSONObject responseJson = new JSONObject();
		HttpResponse response;
		// 创建一个默认的HTTP客户端
		CloseableHttpClient httpClient = HttpClients.createDefault();

		if ("GET".equals(method)) {
			// 创建一个URIBuilder对象，用于构建包含请求参数的URL
			URIBuilder uriBuilder = new URIBuilder(url);
			// 创建一个HTTP GET请求
			HttpGet httpGet = new HttpGet(uriBuilder.build());
			// 遍历请求头信息，将其添加到HTTP GET请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpGet.addHeader(entry.getKey(), entry.getValue());
			}
			// 获取请求体中的所有键
			Set<String> strings = requestBody.keySet();
			// 遍历请求体中的键值对，将其添加到URL的查询参数中
			for (String string : strings) {
				String key = string;
				String value = requestBody.getString(key);
				uriBuilder.addParameter(key, value);
			}
			// 执行HTTP GET请求
			response = httpClient.execute(httpGet);
		} else if ("POST".equals(method)) {
			// 创建一个HTTP POST请求
			HttpPost httpPost = new HttpPost(url);
			// 遍历请求头信息，将其添加到HTTP POST请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpPost.addHeader(entry.getKey(), entry.getValue());
			}
			// 创建一个列表，用于存储请求参数
			ArrayList<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();
			// 获取请求体中的所有键
			Set<String> strings = requestBody.keySet();
			// 遍历请求体中的键值对，将其添加到参数列表中
			for (String string : strings) {
				String key = (String) string;
				String value = requestBody.getString(key);
				list.add(new BasicNameValuePair(key, value));
			}
			// 创建一个UrlEncodedFormEntity对象，将参数列表以UTF-8编码包装
			httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
			// 执行HTTP POST请求
			response = httpClient.execute(httpPost);
		} else if ("PUT".equals(method)) {
			// 创建一个HTTP PUT请求
			HttpPut httpPut = new HttpPut(url);
			// 遍历请求头信息，将其添加到HTTP PUT请求中
			for (Entry<String, String> entry : header.entrySet()) {
				httpPut.addHeader(entry.getKey(), entry.getValue());
			}
			// 创建一个列表，用于存储请求参数
			ArrayList<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();
			// 获取请求体中的所有键
			Set<String> strings = requestBody.keySet();
			// 遍历请求体中的键值对，将其添加到参数列表中
			for (String string : strings) {
				String key = (String) string;
				String value = requestBody.getString(key);
				list.add(new BasicNameValuePair(key, value));
			}
			// 创建一个UrlEncodedFormEntity对象，将参数列表以UTF-8编码包装
			httpPut.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
			// 执行HTTP PUT请求
			response = httpClient.execute(httpPut);
		} else {
			// 如果请求方法不支持，抛出不支持的HTTP方法异常
			throw new IllegalArgumentException("Unsupported HTTP method: " + method);
		}

		// 将响应实体转换为字符串
		String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
		// 将响应字符串解析为JSON对象
		responseJson = JSONObject.parseObject(responseBody);
		// 关闭HTTP客户端
		httpClient.close();
		return responseJson;
	}

	/**
	 * 通过网络URL获取文件的字节数组
	 *
	 * @param urlStr 文件的网络URL地址
	 * @return 文件的字节数组
	 * @throws IOException 如果发生I/O错误
	 */
	public byte[] getBytesByNetURL(String urlStr) throws IOException {
		// 创建一个URL对象
		URL url = new URL(urlStr);
		// 创建一个HTTP连接
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		// 设置连接超时时间为5秒
		conn.setConnectTimeout(5 * 1000);
		// 获取输入流，用于读取文件内容
		InputStream in = conn.getInputStream();
		// 创建一个ByteArrayOutputStream对象，用于存储文件内容
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len;
		// 循环读取文件内容，并写入到ByteArrayOutputStream中
		while ((len = in.read(buffer)) != -1) {
			outputStream.write(buffer, 0, len);
		}
		// 关闭输入流
		in.close();
		// 返回文件的字节数组
		return outputStream.toByteArray();
	}
}