package com.jeeplus.assess.invoice.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 支持多Sheet的Excel导出工具类
 */
/**
 * 多页签Excel导出工具类
 * 支持创建多个Sheet页，每个页签可独立设置名称和数据
 */

/**
 * 支持多Sheet的Excel导出工具类
 */
public class ExportMultipleTabsExcel {
	private static final Logger log = LoggerFactory.getLogger(ExportMultipleTabsExcel.class);
	private Workbook workbook; // 共享的工作簿
	private Map<String, SheetData> sheetDataMap = new HashMap<>(); // 存储各Sheet的数据

	/**
	 * 内部类：存储单个Sheet的数据
	 */
	private static class SheetData {
		String sheetName;
		String title;
		Class<?> entityClass;
		List<?> dataList;
		List<Object[]> annotationList; // 存储ExcelField注解信息
		int rownum = 0; // 当前行号

		public SheetData(String sheetName, String title, Class<?> entityClass) {
			this.sheetName = sheetName;
			this.title = title;
			this.entityClass = entityClass;
			this.annotationList = initAnnotationList(entityClass);
		}

		// 初始化注解列表
		private List<Object[]> initAnnotationList(Class<?> cls) {
			List<Object[]> list = new ArrayList<>();
			// 处理字段注解
			Field[] fields = cls.getDeclaredFields();
			for (Field field : fields) {
				ExcelField ef = field.getAnnotation(ExcelField.class);
				if (ef != null && (ef.type() == 0 || ef.type() == 1)) {
					list.add(new Object[]{ef, field});
				}
			}
			// 处理方法注解
			Method[] methods = cls.getDeclaredMethods();
			for (Method method : methods) {
				ExcelField ef = method.getAnnotation(ExcelField.class);
				if (ef != null && (ef.type() == 0 || ef.type() == 1)) {
					list.add(new Object[]{ef, method});
				}
			}
			// 按排序号排序
			list.sort(Comparator.comparingInt(o -> ((ExcelField) o[0]).sort()));
			return list;
		}
	}

	/**
	 * 构造函数：初始化工作簿
	 */
	public ExportMultipleTabsExcel() {
		this.workbook = new SXSSFWorkbook(1000); // 内存中保留1000行，适合大数据量
	}

	/**
	 * 添加一个Sheet页
	 */
	public void addSheet(String sheetName, String title, Class<?> entityClass, List<?> dataList) {
		SheetData sheetData = new SheetData(sheetName, title, entityClass);
		sheetData.dataList = dataList;
		sheetDataMap.put(sheetName, sheetData);
	}

	/**
	 * 创建单元格样式
	 */
	private Map<String, CellStyle> createStyles(Workbook wb) {
		Map<String, CellStyle> styles = new HashMap<>();

		// 标题样式
		CellStyle style = wb.createCellStyle();
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setVerticalAlignment(VerticalAlignment.CENTER);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setBorderTop(BorderStyle.THIN);
		Font titleFont = wb.createFont();
		titleFont.setFontName("宋体");
		titleFont.setFontHeightInPoints((short) 16);
		titleFont.setBold(true);
		style.setFont(titleFont);
		styles.put("title", style);

		// 表头样式（无边框 + 更深底色 + 白色字体）
		style = wb.createCellStyle();
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setVerticalAlignment(VerticalAlignment.CENTER);
		style.setBorderBottom(BorderStyle.NONE);
		style.setBorderLeft(BorderStyle.NONE);
		style.setBorderRight(BorderStyle.NONE);
		style.setBorderTop(BorderStyle.NONE);
		style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		Font headerFont = wb.createFont();
		headerFont.setFontName("宋体");
		headerFont.setFontHeightInPoints((short) 11);
		headerFont.setBold(true);
		headerFont.setColor(IndexedColors.WHITE.getIndex()); // 白色字体
		style.setFont(headerFont);
		styles.put("header", style);

		// 数据单元格样式（区分字符串和数字对齐）
		// 字符串居中样式
		CellStyle stringStyle = wb.createCellStyle();
		stringStyle.setAlignment(HorizontalAlignment.CENTER);
		stringStyle.setVerticalAlignment(VerticalAlignment.CENTER);
		stringStyle.setBorderBottom(BorderStyle.THIN);
		stringStyle.setBorderLeft(BorderStyle.THIN);
		stringStyle.setBorderRight(BorderStyle.THIN);
		stringStyle.setBorderTop(BorderStyle.THIN);
		Font stringFont = wb.createFont();
		stringFont.setFontName("宋体");
		stringFont.setFontHeightInPoints((short) 11);
		stringStyle.setFont(stringFont);
		styles.put("data_string", stringStyle);

		// 数字靠右样式
		CellStyle numberStyle = wb.createCellStyle();
		numberStyle.setAlignment(HorizontalAlignment.RIGHT);
		numberStyle.setVerticalAlignment(VerticalAlignment.CENTER);
		numberStyle.setBorderBottom(BorderStyle.THIN);
		numberStyle.setBorderLeft(BorderStyle.THIN);
		numberStyle.setBorderRight(BorderStyle.THIN);
		numberStyle.setBorderTop(BorderStyle.THIN);
		Font numberFont = wb.createFont();
		numberFont.setFontName("宋体");
		numberFont.setFontHeightInPoints((short) 11);
		numberStyle.setFont(numberFont);
		styles.put("data_number", numberStyle);

		return styles;
	}

