package com.eactive.ext.kjb.statistics.service;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
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.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import com.eactive.ext.kjb.statistics.ui.ApiStatsUI;

import lombok.extern.slf4j.Slf4j;

/**
 * API 통계 Excel Export 서비스
 * Hour/Minute 통계 데이터를 Excel 파일로 생성
 */
@Slf4j
@Service
public class ApiStatsExcelExportService {

	private static final String[] COLUMN_HEADERS = {
		"통계시간", "API명", "인스턴스", "업무구분", "클라이언트ID",
		"Inbound Adapter", "Outbound Adapter",
		"총건수", "성공건수", "Timeout건수", "시스템오류건수",
		"평균응답시간", "최소응답시간", "최대응답시간"
	};

	/**
	 * API 통계 데이터를 Excel 파일로 생성하여 HTTP 응답으로 전송
	 *
	 * @param dataList API 통계 데이터 리스트
	 * @param fileName 다운로드 파일명
	 * @param response HTTP 응답 객체
	 * @throws IOException 파일 생성 실패 시
	 */
	public void exportApiStats(List<ApiStatsUI> dataList, String fileName, HttpServletResponse response)
			throws IOException {

		log.info("Starting Excel export - rows: {}, filename: {}", dataList.size(), fileName);

		try (Workbook workbook = new XSSFWorkbook()) {
			Sheet sheet = workbook.createSheet("API통계");
			log.debug("Excel sheet created");

			// 스타일 생성
			CellStyle headerStyle = createHeaderStyle(workbook);
			CellStyle stringStyle = createStringStyle(workbook);
			CellStyle numberStyle = createNumberStyle(workbook);
			CellStyle decimalStyle = createDecimalStyle(workbook);
			log.debug("Excel styles created");

			// 헤더 행 생성
			createHeaderRow(sheet, headerStyle);
			log.debug("Header row created");

			// 데이터 행 생성
			int rowNum = 1;
			for (ApiStatsUI data : dataList) {
				createDataRow(sheet, rowNum++, data, stringStyle, numberStyle, decimalStyle);
			}
			log.info("Data rows created - count: {}", dataList.size());

			// 컬럼 너비 자동 조정
			autoSizeColumns(sheet);
			log.debug("Column widths adjusted");

			// HTTP 응답 설정
			setHttpResponse(response, fileName, workbook);
			log.info("Excel file sent to response");

		} catch (Exception e) {
			log.error("Error creating Excel file", e);
			throw new IOException("Excel file creation failed: " + e.getMessage(), e);
		}
	}

	/**
	 * 헤더 스타일 생성 (회색 배경, 볼드, 테두리)
	 */
	private CellStyle createHeaderStyle(Workbook workbook) {
		CellStyle style = workbook.createCellStyle();

		// 배경색
		style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

		// 테두리
		style.setBorderTop(BorderStyle.THIN);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);

		// 정렬
		style.setAlignment(HorizontalAlignment.CENTER);

		// 폰트 (볼드)
		Font font = workbook.createFont();
		font.setBold(true);
		style.setFont(font);

