package kr.itn.itnhub.seed;

import kr.itn.itnhub.AbstractDbTest;
import kr.itn.itnhub.org.OrgStatus;
import kr.itn.itnhub.org.Organization;
import kr.itn.itnhub.org.OrganizationMapper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class SeedServiceTest extends AbstractDbTest {

    @Autowired
    SeedService seedService;

    @Autowired
    OrganizationMapper mapper;

    @Autowired
    JdbcTemplate jdbc;

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

    private byte[] workbook(String[]... dataRows) throws Exception {
        try (XSSFWorkbook wb = new XSSFWorkbook();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {

            Sheet sheet = wb.createSheet(SeedParser.SHEET_NAME);
            sheet.createRow(0);
            sheet.createRow(1);

            int rowNum = 2;
            for (String[] data : dataRows) {
                Row row = sheet.createRow(rowNum++);
                row.createCell(1).setCellValue(data[0]);
                row.createCell(2).setCellValue(data[1]);
                row.createCell(5).setCellValue(data[2]);
                if (data[3] != null) row.createCell(6).setCellValue(data[3]);
                if (data[4] != null) row.createCell(7).setCellValue(data[4]);
                if (data[5] != null) row.createCell(8).setCellValue(data[5]);
                if (data[6] != null) row.createCell(9).setCellValue(data[6]);
                if (data[7] != null) row.createCell(10).setCellValue(data[7]);
            }
            wb.write(out);
            return out.toByteArray();
        }
    }

    @Test
    void 최초_시드는_전부_신규다() throws Exception {
        byte[] xlsx = workbook(
                new String[]{"001", "00", "국제방송교류재단", "팀", "송민지", "과장", "02-1", "a@b.kr"},
                new String[]{"002", "00", "세종학당재단", "팀", "권유나", "6급", "02-2", "c@d.kr"});

        SeedReport report = seedService.seed(new ByteArrayInputStream(xlsx));

        assertThat(report.created()).isEqualTo(2);
        assertThat(report.updated()).isZero();
        assertThat(report.total()).isEqualTo(2);
        assertThat(mapper.findAll()).hasSize(2);
    }

    @Test
    void 같은_파일을_다시_올려도_행이_늘지_않는다() throws Exception {
        byte[] xlsx = workbook(
                new String[]{"001", "00", "국제방송교류재단", "팀", "송민지", "과장", "02-1", "a@b.kr"});

        seedService.seed(new ByteArrayInputStream(xlsx));
        SeedReport second = seedService.seed(new ByteArrayInputStream(xlsx));

        assertThat(second.created()).isZero();
        assertThat(second.updated()).isEqualTo(1);
        assertThat(mapper.findAll()).hasSize(1);
    }

    @Test
    void 재시드는_이미_만든_채널ID를_보존한다() throws Exception {
        byte[] xlsx = workbook(
                new String[]{"001", "00", "국제방송교류재단", "팀", "송민지", "과장", "02-1", "a@b.kr"});

        seedService.seed(new ByteArrayInputStream(xlsx));
        Long id = mapper.findAll().get(0).getId();
        mapper.updateChannelIdMj(id, "chan-mj");
        mapper.updateChannelIdLaw(id, "chan-law");

        seedService.seed(new ByteArrayInputStream(xlsx));

        assertThat(mapper.findById(id).getStatus()).isEqualTo(OrgStatus.ACTIVE);
    }

    @Test
    void 담당자정보가_없는_기관은_정보대기로_들어온다() throws Exception {
        byte[] xlsx = workbook(
                new String[]{"008", "00", "경찰청", "데이터정책계", "박진우", "경위", "02-3", "e@f.kr"},
                new String[]{"008", "01", "경찰청_치안정책연구소", null, null, null, null, null});

        seedService.seed(new ByteArrayInputStream(xlsx));

        List<Organization> all = mapper.findAll();
        assertThat(all).hasSize(2);
        assertThat(all).extracting(Organization::getStatus)
                .containsExactly(OrgStatus.READY, OrgStatus.INFO_PENDING);
    }
}
