package org.xyzh.common.utils;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;

/**
 * @description    ServletUtils.java文件描述：Servlet相关常用工具方法
 * @filename    ServletUtils.java
 * @author    yslg
 * @copyright xyzh
 * @since 2023-12-19
 */
public class ServletUtils {

	/**
	 * @description    获取请求的真实IP地址
	 * @param    request HTTP请求对象
	 * @return    客户端真实IP地址
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static String getClientIp(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (ip != null && ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
			// 多级代理时取第一个
			int idx = ip.indexOf(',');
			if (idx > -1) {
				ip = ip.substring(0, idx);
			}
			return ip.trim();
		}
		ip = request.getHeader("Proxy-Client-IP");
		if (ip != null && ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getHeader("WL-Proxy-Client-IP");
		if (ip != null && ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getRemoteAddr();
		return ip;
	}

	/**
	 * @description    向响应写出JSON字符串
	 * @param    response HTTP响应对象
	 * @param    json 要写出的JSON字符串
	 * @return    void
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static void writeJson(HttpServletResponse response, String json) throws IOException {
		response.setContentType("application/json;charset=UTF-8");
		PrintWriter writer = response.getWriter();
		writer.write(json);
		writer.flush();
		writer.close();
	}

	/**
	 * @description    获取请求参数（支持默认值）
	 * @param    request HTTP请求对象
	 * @param    name 参数名
	 * @param    defaultValue 默认值
	 * @return    参数值或默认值
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static String getParameter(HttpServletRequest request, String name, String defaultValue) {
		String value = request.getParameter(name);
		return value != null ? value : defaultValue;
	}

	/**
	 * @description    判断请求是否为Ajax
	 * @param    request HTTP请求对象
	 * @return    是否为Ajax请求
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static boolean isAjaxRequest(HttpServletRequest request) {
		String header = request.getHeader("X-Requested-With");
		return "XMLHttpRequest".equalsIgnoreCase(header);
	}

	/**
	 * @description    获取请求体内容
	 * @param    request HTTP请求对象
	 * @return    请求体内容
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static String getRequestBody(HttpServletRequest request) throws IOException {
		StringBuilder sb = new StringBuilder();
		BufferedReader reader = request.getReader();
		String line;
		while ((line = reader.readLine()) != null) {
			sb.append(line);
		}
		return sb.toString();
	}

	/**
	 * @description    重定向到指定URL
	 * @param    response HTTP响应对象
	 * @param    url 目标URL
	 * @return    void
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static void redirect(HttpServletResponse response, String url) throws IOException {
		response.sendRedirect(url);
	}

	/**
	 * @description    获取完整请求URL
	 * @param    request HTTP请求对象
	 * @return    完整URL
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static String getFullUrl(HttpServletRequest request) {
		StringBuilder url = new StringBuilder();
		url.append(request.getScheme()).append("://");
		url.append(request.getServerName());
		int port = request.getServerPort();
		if (("http".equals(request.getScheme()) && port != 80) || 
			("https".equals(request.getScheme()) && port != 443)) {
			url.append(":").append(port);
		}
		url.append(request.getRequestURI());
		String queryString = request.getQueryString();
		if (queryString != null) {
			url.append("?").append(queryString);
		}
		return url.toString();
	}

	/**
	 * @description    判断请求是否为GET方法
	 * @param    request HTTP请求对象
	 * @return    是否为GET请求
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static boolean isGet(HttpServletRequest request) {
		return "GET".equalsIgnoreCase(request.getMethod());
	}

	/**
	 * @description    判断请求是否为POST方法
	 * @param    request HTTP请求对象
	 * @return    是否为POST请求
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static boolean isPost(HttpServletRequest request) {
		return "POST".equalsIgnoreCase(request.getMethod());
	}

	/**
	 * @description    判断请求是否为PUT方法
	 * @param    request HTTP请求对象
	 * @return    是否为PUT请求
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static boolean isPut(HttpServletRequest request) {
		return "PUT".equalsIgnoreCase(request.getMethod());
	}

	/**
	 * @description    判断请求是否为DELETE方法
	 * @param    request HTTP请求对象
	 * @return    是否为DELETE请求
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static boolean isDelete(HttpServletRequest request) {
		return "DELETE".equalsIgnoreCase(request.getMethod());
	}

	/**
	 * @description    获取所有请求参数
	 * @param    request HTTP请求对象
	 * @return    参数Map
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static Map<String, String> getParameterMap(HttpServletRequest request) {
		Map<String, String> paramMap = new HashMap<>();
		Enumeration<String> parameterNames = request.getParameterNames();
		while (parameterNames.hasMoreElements()) {
			String paramName = parameterNames.nextElement();
			String paramValue = request.getParameter(paramName);
			paramMap.put(paramName, paramValue);
		}
		return paramMap;
	}

	/**
	 * @description    获取请求头信息
	 * @param    request HTTP请求对象
	 * @return    头信息Map
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static Map<String, String> getHeaderMap(HttpServletRequest request) {
		Map<String, String> headerMap = new HashMap<>();
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String headerName = headerNames.nextElement();
			String headerValue = request.getHeader(headerName);
			headerMap.put(headerName, headerValue);
		}
		return headerMap;
	}

	/**
	 * @description    获取Cookie值
	 * @param    request HTTP请求对象
	 * @param    name Cookie名
	 * @return    Cookie值
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static String getCookieValue(HttpServletRequest request, String name) {
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (name.equals(cookie.getName())) {
					return cookie.getValue();
				}
			}
		}
		return null;
	}

	/**
	 * @description    设置Cookie
	 * @param    response HTTP响应对象
	 * @param    name Cookie名
	 * @param    value Cookie值
	 * @param    maxAge 过期时间(秒)
	 * @return    void
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) {
		Cookie cookie = new Cookie(name, value);
		cookie.setMaxAge(maxAge);
		cookie.setPath("/");
		cookie.setHttpOnly(true);
		response.addCookie(cookie);
	}

	/**
	 * @description    删除Cookie
	 * @param    response HTTP响应对象
	 * @param    name Cookie名
	 * @return    void
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static void removeCookie(HttpServletResponse response, String name) {
		Cookie cookie = new Cookie(name, null);
		cookie.setMaxAge(0);
		cookie.setPath("/");
		response.addCookie(cookie);
	}

	/**
	 * @description    判断是否为HTTPS请求
	 * @param    request HTTP请求对象
	 * @return    是否为HTTPS请求
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static boolean isHttps(HttpServletRequest request) {
		return "https".equals(request.getScheme()) || request.isSecure() || 
			"443".equals(request.getHeader("X-Forwarded-Port")) || 
			"https".equals(request.getHeader("X-Forwarded-Proto"));
	}

	/**
	 * @description    获取上下文路径
	 * @param    request HTTP请求对象
	 * @return    上下文路径
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static String getContextPath(HttpServletRequest request) {
		return request.getContextPath();
	}

	/**
	 * @description    检测请求是否包含指定参数
	 * @param    request HTTP请求对象
	 * @param    paramName 参数名
	 * @return    是否包含参数
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static boolean hasParameter(HttpServletRequest request, String paramName) {
		return request.getParameter(paramName) != null;
	}

	/**
	 * @description    获取Session对象
	 * @param    request HTTP请求对象
	 * @return    HttpSession对象
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static HttpSession getSession(HttpServletRequest request) {
		return request.getSession();
	}

	/**
	 * @description    获取Session属性
	 * @param    request HTTP请求对象
	 * @param    attributeName 属性名
	 * @return    属性值
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static Object getSessionAttribute(HttpServletRequest request, String attributeName) {
		HttpSession session = request.getSession(false);
		return session != null ? session.getAttribute(attributeName) : null;
	}

	/**
	 * @description    设置Session属性
	 * @param    request HTTP请求对象
	 * @param    attributeName 属性名
	 * @param    attributeValue 属性值
	 * @return    void
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static void setSessionAttribute(HttpServletRequest request, String attributeName, Object attributeValue) {
		request.getSession().setAttribute(attributeName, attributeValue);
	}

	/**
	 * @description    移除Session属性
	 * @param    request HTTP请求对象
	 * @param    attributeName 属性名
	 * @return    void
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static void removeSessionAttribute(HttpServletRequest request, String attributeName) {
		HttpSession session = request.getSession(false);
		if (session != null) {
			session.removeAttribute(attributeName);
		}
	}

	/**
	 * @description    防止XSS攻击的字符串过滤
	 * @param    input 输入字符串
	 * @return    过滤后的字符串
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static String escapeXss(String input) {
		if (input == null) {
			return null;
		}
		return input
				.replace("<", "&lt;")
				.replace(">", "&gt;")
				.replace("'", "&#39;")
				.replace("\"", "&quot;")
				.replace("&", "&amp;");
	}

	/**
	 * @description    获取所有请求参数名
	 * @param    request HTTP请求对象
	 * @return    参数名集合
	 * @author    yslg
	 * @since 2023-12-19
	 */
	public static Set<String> getParameterNames(HttpServletRequest request) {
		Set<String> paramNames = new HashSet<>();
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			paramNames.add(names.nextElement());
		}
		return paramNames;
	}
}