package egovframework.util.excel;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.List;

/**
 * 엑셀 시트 데이터를 담는 DTO 클래스
 *
 * <p>이 클래스는 엑셀 파일 생성에 필요한 데이터와 메타정보를 캡슐화합니다.
 * 데이터 리스트, VO 클래스 타입, 제목(선택사항)을 포함합니다.</p>
 *
 * <p><b>주요 특징:</b></p>
 * <ul>
 *   <li>불변(Immutable) 객체 - 모든 필드가 final</li>
 *   <li>팩토리 메서드 패턴 - of() 메서드로 객체 생성</li>
 *   <li>제목 행 지원 - 선택적으로 엑셀 상단에 제목 행 추가 가능</li>
 * </ul>
 *
 * <p><b>사용 예제 1: 제목 없는 엑셀 시트</b></p>
 * <pre>{@code
 * // VO 리스트 조회
 * List<UserVO> userList = userService.selectUserList();
 *
 * // ExcelSheetData 생성 (제목 없음)
 * ExcelSheetData sheetData = ExcelSheetData.of(userList, UserVO.class);
 *
 * // 엑셀 파일 생성
 * new SxssfExcelFile(sheetData, request, response, "사용자목록.xlsx");
 * }</pre>
 *
 * <p><b>사용 예제 2: 제목이 있는 엑셀 시트</b></p>
 * <pre>{@code
 * // VO 리스트 조회
 * List<UserVO> userList = userService.selectUserList();
 *
 * // ExcelSheetData 생성 (제목 포함)
 * ExcelSheetData sheetData = ExcelSheetData.of(
 *     userList,
 *     UserVO.class,
 *     "2024년 1월 사용자 목록"  // 제목 행에 표시될 텍스트
 * );
 *
 * // 엑셀 파일 생성 (첫 행에 제목이 표시됨)
 * new SxssfExcelFile(sheetData, request, response, "사용자목록.xlsx");
 * }</pre>
 *
 * <p><b>사용 예제 3: 다중 시트 엑셀</b></p>
 * <pre>{@code
 * // 시트 1: 사용자 목록
 * List<UserVO> userList = userService.selectUserList();
 * ExcelSheetData userSheet = ExcelSheetData.of(userList, UserVO.class, "사용자 목록");
 *
 * // 시트 2: 부서 목록
 * List<DeptVO> deptList = deptService.selectDeptList();
 * ExcelSheetData deptSheet = ExcelSheetData.of(deptList, DeptVO.class, "부서 목록");
 *
 * // 다중 시트 그룹 생성
 * ExcelSheetDataGroup dataGroup = ExcelSheetDataGroup.of(
 *     List.of(userSheet, deptSheet)
 * );
 *
 * // 다중 시트 엑셀 파일 생성
 * new SxssfMultiSheetExcelFile(dataGroup, response);
 * }</pre>
 *
 * @see SxssfExcelFile
 * @see SxssfMultiSheetExcelFile
 * @see ExcelSheetDataGroup
 * @author eGovFrame
 */
@Getter
@AllArgsConstructor
public class ExcelSheetData {

	// ==================== 필드 ====================

	/**
	 * 엑셀에 출력할 데이터 리스트
	 *
	 * <p>각 요소는 {@link ExcelColumn} 어노테이션이 붙은 VO 객체여야 합니다.
	 * 리스트의 각 객체가 엑셀의 한 행(row)으로 변환됩니다.</p>
	 */
	private final List<?> dataList;

	/**
	 * 데이터 리스트의 요소 타입 (VO 클래스)
	 *
	 * <p>이 클래스는 다음 어노테이션을 가져야 합니다:
	 * <ul>
	 *   <li>{@link ExcelColumn} - 각 필드에 붙여서 헤더명과 컬럼 너비 지정</li>
	 *   <li>{@link ExcelSheet} - 클래스에 붙여서 시트명 지정 (선택사항)</li>
	 * </ul>
	 * </p>
	 *
	 * <p><b>예제:</b></p>
	 * <pre>{@code
	 * @ExcelSheet(name = "사용자")
	 * public class UserVO {
	 *     @ExcelColumn(headerName = "이름", headerWidth = 20)
	 *     private String userName;
	 *
	 *     @ExcelColumn(headerName = "이메일")
	 *     private String email;
	 * }
	 * }</pre>
	 */
	private final Class<?> type;

	/**
	 * 제목 행 텍스트 (선택사항)
	 *
	 * <p>이 값이 null이 아니고 빈 문자열이 아니면, 엑셀 파일의 첫 번째 행에
	 * 제목이 표시됩니다. 제목은 모든 컬럼에 걸쳐 병합된 셀로 표시되며,
	 * 굵은 22포인트 폰트로 렌더링됩니다.</p>
	 *
	 * <p>null이거나 빈 문자열이면 제목 행을 생성하지 않고,
	 * 첫 번째 행부터 헤더가 시작됩니다.</p>
	 */
	private final String title;

	// ==================== 팩토리 메서드 ====================

	/**
	 * 제목이 없는 ExcelSheetData 객체를 생성합니다.
	 *
	 * <p>이 메서드로 생성한 객체는 제목 행 없이 헤더와 데이터만 출력됩니다.</p>
	 *
	 * <p><b>생성되는 엑셀 구조:</b></p>
	 * <pre>
	 * Row 0: [헤더1] [헤더2] [헤더3] ...
	 * Row 1: [데이터] [데이터] [데이터] ...
	 * Row 2: [데이터] [데이터] [데이터] ...
	 * ...
	 * </pre>
	 *
	 * @param dataList 엑셀에 출력할 데이터 리스트 (null이거나 비어있어도 됨)
	 * @param type 데이터 리스트의 요소 타입 (VO 클래스, null이면 안됨)
	 * @return 생성된 ExcelSheetData 객체
	 */
	public static ExcelSheetData of(List<?> dataList, Class<?> type) {
		return new ExcelSheetData(dataList, type, null);
	}

	/**
	 * 제목이 있는 ExcelSheetData 객체를 생성합니다.
	 *
	 * <p>이 메서드로 생성한 객체는 제목 행, 헤더 행, 데이터 행 순서로 출력됩니다.
	 * 제목은 첫 번째 행에 모든 컬럼에 걸쳐 병합되어 표시됩니다.</p>
	 *
	 * <p><b>생성되는 엑셀 구조:</b></p>
	 * <pre>
	 * Row 0: [제목 텍스트 - 병합된 셀]
	 * Row 1: [헤더1] [헤더2] [헤더3] ...
	 * Row 2: [데이터] [데이터] [데이터] ...
	 * Row 3: [데이터] [데이터] [데이터] ...
	 * ...
	 * </pre>
	 *
	 * @param dataList 엑셀에 출력할 데이터 리스트 (null이거나 비어있어도 됨)
	 * @param type 데이터 리스트의 요소 타입 (VO 클래스, null이면 안됨)
	 * @param title 제목 행에 표시될 텍스트 (null이면 제목 행을 생성하지 않음)
	 * @return 생성된 ExcelSheetData 객체
	 */
	public static ExcelSheetData of(List<?> dataList, Class<?> type, String title) {
		return new ExcelSheetData(dataList, type, title);
	}
}
