package org.camunda.bpm.extension.keycloak.sso;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Cookie;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * Keycloak Logout Handler.
 * Provides logout functionality for keycloak.
 */
@Service
public class KeycloakLogoutHandler implements LogoutSuccessHandler {

	/** This class' logger. */
	private static final Logger LOG = LoggerFactory.getLogger(KeycloakLogoutHandler.class);
	
	/** Redirect strategy. */
	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
	
	/** Keycloak's logout URI. */
	private String oauth2UserLogoutUri;

	/** Keycloak's Client ID. */
	@Value("${keycloak.clientId}")
	private String clientId;

	/**
	 * Default constructor.
	 * @param oauth2UserAuthorizationUri configured keycloak authorization URI
	 */
	public KeycloakLogoutHandler(@Value("${spring.security.oauth2.client.provider.keycloak.authorization-uri:}") String oauth2UserAuthorizationUri) {
		if (!ObjectUtils.isEmpty(oauth2UserAuthorizationUri)) {
			// in order to get the valid logout uri: simply replace "/auth" at the end of the user authorization uri with "/logout"
			this.oauth2UserLogoutUri = oauth2UserAuthorizationUri.replace("openid-connect/auth", "openid-connect/logout");
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException {

		if (!ObjectUtils.isEmpty(oauth2UserLogoutUri)) {
			// Calculate redirect URI for Keycloak, something like http://<host:port>/camunda/login
			var requestUrl = request.getRequestURL().toString();
			var redirectUri = requestUrl.substring(0, requestUrl.indexOf("/app"));
			// Complete logout URL
			var logoutUrl = oauth2UserLogoutUri + "?post_logout_redirect_uri=" + redirectUri + "&client_id=" + clientId;
			Cookie[] cookies = request.getCookies();
			for (Cookie cookie : cookies) {
				LOG.debug("-------cookie---------->"+cookie.getName());
				cookie.setMaxAge(0);
				cookie.setValue(null);
				cookie.setPath("/camunda");
				response.addCookie(cookie);
			}
			LOG.debug("-------context path---------->"+request.getContextPath());

			//To remove JSESSIONID
			Cookie cookieWithSlash = new Cookie("JSESSIONID", null);
			//Tomcat adds extra slash at the end of context path (e.g. "/foo/")
			cookieWithSlash.setPath(request.getContextPath() + "/");
			cookieWithSlash.setMaxAge(0);

			Cookie cookieWithoutSlash = new Cookie("JSESSIONID", null);
			//JBoss doesn't add extra slash at the end of context path (e.g. "/foo")
			cookieWithoutSlash.setPath(request.getContextPath());
			cookieWithoutSlash.setMaxAge(0);

			//Remove cookies on logout so that invalidSessionURL (session timeout) is not displayed on proper logout event
			response.addCookie(cookieWithSlash); //For Tomcat
			response.addCookie(cookieWithoutSlash); //For JBoss
			// Do logout by redirecting to Keycloak logout
			LOG.debug("Redirecting to logout URL {}", logoutUrl);
			redirectStrategy.sendRedirect(request, response, logoutUrl);
		}
	}	
	
}
