package com.devjob.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.devjob.dto.MemberJoinRequest;
import tools.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;

/**
 * EP18: 회원가입 API 통합 테스트.
 * @SpringBootTest로 전체 컨텍스트를 띄우고, @AutoConfigureMockMvc가 구성한 MockMvc로 HTTP 요청을 흉내낸다.
 * @Transactional을 클래스에 붙여 각 테스트가 끝나면 자동 롤백되어 테스트 간 데이터가 격리된다.
 */
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class MemberControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    @DisplayName("회원가입 성공 - 정상 이메일, 비밀번호 8자 이상 → 201 Created")
    void joinSuccess() throws Exception {
        MemberJoinRequest req = new MemberJoinRequest("test@devjob.com", "password123");

        mockMvc.perform(post("/api/members/join")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(req)))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.success").value(true))
                .andExpect(jsonPath("$.data.email").value("test@devjob.com"))
                .andDo(print());
    }

    @Test
    @DisplayName("회원가입 실패 - 중복 이메일 → 409 Conflict")
    void joinDuplicateEmail() throws Exception {
        MemberJoinRequest req = new MemberJoinRequest("dup@devjob.com", "password123");

        // given: 먼저 한 번 가입
        mockMvc.perform(post("/api/members/join")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(req)))
                .andExpect(status().isCreated());

        // when: 같은 이메일로 재가입 시도 → 409
        mockMvc.perform(post("/api/members/join")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(req)))
                .andExpect(status().isConflict())
                .andExpect(jsonPath("$.success").value(false))
                .andExpect(jsonPath("$.errorCode").value("DUPLICATE_EMAIL"));
    }

    @Test
    @DisplayName("회원가입 실패 - 비밀번호 8자 미만 → 400 Bad Request")
    void joinInvalidPassword() throws Exception {
        MemberJoinRequest req = new MemberJoinRequest("short@devjob.com", "1234");

        mockMvc.perform(post("/api/members/join")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(req)))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.success").value(false))
                .andExpect(jsonPath("$.errorCode").value("VALIDATION_ERROR"));
    }
}
