package incheon.ags.ias.dataHoprReg.util;

import incheon.com.cmm.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * KB RTMS 파일 정제 유틸리티
 *
 * 정제 규칙 (기존 kbSample.jsp 서버사이드 이식):
 * 1. 줄 끝 "|" 제거
 * 2. "인천광역시" 포함 줄: 첫 번째 "||" → "|" 변환
 * 3. 법정동코드 전용: "28"로 시작하지 않는 줄 필터링
 *
 * 인코딩: CP949(MS949) 우선, UTF-8 폴백
 */
@Slf4j
public class KbRtmsFileRefiner {

    private KbRtmsFileRefiner() {}

    /**
     * 파일을 읽고 정제하여 파싱된 행 목록을 반환한다.
     *
     * @param file           대상 파일
     * @param filterIncheon  true이면 "28"로 시작하는 줄만 필터링 (법정동코드용)
     * @param fixDoublePipe  true이면 "인천광역시" 포함 줄의 첫 번째 "||" → "|" 변환
     * @param expectedCols   기대 컬럼 수 (정제 후 기준)
     * @return 정제 + 파싱된 행 목록 (각 행은 컬럼 문자열 리스트)
     */
    public static List<List<String>> readAndRefine(File file, boolean filterIncheon,
                                                    boolean fixDoublePipe, int expectedCols) throws Exception {
        Charset primaryEncoding = Charset.forName("MS949");
        Charset fallbackEncoding = StandardCharsets.UTF_8;

        try {
            return doReadAndRefine(file, primaryEncoding, filterIncheon, fixDoublePipe, expectedCols);
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.warn("MS949 인코딩 실패, UTF-8로 재시도: {}", e.getMessage());
            return doReadAndRefine(file, fallbackEncoding, filterIncheon, fixDoublePipe, expectedCols);
        }
    }

    private static List<List<String>> doReadAndRefine(File file, Charset charset,
                                                       boolean filterIncheon, boolean fixDoublePipe,
                                                       int expectedCols) throws Exception {
        List<List<String>> result = new ArrayList<>();
        int lineNum = 0;
        int skippedCount = 0;
        boolean firstRowChecked = false;

        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), charset))) {

            String rawLine;
            while ((rawLine = reader.readLine()) != null) {
                lineNum++;

                // BOM 제거
                if (lineNum == 1 && rawLine.startsWith("\uFEFF")) {
                    rawLine = rawLine.substring(1);
                }

                if (rawLine.trim().isEmpty()) continue;

                // === 정제 시작 ===

                String line = rawLine;

                // 1. 줄 끝 "|" 제거
                if (line.endsWith("|")) {
                    line = line.substring(0, line.length() - 1);
                }

                // 2. 법정동코드 필터: "28"로 시작하지 않으면 스킵
                if (filterIncheon && !line.startsWith("28")) {
                    skippedCount++;
                    continue;
                }

                // 3. "인천광역시" 포함 줄의 첫 번째 "||" → "|"
                if (fixDoublePipe && line.contains("인천광역시")) {
                    line = line.replaceFirst("\\|\\|", "|");
                }

                // === 파싱 ===
                String[] parts = line.split("\\|", -1);
                List<String> columns = new ArrayList<>(parts.length);
                for (String part : parts) {
                    String trimmed = part.trim();
                    columns.add(trimmed.isEmpty() ? null : trimmed);
                }

                // 첫 데이터 행 항목 수 검증
                if (!firstRowChecked) {
                    firstRowChecked = true;
                    int actualCols = columns.size();
                    if (actualCols != expectedCols) {
                        throw new BusinessException(
                                "파일 항목 수가 맞지 않습니다. 기대: " + expectedCols + "개, 실제: " + actualCols + "개. 올바른 파일인지 확인해주세요.");
                    }
                }

                // 컬럼 수 보정
                if (columns.size() < expectedCols) {
                    // 부족한 컬럼은 null로 채움
                    while (columns.size() < expectedCols) {
                        columns.add(null);
                    }
                } else if (columns.size() > expectedCols) {
                    // 초과 컬럼은 잘라냄 (trailing empty 등)
                    columns = new ArrayList<>(columns.subList(0, expectedCols));
                }

                result.add(columns);
            }
        }

        log.info("파일 파싱 완료 ({}) - 총 {}줄, 데이터 {}건, 스킵 {}건",
                charset.name(), lineNum, result.size(), skippedCount);

        return result;
    }
}