	/**
	 * 生成Excel文件
	 */
	public void write(OutputStream os) throws IOException {
		for (SheetData sheetData : sheetDataMap.values()) {
			createSheetContent(sheetData);
		}
		// 写入输出流
		workbook.write(os);
	}

	/**
	 * 创建单个Sheet的内容
	 */
	private void createSheetContent(SheetData sheetData) {
		Sheet sheet = workbook.createSheet(sheetData.sheetName);
		Map<String, CellStyle> styles = createStyles(workbook);
		List<Object[]> annotationList = sheetData.annotationList;
		int rownum = sheetData.rownum;

		// 创建标题行
		if (StringUtils.isNotBlank(sheetData.title)) {
			Row titleRow = sheet.createRow(rownum++);
			titleRow.setHeightInPoints(30);
			Cell titleCell = titleRow.createCell(0);
			titleCell.setCellStyle(styles.get("title"));
			titleCell.setCellValue(sheetData.title);
			sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, annotationList.size() - 1));
		}

		// 创建表头行
		Row headerRow = sheet.createRow(rownum++);
		headerRow.setHeightInPoints(18);
		for (int i = 0; i < annotationList.size(); i++) {
			Object[] os = annotationList.get(i);
			ExcelField ef = (ExcelField) os[0];
			String header = ef.title();

			// 估算列宽：中文字符每个占2个字符宽度，英文字符每个占1个
			int width = 0;
			for (char c : header.toCharArray()) {
				width += (c > 127) ? 2 : 1;
			}
			// 最小宽度为10，最大为50
			width = Math.max(width, 10);
			width = Math.min(width, 50);
			sheet.setColumnWidth(i, width * 256 * 2); // 设置列宽

			// 新增：创建表头单元格并设置标题值
			Cell headerCell = headerRow.createCell(i);
			headerCell.setCellStyle(styles.get("header"));
			headerCell.setCellValue(header);
		}

		// 填充数据行（区分字符串和数字对齐）
		if (sheetData.dataList != null && !sheetData.dataList.isEmpty()) {
			for (Object obj : sheetData.dataList) {
				Row dataRow = sheet.createRow(rownum++);
				dataRow.setHeightInPoints(16);
				for (int i = 0; i < annotationList.size(); i++) {
					Object[] os = annotationList.get(i);
					ExcelField ef = (ExcelField) os[0];
					Cell cell = dataRow.createCell(i);

					// 获取单元格值
					Object value = getFieldValue(obj, ef, os);

					// 根据值的类型设置对齐样式
					if (value instanceof Number) {
						cell.setCellStyle(styles.get("data_number")); // 数字靠右
					} else {
						cell.setCellStyle(styles.get("data_string")); // 字符串居中
					}

					// 设置单元格值
					setCellValue(cell, value, ef);
				}
			}
		}
	}

	/**
	 * 使用标准反射获取字段值
	 */
	private Object getFieldValue(Object obj, ExcelField ef, Object[] os) {
		try {
			String fieldName = ef.value();
			if (StringUtils.isBlank(fieldName)) {
				if (os[1] instanceof Field) {
					fieldName = ((Field) os[1]).getName();
				} else if (os[1] instanceof Method) {
					Method method = (Method) os[1];
					return method.invoke(obj);
				}
			}

			// 调用getter方法
			if (StringUtils.isNotBlank(fieldName)) {
				String getterMethod = "get" + fieldName.substring(0, 1).toUpperCase()
						+ fieldName.substring(1);
				Method method = obj.getClass().getMethod(getterMethod);
				Object value = method.invoke(obj);


				return value;
			}
		} catch (Exception e) {
			log.error("获取字段值失败", e);
		}
		return "";
	}

	/**
	 * 设置单元格值（处理不同数据类型）
	 */
	private void setCellValue(Cell cell, Object value, ExcelField ef) {
		if (value == null) {
			cell.setCellValue("");
			return;
		}

		// 处理日期类型
		if (value instanceof Date) {
			String format = StringUtils.isNotBlank(ef.format()) ? ef.format() : "yyyy-MM-dd";
			cell.setCellValue(new SimpleDateFormat(format).format((Date) value));
		}
		// 处理数字类型
		else if (value instanceof Number) {
			cell.setCellValue(((Number) value).doubleValue());
		}
		// 处理布尔类型
		else if (value instanceof Boolean) {
			cell.setCellValue((Boolean) value);
		}
		// 其他类型按字符串处理
		else {
			cell.setCellValue(value.toString());
		}
	}

	/**
	 * 输出到客户端下载
	 */
	public void write(HttpServletResponse response, String fileName) throws IOException {
		response.reset();
		response.setContentType("application/octet-stream; charset=utf-8");
		response.setHeader("Content-Disposition", "attachment; filename="
				+ new String(fileName.getBytes("utf-8"), "ISO-8859-1"));
		write(response.getOutputStream());
	}

	/**
	 * 清理临时文件（避免内存泄漏）
	 */
	public void dispose() {
		if (workbook instanceof SXSSFWorkbook) {
			((SXSSFWorkbook) workbook).dispose();
		}
	}
}