		return style;
	}

	/**
	 * 문자열 데이터 스타일 생성 (기본 테두리)
	 */
	private CellStyle createStringStyle(Workbook workbook) {
		CellStyle style = workbook.createCellStyle();
		style.setBorderTop(BorderStyle.THIN);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		return style;
	}

	/**
	 * 숫자 데이터 스타일 생성 (우측정렬 + 쉼표 구분)
	 */
	private CellStyle createNumberStyle(Workbook workbook) {
		CellStyle style = workbook.createCellStyle();
		style.setBorderTop(BorderStyle.THIN);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setAlignment(HorizontalAlignment.RIGHT);
		style.setDataFormat(workbook.createDataFormat().getFormat("#,##0"));
		return style;
	}

	/**
	 * 소수점 데이터 스타일 생성 (우측정렬 + 소수점 3자리)
	 */
	private CellStyle createDecimalStyle(Workbook workbook) {
		CellStyle style = workbook.createCellStyle();
		style.setBorderTop(BorderStyle.THIN);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setAlignment(HorizontalAlignment.RIGHT);
		style.setDataFormat(workbook.createDataFormat().getFormat("0.000"));
		return style;
	}

	/**
	 * 헤더 행 생성
	 */
	private void createHeaderRow(Sheet sheet, CellStyle headerStyle) {
		Row headerRow = sheet.createRow(0);

		for (int i = 0; i < COLUMN_HEADERS.length; i++) {
			Cell cell = headerRow.createCell(i);
			cell.setCellValue(COLUMN_HEADERS[i]);
			cell.setCellStyle(headerStyle);
		}
	}

	/**
	 * 데이터 행 생성
	 */
	private void createDataRow(Sheet sheet, int rowNum, ApiStatsUI data,
			CellStyle stringStyle, CellStyle numberStyle, CellStyle decimalStyle) {

		Row row = sheet.createRow(rowNum);
		int colNum = 0;

		// 문자열 컬럼 (0-6)
		createStringCell(row, colNum++, data.getStatTime(), stringStyle);
		createStringCell(row, colNum++, data.getApiName(), stringStyle);
		createStringCell(row, colNum++, data.getGwInstanceId(), stringStyle);
		createStringCell(row, colNum++, data.getBizDivCode(), stringStyle);
		createStringCell(row, colNum++, data.getClientId(), stringStyle);
		createStringCell(row, colNum++, data.getInboundAdapter(), stringStyle);
		createStringCell(row, colNum++, data.getOutboundAdapter(), stringStyle);

		// 숫자 컬럼 (7-14)
		createLongCell(row, colNum++, data.getTotalCnt(), numberStyle);
		createLongCell(row, colNum++, data.getSuccessCnt(), numberStyle);
		createLongCell(row, colNum++, data.getTimeoutCnt(), numberStyle);
		createLongCell(row, colNum++, data.getSystemErrCnt(), numberStyle);
		

		// 소수점 컬럼 (15-19)
		createDecimalCell(row, colNum++, data.getAvgRespTime(), decimalStyle);
		createDecimalCell(row, colNum++, data.getMinRespTime(), decimalStyle);
		createDecimalCell(row, colNum++, data.getMaxRespTime(), decimalStyle);
		
	}

	/**
	 * 문자열 셀 생성
	 */
	private void createStringCell(Row row, int colNum, String value, CellStyle style) {
		Cell cell = row.createCell(colNum);
		cell.setCellValue(value != null ? value : "");
		cell.setCellStyle(style);
	}

	/**
	 * Long 타입 숫자 셀 생성
	 */
	private void createLongCell(Row row, int colNum, Long value, CellStyle style) {
		Cell cell = row.createCell(colNum);
		if (value != null) {
			cell.setCellValue(value.doubleValue());
		} else {
			cell.setCellValue(0);
		}
		cell.setCellStyle(style);
	}

	/**
	 * BigDecimal 타입 소수점 셀 생성
	 */
	private void createDecimalCell(Row row, int colNum, BigDecimal value, CellStyle style) {
		Cell cell = row.createCell(colNum);
		if (value != null) {
			cell.setCellValue(value.doubleValue());
		} else {
			cell.setCellValue(0.0);
		}
		cell.setCellStyle(style);
	}

	/**
	 * 컬럼 너비 자동 조정
	 */
	private void autoSizeColumns(Sheet sheet) {
		for (int i = 0; i < COLUMN_HEADERS.length; i++) {
			sheet.autoSizeColumn(i);
			// 한글 문자 고려하여 약간 여유 공간 추가
			sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 512);
		}
	}

	/**
	 * HTTP 응답 설정 및 파일 전송
	 */
	private void setHttpResponse(HttpServletResponse response, String fileName, Workbook workbook)
			throws IOException {

		// Content-Type 설정
		response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

		// Content-Disposition 설정 (파일명 UTF-8 인코딩)
		String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString())
				.replaceAll("\\+", "%20");
		response.setHeader("Content-Disposition",
				"attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);

		// Workbook을 응답 스트림으로 전송
		workbook.write(response.getOutputStream());
		response.getOutputStream().flush();
	}
}
