package kr.itn.itnhub.seed;

import kr.itn.itnhub.AbstractDbTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * Finding 1 회귀 테스트: 업로드 컨트롤러가 확장자·빈 파일 검증 실패를 SeedParseException으로
 * 던지고, GlobalExceptionHandler가 그것을 500이 아니라 400으로 내려주는지 HTTP 경계에서 확인한다.
 */
@AutoConfigureMockMvc
@WithMockUser(roles = "ADMIN")
class SeedControllerTest extends AbstractDbTest {

    @Autowired
    MockMvc mvc;

    @Autowired
    JdbcTemplate jdbc;

    @BeforeEach
    void clean() {
        jdbc.update("delete from organization");
    }

    @Test
    void 빈_파일이면_400이다() throws Exception {
        MockMultipartFile empty = new MockMultipartFile("file", "seed.xlsx",
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", new byte[0]);

        mvc.perform(multipart("/api/seed").file(empty).with(csrf()))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.message").value(containsString("비어")));
    }

    @Test
    void 확장자가_xlsx_xlsm이_아니면_400이다() throws Exception {
        MockMultipartFile txt = new MockMultipartFile("file", "seed.txt",
                "text/plain", "아무 내용".getBytes());

        mvc.perform(multipart("/api/seed").file(txt).with(csrf()))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.message").value(containsString("xlsx")));
    }

    @Test
    void 시트가_없는_엑셀이면_400이다() throws Exception {
        byte[] wrongSheet = wrongSheetWorkbook();
        MockMultipartFile xlsx = new MockMultipartFile("file", "seed.xlsx",
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", wrongSheet);

        mvc.perform(multipart("/api/seed").file(xlsx).with(csrf()))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.message").value(containsString(SeedParser.SHEET_NAME)));
    }

    private byte[] wrongSheetWorkbook() throws Exception {
        try (var wb = new org.apache.poi.xssf.usermodel.XSSFWorkbook();
             var out = new java.io.ByteArrayOutputStream()) {
            wb.createSheet("다른시트");
            wb.write(out);
            return out.toByteArray();
        }
    }
}
