package kr.itn.itnhub.review;

import kr.itn.itnhub.org.OrgNotFoundException;
import kr.itn.itnhub.org.OrganizationMapper;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.List;

/** 기관관리 상세의 권리확인 탭이 쓰는 목록/상세/수정/삭제/다운로드 서비스. */
@Service
public class ReviewService {

    /** 1행 그룹 제목 + 2행 컬럼 헤더. W열은 원본 시트의 빈 열이라 빈 문자열로 남겨둔다. */
    private static final String[] COLUMN_HEADERS = {
            "순번", "사이트명", "범주", "게시판 경로", "게시판명", "게시물제목", "URL주소",
            "게시글 등록", "제작일", "공표일", "첨부파일여부", "기존 공공누리부착", "기존 공공누리유형", "AI유형",
            "비고(조사원)", "개방가능여부", "권리확인(대분류)", "권리확인(세부)", "처리결과",
            "공공누리유형(판정)", "AI유형(판정)", "의견", "", "비고(변호사)", "권리처리필요"
    };

    private final ReviewItemMapper mapper;
    private final OrganizationMapper orgMapper;

    public ReviewService(ReviewItemMapper mapper, OrganizationMapper orgMapper) {
        this.mapper = mapper;
        this.orgMapper = orgMapper;
    }

    public ReviewPage list(Long orgId, String keyword, int page, int size) {
        requireOrg(orgId);
        String kw = normalizeKeyword(keyword);
        int safePage = Math.max(page, 0);
        int safeSize = size <= 0 ? 30 : size;
        int offset = safePage * safeSize;

        List<ReviewItem> items = mapper.findPage(orgId, kw, offset, safeSize);
        int total = mapper.countByOrg(orgId, kw);
        int done = mapper.countDone(orgId);
        return new ReviewPage(items, total, done, safePage, safeSize);
    }

    public ReviewItem get(Long orgId, Long itemId) {
        requireOrg(orgId);
        return requireItem(orgId, itemId);
    }

    @Transactional
    public ReviewItem updateJudgment(Long orgId, Long itemId, JudgmentRequest request) {
        requireOrg(orgId);
        int updated = mapper.updateJudgment(orgId, itemId,
                request.openable(), request.reviewMajor(), request.reviewMinor(), request.reviewResult(),
                request.judgedKoglType(), request.judgedAiType(), request.opinion(), request.lawyerNote(),
                request.needsProcessing());
        if (updated == 0) {
            throw new ReviewNotFoundException("게시물을 찾을 수 없습니다: " + itemId);
        }
        return mapper.findById(orgId, itemId);
    }

    @Transactional
    public void delete(Long orgId, Long itemId) {
        requireOrg(orgId);
        int deleted = mapper.deleteById(orgId, itemId);
        if (deleted == 0) {
            throw new ReviewNotFoundException("게시물을 찾을 수 없습니다: " + itemId);
        }
    }

    /** 원본 파일과 같은 헤더 배치(1행 그룹제목, 2행 컬럼헤더, 3행부터 데이터)로 xlsx를 만든다. */
    public byte[] downloadWorkbook(Long orgId) {
        requireOrg(orgId);
        List<ReviewItem> items = mapper.findAllByOrg(orgId);

        try (XSSFWorkbook wb = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            Sheet sheet = wb.createSheet(ReviewParser.PRIMARY_SHEET_NAME);

            Row groupRow = sheet.createRow(0);
            groupRow.createCell(0).setCellValue("게시물 정보(조사원)");
            groupRow.createCell(15).setCellValue("권리확인(변호사)");

            Row headerRow = sheet.createRow(1);
            for (int i = 0; i < COLUMN_HEADERS.length; i++) {
                headerRow.createCell(i).setCellValue(COLUMN_HEADERS[i]);
            }

            int rowNum = 2;
            for (ReviewItem item : items) {
                Row row = sheet.createRow(rowNum++);
                setCell(row, 0, String.valueOf(item.getSeq()));
                setCell(row, 1, item.getSiteName());
                setCell(row, 2, item.getCategory());
                setCell(row, 3, item.getBoardPath());
                setCell(row, 4, item.getBoardName());
                setCell(row, 5, item.getPostTitle());
                setCell(row, 6, item.getUrl());
                setCell(row, 7, item.getPostRegistered());
                setCell(row, 8, item.getProducedDate());
                setCell(row, 9, item.getPublishedDate());
                setCell(row, 10, item.getHasAttachment());
                setCell(row, 11, item.getKoglAttached());
                setCell(row, 12, item.getKoglType());
                setCell(row, 13, item.getAiType());
                setCell(row, 14, item.getSurveyorNote());
                setCell(row, 15, item.getOpenable());
                setCell(row, 16, item.getReviewMajor());
                setCell(row, 17, item.getReviewMinor());
                setCell(row, 18, item.getReviewResult());
                setCell(row, 19, item.getJudgedKoglType());
                setCell(row, 20, item.getJudgedAiType());
                setCell(row, 21, item.getOpinion());
                // 22 = W, 빈 열
                setCell(row, 23, item.getLawyerNote());
                setCell(row, 24, item.getNeedsProcessing());
            }

            wb.write(out);
            return out.toByteArray();
        } catch (IOException e) {
            throw new UncheckedIOException("권리확인 엑셀을 만들지 못했습니다.", e);
        }
    }

    private void setCell(Row row, int columnIndex, String value) {
        if (value == null) {
            return;
        }
        Cell cell = row.createCell(columnIndex);
        cell.setCellValue(value);
    }

    private String normalizeKeyword(String keyword) {
        return (keyword == null || keyword.isBlank()) ? null : keyword.trim();
    }

    private void requireOrg(Long orgId) {
        if (orgMapper.findById(orgId) == null) {
            throw new OrgNotFoundException("기관을 찾을 수 없습니다: " + orgId);
        }
    }

    private ReviewItem requireItem(Long orgId, Long itemId) {
        ReviewItem item = mapper.findById(orgId, itemId);
        if (item == null) {
            throw new ReviewNotFoundException("게시물을 찾을 수 없습니다: " + itemId);
        }
        return item;
    }
}
