package com.owrawww.service;

import com.owrawww.domain.Bbs;
import com.owrawww.domain.mapper.BbsMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
class BbsServiceTest {

    @Mock
    private BbsMapper bbsMapper;

    @InjectMocks
    private BbsService bbsService;

    private Bbs sampleBbs;

    @BeforeEach
    void setUp() {
        sampleBbs = new Bbs();
        sampleBbs.setId(1L);
        sampleBbs.setTitle("테스트 제목");
        sampleBbs.setName("작성자");
        sampleBbs.setBody("내용입니다.");
        sampleBbs.setViewCnt(0);
    }

    @Test
    @DisplayName("getList - 정상적으로 목록과 페이징 정보를 반환한다")
    void getList_returnsListAndPagingInfo() {
        given(bbsMapper.selectList(any())).willReturn(List.of(sampleBbs, sampleBbs));
        given(bbsMapper.selectCount(any())).willReturn(2);

        Map<String, Object> result = bbsService.getList(1, "all", "", 1, 1, 1);

        assertThat(result.get("list")).isEqualTo(List.of(sampleBbs, sampleBbs));
        assertThat(result.get("totalCount")).isEqualTo(2);
        assertThat(result.get("currentPage")).isEqualTo(1);
        assertThat(result.get("totalPages")).isEqualTo(1);
    }

    @Test
    @DisplayName("getList - 페이지 번호가 0 이하이면 1로 보정된다")
    void getList_pageUnderOne_normalizedToOne() {
        given(bbsMapper.selectList(any())).willReturn(List.of());
        given(bbsMapper.selectCount(any())).willReturn(0);

        Map<String, Object> result = bbsService.getList(0, "all", "", 1, 1, 1);

        assertThat(result.get("currentPage")).isEqualTo(1);
    }

    @Test
    @DisplayName("getList - totalCount가 0이면 totalPages는 1이다")
    void getList_emptyResult_totalPagesIsOne() {
        given(bbsMapper.selectList(any())).willReturn(List.of());
        given(bbsMapper.selectCount(any())).willReturn(0);

        Map<String, Object> result = bbsService.getList(1, "all", "", 1, 1, 1);

        assertThat(result.get("totalPages")).isEqualTo(1);
    }

    @Test
    @DisplayName("getDetail - 조회수 증가 후 게시글과 이전/다음 정보를 반환한다")
    void getDetail_incrementsViewCntAndReturnsDetail() {
        given(bbsMapper.selectById(any())).willReturn(sampleBbs);
        given(bbsMapper.selectPrev(any())).willReturn(null);
        given(bbsMapper.selectNext(any())).willReturn(null);

        Map<String, Object> result = bbsService.getDetail(1L, 1, 1, 1, 1, "all", "");

        verify(bbsMapper).incrementViewCnt(1L);
        assertThat(result.get("bbs")).isEqualTo(sampleBbs);
        assertThat(result.get("prev")).isNull();
        assertThat(result.get("next")).isNull();
    }

    @Test
    @DisplayName("getPreview - limit 개수만큼 미리보기 목록을 반환한다")
    void getPreview_returnsLimitedList() {
        given(bbsMapper.selectPreview(any())).willReturn(List.of(sampleBbs));

        List<Bbs> result = bbsService.getPreview(1, 2, 1, 5);

        assertThat(result).hasSize(1);
        assertThat(result.get(0).getTitle()).isEqualTo("테스트 제목");
    }
}
