package com.liquidnet.client.admin.zhengzai.sweet.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.liquidnet.client.admin.common.config.RuoYiConfig;
import com.liquidnet.client.admin.common.exception.BusinessException;
import com.liquidnet.client.admin.common.utils.StringUtils;
import com.liquidnet.service.sweet.entity.SweetFormSubmission;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileOutputStream;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 动态表单报名 Excel 导出
 */
public class SweetFormSubmissionExcelUtils {

    private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private static final String COL_CREATED_AT = "提交时间";

    private SweetFormSubmissionExcelUtils() {
    }

    public static String export(List<SweetFormSubmission> submissions, String exportName) {
        if (submissions == null || submissions.isEmpty()) {
            throw new BusinessException("查无报名信息");
        }

        List<Map<String, String>> rows = new ArrayList<>();
        Set<String> dataKeys = new LinkedHashSet<>();

        for (SweetFormSubmission submission : submissions) {
            Map<String, String> row = new LinkedHashMap<>();
            row.put(COL_CREATED_AT, submission.getCreatedAt() == null ? "" : submission.getCreatedAt().format(DTF));
            parseDataJson(submission.getData(), row, dataKeys);
            rows.add(row);
        }

        List<String> headers = new ArrayList<>();
        headers.add(COL_CREATED_AT);
        headers.addAll(dataKeys);

        String sheetName = sanitizeSheetName(exportName);
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(sheetName);
        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < headers.size(); i++) {
            headerRow.createCell(i).setCellValue(headers.get(i));
        }

        int rowNum = 1;
        for (Map<String, String> rowData : rows) {
            Row row = sheet.createRow(rowNum++);
            for (int i = 0; i < headers.size(); i++) {
                String value = rowData.get(headers.get(i));
                row.createCell(i).setCellValue(value == null ? "" : value);
            }
        }

        String filename = sanitizeFilename(exportName) + ".xlsx";
        String absolutePath = RuoYiConfig.getDownloadPath() + filename;
        File desc = new File(absolutePath);
        if (!desc.getParentFile().exists()) {
            desc.getParentFile().mkdirs();
        }
        try (FileOutputStream out = new FileOutputStream(desc)) {
            workbook.write(out);
            workbook.close();
        } catch (Exception e) {
            throw new BusinessException("导出Excel失败，请联系网站管理员！");
        }
        return filename;
    }

    public static String buildExportName(String activityLabel, String beginTime, String endTime) {
        StringBuilder name = new StringBuilder(activityLabel).append("报名数据");
        if (StringUtils.isNotEmpty(beginTime) || StringUtils.isNotEmpty(endTime)) {
            name.append("_");
            if (StringUtils.isNotEmpty(beginTime)) {
                name.append(normalizeTimeForName(beginTime));
            }
            name.append("-");
            if (StringUtils.isNotEmpty(endTime)) {
                name.append(normalizeTimeForName(endTime));
            }
        }
        return name.toString();
    }

    private static String normalizeTimeForName(String time) {
        return time.trim().replace(":", "").replace(" ", "_");
    }

    private static String sanitizeSheetName(String name) {
        if (StringUtils.isEmpty(name)) {
            return "报名数据";
        }
        String sanitized = name.replaceAll("[\\\\/?*\\[\\]:]", "_");
        return sanitized.length() > 31 ? sanitized.substring(0, 31) : sanitized;
    }

    private static String sanitizeFilename(String name) {
        if (StringUtils.isEmpty(name)) {
            return "报名数据";
        }
        return name.replaceAll("[\\\\/:*?\"<>|]", "_");
    }

    private static void parseDataJson(String dataJson, Map<String, String> row, Set<String> dataKeys) {
        if (dataJson == null || dataJson.trim().isEmpty()) {
            return;
        }
        try {
            JSONObject jsonObject = JSON.parseObject(dataJson, Feature.OrderedField);
            if (jsonObject == null) {
                return;
            }
            for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                String key = entry.getKey();
                if (!dataKeys.contains(key)) {
                    dataKeys.add(key);
                }
                row.put(key, formatValue(entry.getValue()));
            }
        } catch (Exception ignored) {
            if (!dataKeys.contains("data")) {
                dataKeys.add("data");
            }
            row.put("data", dataJson);
        }
    }

    private static String formatValue(Object value) {
        if (value == null) {
            return "";
        }
        if (value instanceof Map || value instanceof List) {
            return JSON.toJSONString(value);
        }
        return String.valueOf(value);
    }
}
