package com.infoepoch.pms.agent.service.auth;

import com.infoepoch.pms.agent.common.utils.component.RedisTool;
import com.infoepoch.pms.agent.properties.SsoProperties;
import com.infoepoch.pms.agent.service.auth.dto.LoginSessionUser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

import java.util.concurrent.TimeUnit;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class LoginSessionServiceTest {

    private RedisTool redisTool;
    private LoginSessionService loginSessionService;

    @BeforeEach
    void setUp() {
        redisTool = mock(RedisTool.class);
        loginSessionService = new LoginSessionService(redisTool, ssoProperties());
    }

    @Test
    void createsLoginSessionCookieAndStoresUserInRedis() {
        MockHttpServletResponse response = new MockHttpServletResponse();
        LoginSessionUser user = new LoginSessionUser("user-1", "zhangsan", "张三", "org-1", "组织一");

        loginSessionService.createLoginSession(user, response);

        String setCookie = response.getHeader("Set-Cookie");
        assertThat(setCookie).contains("pms_agent_session=");
        assertThat(setCookie).contains("Path=/");
        assertThat(setCookie).contains("Max-Age=7200");
        assertThat(setCookie).contains("HttpOnly");
        assertThat(setCookie).contains("SameSite=Lax");
        verify(redisTool).put(eq("pms-agent:session:" + cookieValue(setCookie)), eq(user), eq(7200L), eq(TimeUnit.SECONDS));
    }

    @Test
    void getsCurrentUserFromSessionCookie() {
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setCookies(new jakarta.servlet.http.Cookie("pms_agent_session", "session-1"));
        LoginSessionUser user = new LoginSessionUser("user-1", "zhangsan", "张三", "org-1", "组织一");
        when(redisTool.get("pms-agent:session:session-1")).thenReturn(user);

        LoginSessionUser currentUser = loginSessionService.getCurrentUser(request);

        assertThat(currentUser).isEqualTo(user);
    }

    @Test
    void clearsSsoCookieWithPathAndMaxAgeZero() {
        MockHttpServletResponse response = new MockHttpServletResponse();

        loginSessionService.clearSsoCookie(response);

        String setCookie = response.getHeader("Set-Cookie");
        assertThat(setCookie).contains("pms_agent_sso_token=");
        assertThat(setCookie).contains("Path=/");
        assertThat(setCookie).contains("Max-Age=0");
        assertThat(setCookie).contains("HttpOnly");
        assertThat(setCookie).contains("SameSite=Lax");
    }

    @Test
    void clearsLoginSessionCookieAndRemovesRedisSession() {
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setCookies(new jakarta.servlet.http.Cookie("pms_agent_session", "session-1"));
        MockHttpServletResponse response = new MockHttpServletResponse();

        loginSessionService.clearLoginSession(request, response);

        String setCookie = response.getHeader("Set-Cookie");
        assertThat(setCookie).contains("pms_agent_session=");
        assertThat(setCookie).contains("Path=/");
        assertThat(setCookie).contains("Max-Age=0");
        assertThat(setCookie).contains("HttpOnly");
        assertThat(setCookie).contains("SameSite=Lax");
        verify(redisTool).remove("pms-agent:session:session-1");
    }

    private SsoProperties ssoProperties() {
        SsoProperties properties = new SsoProperties();
        properties.setCookieName("pms_agent_sso_token");
        properties.setSessionCookieName("pms_agent_session");
        properties.setSessionTtlSeconds(7200);
        return properties;
    }

    private String cookieValue(String setCookie) {
        return setCookie.substring("pms_agent_session=".length(), setCookie.indexOf(';'));
    }
}
