package kr.itn.itnhub.contact;

import kr.itn.itnhub.seed.SeedParseException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 회원정보 xlsx(Sheet1)를 읽는다.
 *
 * 시트 배치 (1행 헤더, 2행부터 데이터):
 *   A=순번  B=구분  C=기관명  D=부서명  E=담당자명  F=직급/직함  G=유선전화  H=이메일
 *
 * 담당자명(E)이 빈 첫 행에서 데이터가 끝난 것으로 보고 읽기를 멈춘다. 구분(B)이
 * 알려진 값(주관기관/변호사/신청기관/수행기관)이 아니면 그 행은 건너뛰고 skipped로
 * 센다 - 시트 끝은 아니므로 이어서 다음 행을 계속 읽는다.
 */
@Component
public class MemberDirectoryParser {

    public static final String SHEET_NAME = "Sheet1";

    private static final int DATA_START_ROW_INDEX = 1; // 2행
    private static final int COL_CATEGORY = 1;  // B
    private static final int COL_ORG_NAME = 2;  // C
    private static final int COL_DEPT = 3;      // D
    private static final int COL_NAME = 4;      // E
    private static final int COL_TITLE = 5;     // F
    private static final int COL_PHONE = 6;     // G
    private static final int COL_EMAIL = 7;     // H

    private static final Map<String, String> CATEGORY_LABELS = Map.of(
            "주관기관", "MJ",
            "변호사", "LAWYER",
            "신청기관", "APPLICANT",
            "수행기관", "OPERATOR");

    public MemberParseResult parse(InputStream xlsx) {
        try (Workbook wb = WorkbookFactory.create(xlsx)) {
            Sheet sheet = wb.getSheet(SHEET_NAME);
            if (sheet == null) {
                throw new SeedParseException(
                        "통합문서에 '" + SHEET_NAME + "' 시트가 없습니다.");
            }
            return readRows(sheet);
        } catch (IOException e) {
            throw new SeedParseException("엑셀 파일을 읽지 못했습니다.", e);
        }
    }

    private MemberParseResult readRows(Sheet sheet) {
        List<MemberRow> rows = new ArrayList<>();
        int skipped = 0;

        for (int i = DATA_START_ROW_INDEX; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            String name = row == null ? "" : string(row, COL_NAME);
            if (name.isBlank()) {
                break; // 담당자명이 빈 첫 행에서 데이터 끝
            }

            String category = CATEGORY_LABELS.get(string(row, COL_CATEGORY));
            if (category == null) {
                skipped++;
                continue;
            }

            rows.add(new MemberRow(
                    category,
                    nullIfBlank(string(row, COL_ORG_NAME)),
                    normalizeDept(string(row, COL_DEPT)),
                    name,
                    nullIfBlank(string(row, COL_TITLE)),
                    nullIfBlank(string(row, COL_PHONE)),
                    nullIfBlank(string(row, COL_EMAIL))));
        }
        return new MemberParseResult(rows, skipped);
    }

    /** 부서명은 "-"와 공백 모두 값 없음으로 취급한다. */
    private String normalizeDept(String value) {
        String v = nullIfBlank(value);
        return "-".equals(v) ? null : v;
    }

    private String string(Row row, int columnIndex) {
        Cell cell = row.getCell(columnIndex);
        if (cell == null) {
            return "";
        }
        return cellValue(cell, cell.getCellType());
    }

    /** SeedParser와 동일한 셀 값 변환 규칙(FORMULA는 캐시된 결과 타입으로 위임). */
    private String cellValue(Cell cell, CellType cellType) {
        return switch (cellType) {
            case STRING -> cell.getStringCellValue().trim();
            case NUMERIC -> String.valueOf(Math.round(cell.getNumericCellValue()));
            case BOOLEAN -> String.valueOf(cell.getBooleanCellValue());
            case FORMULA -> cellValue(cell, cell.getCachedFormulaResultType());
            default -> "";
        };
    }

    private String nullIfBlank(String value) {
        return (value == null || value.isBlank()) ? null : value;
    }
}
