package com.intive.patronage.toz.passwords;

import com.intive.patronage.toz.config.ApiUrl;
import com.intive.patronage.toz.environment.ApiProperties;
import com.intive.patronage.toz.passwords.model.PasswordChangeRequestView;
import com.intive.patronage.toz.tokens.model.view.UserCredentialsView;
import com.intive.patronage.toz.users.UserService;
import com.intive.patronage.toz.users.model.db.User;
import com.intive.patronage.toz.util.ModelMapper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.MediaType;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import static com.intive.patronage.toz.config.ApiUrl.ACQUIRE_TOKEN_PATH;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest(
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        properties = {ApiProperties.JWT_SECRET_BASE64, ApiProperties.SUPER_ADMIN_PASSWORD}
)
@ActiveProfiles("test")
public class PasswordsControllerTest {

    private static final MediaType CONTENT_TYPE = MediaType.APPLICATION_JSON_UTF8;
    private static final String EMAIL = "user@mail.com";
    private static final String OLD_PASSWORD = "OldPassword";
    private static final String NEW_PASSWORD = "NewPassword";
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String TOKEN_PREFIX = "Bearer ";
    private static final User.Role USER_ROLE = User.Role.VOLUNTEER;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private UserService userService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private MessageSource messageSource;

    private User user;
    private String token;

    @Before
    public void setUp() throws Exception {
        final String passwordHash = passwordEncoder.encode(OLD_PASSWORD);
        user = new User();
        user.addRole(USER_ROLE);
        user.setEmail(EMAIL);
        userService.createWithPasswordHash(user, passwordHash);

        UserCredentialsView credentialsView = new UserCredentialsView(user.getEmail(), OLD_PASSWORD);
        MvcResult result = mockMvc.perform(post(ACQUIRE_TOKEN_PATH)
                .contentType(CONTENT_TYPE)
                .content(ModelMapper.convertToJsonString(credentialsView)))
                .andReturn();

        String response = result.getResponse().getContentAsString();
        token = response.substring("{\"jwt\":\"".length(), response.length() - 2);
    }

    @After
    public void tearDown() throws Exception {
        userService.delete(user.getId());
    }

    @Test
    public void shouldReturnBadRequestWhenPasswordAreTheSame() throws Exception {

        PasswordChangeRequestView samePasswords = new PasswordChangeRequestView(OLD_PASSWORD, OLD_PASSWORD);

        mockMvc.perform(post(ApiUrl.PASSWORDS_PATH)
                .header(AUTHORIZATION_HEADER, TOKEN_PREFIX + token)
                .contentType(CONTENT_TYPE)
                .content(ModelMapper.convertToJsonString(samePasswords)))
                .andExpect(status().isBadRequest());
    }

    @Test
    public void shouldReturnBadRequestWhenPasswordsDoNotMatch() throws Exception {

        PasswordChangeRequestView notMatchingPasswords = new PasswordChangeRequestView(NEW_PASSWORD, NEW_PASSWORD);

        mockMvc.perform(post(ApiUrl.PASSWORDS_PATH)
                .header(AUTHORIZATION_HEADER, TOKEN_PREFIX + token)
                .contentType(CONTENT_TYPE)
                .content(ModelMapper.convertToJsonString(notMatchingPasswords)))
                .andExpect(status().isBadRequest());
    }

    @Test
    public void shouldChangePassword() throws Exception {

        PasswordChangeRequestView passwords = new PasswordChangeRequestView(OLD_PASSWORD, NEW_PASSWORD);
        String responseMessage = messageSource.getMessage(
                "passwordChangeSuccessful", null, LocaleContextHolder.getLocale());

        mockMvc.perform(post(ApiUrl.PASSWORDS_PATH)
                .header(AUTHORIZATION_HEADER, TOKEN_PREFIX + token)
                .contentType(CONTENT_TYPE)
                .content(ModelMapper.convertToJsonString(passwords)))
                .andExpect(status().isCreated())
                .andExpect(content().contentType(CONTENT_TYPE))
                .andExpect(jsonPath("message", is(responseMessage)));

        UserCredentialsView credentialsView = new UserCredentialsView(user.getEmail(), NEW_PASSWORD);
        mockMvc.perform(post(ACQUIRE_TOKEN_PATH)
                .contentType(CONTENT_TYPE)
                .content(ModelMapper.convertToJsonString(credentialsView)))
                .andExpect(content().contentType(CONTENT_TYPE))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("jwt", notNullValue()));
    }
}

@@ -2304,16 +2304,78 @@
 LUNTEER;
+%0A    private static final String JWT_JSON_SIGN = %22%5C%22jwt%5C%22:%5C%22%22;
 %0A%0A    @A
@@ -3319,80 +3319,216 @@
     
-token = response.substring(%22%7B%5C%22jwt%5C%22:%5C%22%22.length(), response.length() - 2
+int jwtTokenBeginIndex = response.indexOf(JWT_JSON_SIGN) + JWT_JSON_SIGN.length();%0A        int jwtTokenEndIndex = response.length() - 2;%0A        token = response.substring(jwtTokenBeginIndex, jwtTokenEndIndex
 );%0A 
@@ -3723,33 +3723,32 @@
 ows Exception %7B%0A
-%0A
         Password
@@ -4223,33 +4223,32 @@
 ows Exception %7B%0A
-%0A
         Password
@@ -4654,32 +4654,32 @@
    %7D%0A%0A    @Test%0A
+
     public void 
@@ -4720,17 +4720,16 @@
 ption %7B%0A
-%0A
         

fix getting jwt token from login response (#53)