package cn.edu.whu.boot.lydcextend.controller;

import cn.edu.whu.boot.collection.service.IBaseService;
import cn.edu.whu.boot.common.domain.CommonConstant;
import cn.edu.whu.boot.common.domain.ResultMessage;
import cn.edu.whu.boot.common.domain.SqlStringConstant;
import cn.edu.whu.boot.common.utils.collection.OtherUtil;
import cn.edu.whu.boot.common.utils.collection.PostgreSqlUtil;
import cn.edu.whu.boot.common.utils.collection.TableOperationUtil;
import cn.edu.whu.boot.xml.domain.Task;
import cn.edu.whu.boot.xml.service.ITaskService;
import cn.edu.whu.boot.xml.xmlreader.bean.Config;
import cn.edu.whu.boot.xml.xmlreader.bean.Field;
import cn.edu.whu.boot.xml.xmlreader.bean.Table;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.FileUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;

/**
 * 照片和媒体路径导出控制器
 * 根据 taskId 遍历任务的所有表：
 * 1. 对于以 _media 为后缀的表，提取表名、id、media_id、media_path 以及位置和相机相关字段
 * 2. 对于其他表，如果包含 photo 和 parentID 字段，则提取表名、ID、parentID 和 photo 字段
 */
@RestController
@RequestMapping("lydcextend")
public class PhotoMediaExportController {
    private static final Logger logger = LoggerFactory.getLogger(PhotoMediaExportController.class);

    private final ITaskService taskService;
    private final IBaseService baseService;

    @Autowired
    public PhotoMediaExportController(ITaskService taskService, IBaseService baseService) {
        this.taskService = taskService;
        this.baseService = baseService;
    }

    /**
     * 获取照片和媒体路径数据
     * 根据 taskId 遍历任务的所有表：
     * 1. 对于以 _media 为后缀的表，提取表名、id、media_id、media_path 以及位置和相机相关字段
     * 2. 对于其他表，如果包含 photo 和 parentID 字段，则提取表名、ID、parentID 和 photo 字段
     * 
     * @param taskId 任务ID
     * @return 照片和媒体数据列表（包含 relationsource 字段）
     */
    @RequestMapping(value = "getPhotoMedia", produces = "text/html;charset=UTF-8")
    public String getPhotoMedia(@RequestParam Integer taskId) {
        try {
            // 获取任务
            Task task = taskService.getTaskById(taskId);
            if (task == null) {
                return ResultMessage.failed("任务不存在").toString();
            }

            // 收集所有需要返回的数据
            List<Map<String, Object>> dataList = new ArrayList<>();
            String schemaName = task.getDatabaseName();
            
            // 缓存任务名、用户名和姓名，避免重复查询
            Map<Integer, String> taskNameCache = new HashMap<>();
            Map<Integer, String> userNameCache = new HashMap<>();
            Map<Integer, String> realNameCache = new HashMap<>();

            // 从数据库直接查询 schema 中的所有表
            String getAllTablesSql = "SELECT table_name FROM information_schema.tables " +
                    "WHERE table_schema = '" + schemaName + "' AND table_type = 'BASE TABLE' " +
                    "ORDER BY table_name";
            List<Map<String, Object>> allTablesResult = baseService.selectData(getAllTablesSql);
            
            if (allTablesResult == null || allTablesResult.isEmpty()) {
                return ResultMessage.failed("schema 中没有找到表").toString();
            }

            // 解析配置获取表配置（用于字段检查）
            Config config = JSON.toJavaObject(JSON.parseObject(task.getConfig()), Config.class);
            Map<String, Table> tableMap = config.getTables() != null ? config.getTables() : new HashMap<>();
            String configString = task.getConfig();

            // 遍历数据库中的所有表
            for (Map<String, Object> tableRow : allTablesResult) {
                String tableName = (String) tableRow.get("table_name");
                if (tableName == null) {
                    continue;
                }
                
                // 从配置中获取表信息（如果存在）
                Table table = tableMap.get(tableName);

                // 如果表名以 _media 为后缀，获取相关字段
                if (tableName.endsWith("_media")) {
                    // 查询表数据
                    String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
                    String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
                    List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);

                    if (tableDataList != null && !tableDataList.isEmpty()) {
                        // 处理每条数据
                        for (Map<String, Object> rowData : tableDataList) {
                            Map<String, Object> dataRow = new HashMap<>();
                            dataRow.put("schema名称", schemaName);
                            dataRow.put("表名", tableName);
                            
                            // id（父表ID）
                            Object idValue = rowData.get("id");
                            dataRow.put("ID", idValue != null ? idValue.toString() : "");
                            
                            // media_id
                            Object mediaIdValue = rowData.get("media_id");
                            dataRow.put("media_id", mediaIdValue != null ? mediaIdValue.toString() : "");
                            
                            // media_path
                            Object mediaPathValue = rowData.get("media_path");
                            dataRow.put("media_path", mediaPathValue != null ? mediaPathValue.toString() : "");
                            
                            // longitude（经度）
                            Object longitudeValue = rowData.get("longitude");
                            dataRow.put("longitude", longitudeValue != null ? longitudeValue.toString() : "");
                            
                            // latitude（纬度）
                            Object latitudeValue = rowData.get("latitude");
                            dataRow.put("latitude", latitudeValue != null ? latitudeValue.toString() : "");
                            
                            // altitude（高程）
                            Object altitudeValue = rowData.get("altitude");
                            dataRow.put("altitude", altitudeValue != null ? altitudeValue.toString() : "");
                            
                            // accuracy
                            Object accuracyValue = rowData.get("accuracy");
                            dataRow.put("accuracy", accuracyValue != null ? accuracyValue.toString() : "");
                            
                            // camera_angle
                            Object cameraAngleValue = rowData.get("camera_angle");
                            dataRow.put("camera_angle", cameraAngleValue != null ? cameraAngleValue.toString() : "");
                            
                            // camera_pitch
                            Object cameraPitchValue = rowData.get("camera_pitch");
                            dataRow.put("camera_pitch", cameraPitchValue != null ? cameraPitchValue.toString() : "");
                            
                            // camera_roll
                            Object cameraRollValue = rowData.get("camera_roll");
                            dataRow.put("camera_roll", cameraRollValue != null ? cameraRollValue.toString() : "");
                            
                            // 非 _media 表的字段设为空
                            dataRow.put("parentID", "");
                            dataRow.put("photo", "");
                            
                            // 解析任务名、账号和姓名
                            String mediaPathStr = mediaPathValue != null ? mediaPathValue.toString() : "";
                            parseAndSetTaskAndUser(dataRow, mediaPathStr, taskNameCache, userNameCache, realNameCache);
                            
                            // 构建 relationsource（对于 _media 表，id 是父表ID）
                            Object parentIdForMedia = idValue;
                            String relationsource = buildRelationSource(schemaName, tableName, parentIdForMedia, 
                                    tableMap, configString, baseService);
                            dataRow.put("relationsource", relationsource);
                            
                            dataList.add(dataRow);
                        }
                    }
                } else {
                    // 其他表：检查表是否有 photo 和 parentID 字段
                    // 先从数据库查询表的列信息
                    List<String> tableColumns = baseService.getTableColumns(schemaName, tableName);
                    boolean hasPhoto = tableColumns != null && tableColumns.contains("photo");
                    
                    // 从配置中获取 parentID 字段名（如果配置存在）
                    String parentIdFieldName = null;
                    if (table != null) {
                        parentIdFieldName = TableOperationUtil.getParentID(table);
                    } else {
                        // 如果配置中没有，尝试从数据库列中查找（通常 parentID 字段名可能不同）
                        if (tableColumns != null) {
                            for (String col : tableColumns) {
                                if (col.toLowerCase().contains("parent") || col.toLowerCase().contains("parentid")) {
                                    parentIdFieldName = col;
                                    break;
                                }
                            }
                        }
                    }

                    if (hasPhoto && parentIdFieldName != null) {
                        // 查询表数据
                        String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
                        String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
                        List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);

                        if (tableDataList != null && !tableDataList.isEmpty()) {
                            // 获取主键字段名
                            String primaryKey = null;
                            if (table != null) {
                                primaryKey = TableOperationUtil.getPrimaryKey(table);
                            }
                            
                            // 如果配置中没有主键信息，尝试从数据库查询
                            if (primaryKey == null && tableColumns != null) {
                                // 查询主键信息
                                String getPrimaryKeySql = "SELECT a.attname " +
                                        "FROM pg_index i " +
                                        "JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) " +
                                        "WHERE i.indrelid = '\"" + schemaName + "\".\"" + tableName + "\"'::regclass " +
                                        "AND i.indisprimary " +
                                        "LIMIT 1";
                                List<Map<String, Object>> pkResult = baseService.selectData(getPrimaryKeySql);
                                if (pkResult != null && !pkResult.isEmpty()) {
                                    primaryKey = (String) pkResult.get(0).get("attname");
                                }
                            }
                            
                            if (primaryKey == null) {
                                logger.warn("表 {} 没有主键，跳过", tableName);
                                continue;
                            }

                            // 处理每条数据
                            for (Map<String, Object> rowData : tableDataList) {
                                Map<String, Object> dataRow = new HashMap<>();
                                dataRow.put("schema名称", schemaName);
                                dataRow.put("表名", tableName);
                                
                                // ID（主键）
                                Object idValue = rowData.get(primaryKey);
                                dataRow.put("ID", idValue != null ? idValue.toString() : "");
                                
                                // parentID
                                Object parentIdValue = rowData.get(parentIdFieldName);
                                dataRow.put("parentID", parentIdValue != null ? parentIdValue.toString() : "");
                                
                                // photo
                                Object photoValue = rowData.get("photo");
                                dataRow.put("photo", photoValue != null ? photoValue.toString() : "");
                                
                                // 非 _media 表，相关字段设为空
                                dataRow.put("media_id", "");
                                dataRow.put("media_path", "");
                                dataRow.put("longitude", "");
                                dataRow.put("latitude", "");
                                dataRow.put("altitude", "");
                                dataRow.put("accuracy", "");
                                dataRow.put("camera_angle", "");
                                dataRow.put("camera_pitch", "");
                                dataRow.put("camera_roll", "");
                                
                                // 解析任务名、账号和姓名（从 photo 字段）
                                String photoStr = photoValue != null ? photoValue.toString() : "";
                                parseAndSetTaskAndUser(dataRow, photoStr, taskNameCache, userNameCache, realNameCache);
                                
                                // 构建 relationsource
                                String relationsource = buildRelationSource(schemaName, tableName, parentIdValue, 
                                        tableMap, configString, baseService);
                                dataRow.put("relationsource", relationsource);
                                
                                dataList.add(dataRow);
                            }
                        }
                    }
                }
            }

            if (dataList.isEmpty()) {
                return ResultMessage.failed("没有找到符合条件的数据").toString();
            }

            return ResultMessage.success(dataList).toString();
        } catch (Exception e) {
            logger.error("获取照片和媒体数据失败", e);
            return ResultMessage.failed("获取照片和媒体数据失败: " + e.getMessage()).toString();
        }
    }

    /**
     * 导出照片和媒体路径数据到 Excel
     * 
     * @param taskId 任务ID
     * @param response HTTP响应对象
     * @return 操作结果
     */
    @RequestMapping(value = "exportPhotoMedia", produces = "text/html;charset=UTF-8")
    public String exportPhotoMedia(@RequestParam Integer taskId, HttpServletResponse response) throws IOException {
        // 获取任务
        Task task = taskService.getTaskById(taskId);
        if (task == null) {
            return ResultMessage.failed("任务不存在").toString();
        }

        // 收集所有需要导出的数据
        List<Map<String, Object>> exportDataList = new ArrayList<>();
        String schemaName = task.getDatabaseName();
        
        // 缓存任务名、用户名和姓名，避免重复查询
        Map<Integer, String> taskNameCache = new HashMap<>();
        Map<Integer, String> userNameCache = new HashMap<>();
        Map<Integer, String> realNameCache = new HashMap<>();

        // 从数据库直接查询 schema 中的所有表
        String getAllTablesSql = "SELECT table_name FROM information_schema.tables " +
                "WHERE table_schema = '" + schemaName + "' AND table_type = 'BASE TABLE' " +
                "ORDER BY table_name";
        List<Map<String, Object>> allTablesResult = baseService.selectData(getAllTablesSql);
        
        if (allTablesResult == null || allTablesResult.isEmpty()) {
            return ResultMessage.failed("schema 中没有找到表").toString();
        }

        // 解析配置获取表配置（用于字段检查）
        Config config = JSON.toJavaObject(JSON.parseObject(task.getConfig()), Config.class);
        Map<String, Table> tableMap = config.getTables() != null ? config.getTables() : new HashMap<>();
        String configString = task.getConfig();

        // 遍历数据库中的所有表
        for (Map<String, Object> tableRow : allTablesResult) {
            String tableName = (String) tableRow.get("table_name");
            if (tableName == null) {
                continue;
            }
            
            // 从配置中获取表信息（如果存在）
            Table table = tableMap.get(tableName);

            // 如果表名以 _media 为后缀，获取相关字段
            if (tableName.endsWith("_media")) {
                // 查询表数据
                String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
                String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
                List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);

                if (tableDataList != null && !tableDataList.isEmpty()) {
                    // 处理每条数据
                    for (Map<String, Object> rowData : tableDataList) {
                        Map<String, Object> exportRow = new HashMap<>();
                        exportRow.put("schema名称", schemaName);
                        exportRow.put("表名", tableName);
                        
                        // id（父表ID）
                        Object idValue = rowData.get("id");
                        exportRow.put("ID", idValue != null ? idValue.toString() : "");
                        
                        // media_id
                        Object mediaIdValue = rowData.get("media_id");
                        exportRow.put("media_id", mediaIdValue != null ? mediaIdValue.toString() : "");
                        
                        // media_path
                        Object mediaPathValue = rowData.get("media_path");
                        exportRow.put("media_path", mediaPathValue != null ? mediaPathValue.toString() : "");
                        
                        // longitude（经度）
                        Object longitudeValue = rowData.get("longitude");
                        exportRow.put("longitude", longitudeValue != null ? longitudeValue.toString() : "");
                        
                        // latitude（纬度）
                        Object latitudeValue = rowData.get("latitude");
                        exportRow.put("latitude", latitudeValue != null ? latitudeValue.toString() : "");
                        
                        // altitude（高程）
                        Object altitudeValue = rowData.get("altitude");
                        exportRow.put("altitude", altitudeValue != null ? altitudeValue.toString() : "");
                        
                        // accuracy
                        Object accuracyValue = rowData.get("accuracy");
                        exportRow.put("accuracy", accuracyValue != null ? accuracyValue.toString() : "");
                        
                        // camera_angle
                        Object cameraAngleValue = rowData.get("camera_angle");
                        exportRow.put("camera_angle", cameraAngleValue != null ? cameraAngleValue.toString() : "");
                        
                        // camera_pitch
                        Object cameraPitchValue = rowData.get("camera_pitch");
                        exportRow.put("camera_pitch", cameraPitchValue != null ? cameraPitchValue.toString() : "");
                        
                        // camera_roll
                        Object cameraRollValue = rowData.get("camera_roll");
                        exportRow.put("camera_roll", cameraRollValue != null ? cameraRollValue.toString() : "");
                        
                        // 非 _media 表的字段设为空
                        exportRow.put("parentID", "");
                        exportRow.put("photo", "");
                        
                        // 解析任务名、账号和姓名
                        String mediaPathStr = mediaPathValue != null ? mediaPathValue.toString() : "";
                        parseAndSetTaskAndUser(exportRow, mediaPathStr, taskNameCache, userNameCache, realNameCache);
                        
                        // 构建 relationsource（对于 _media 表，id 是父表ID）
                        Object parentIdForMedia = idValue;
                        String relationsource = buildRelationSource(schemaName, tableName, parentIdForMedia, 
                                tableMap, configString, baseService);
                        exportRow.put("relationsource", relationsource);
                        
                        exportDataList.add(exportRow);
                    }
                }
            } else {
                // 其他表：检查表是否有 photo 和 parentID 字段
                // 先从数据库查询表的列信息
                List<String> tableColumns = baseService.getTableColumns(schemaName, tableName);
                boolean hasPhoto = tableColumns != null && tableColumns.contains("photo");
                
                // 从配置中获取 parentID 字段名（如果配置存在）
                String parentIdFieldName = null;
                if (table != null) {
                    parentIdFieldName = TableOperationUtil.getParentID(table);
                } else {
                    // 如果配置中没有，尝试从数据库列中查找（通常 parentID 字段名可能不同）
                    // 这里可以根据实际情况调整查找逻辑
                    if (tableColumns != null) {
                        for (String col : tableColumns) {
                            if (col.toLowerCase().contains("parent") || col.toLowerCase().contains("parentid")) {
                                parentIdFieldName = col;
                                break;
                            }
                        }
                    }
                }

                if (hasPhoto && parentIdFieldName != null) {
                    // 查询表数据
                    String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
                    String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
                    List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);

                    if (tableDataList != null && !tableDataList.isEmpty()) {
                        // 获取主键字段名
                        String primaryKey = null;
                        if (table != null) {
                            primaryKey = TableOperationUtil.getPrimaryKey(table);
                        }
                        
                        // 如果配置中没有主键信息，尝试从数据库查询
                        if (primaryKey == null && tableColumns != null) {
                            // 查询主键信息
                            String getPrimaryKeySql = "SELECT a.attname " +
                                    "FROM pg_index i " +
                                    "JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) " +
                                    "WHERE i.indrelid = '\"" + schemaName + "\".\"" + tableName + "\"'::regclass " +
                                    "AND i.indisprimary " +
                                    "LIMIT 1";
                            List<Map<String, Object>> pkResult = baseService.selectData(getPrimaryKeySql);
                            if (pkResult != null && !pkResult.isEmpty()) {
                                primaryKey = (String) pkResult.get(0).get("attname");
                            }
                        }
                        
                        if (primaryKey == null) {
                            logger.warn("表 {} 没有主键，跳过", tableName);
                            continue;
                        }

                        // 处理每条数据
                        for (Map<String, Object> rowData : tableDataList) {
                            Map<String, Object> exportRow = new HashMap<>();
                            exportRow.put("schema名称", schemaName);
                            exportRow.put("表名", tableName);
                            
                            // ID（主键）
                            Object idValue = rowData.get(primaryKey);
                            exportRow.put("ID", idValue != null ? idValue.toString() : "");
                            
                            // parentID
                            Object parentIdValue = rowData.get(parentIdFieldName);
                            exportRow.put("parentID", parentIdValue != null ? parentIdValue.toString() : "");
                            
                            // photo
                            Object photoValue = rowData.get("photo");
                            exportRow.put("photo", photoValue != null ? photoValue.toString() : "");
                            
                            // 非 _media 表，相关字段设为空
                            exportRow.put("media_id", "");
                            exportRow.put("media_path", "");
                            exportRow.put("longitude", "");
                            exportRow.put("latitude", "");
                            exportRow.put("altitude", "");
                            exportRow.put("accuracy", "");
                            exportRow.put("camera_angle", "");
                            exportRow.put("camera_pitch", "");
                            exportRow.put("camera_roll", "");
                            
                            // 解析任务名、账号和姓名（从 photo 字段）
                            String photoStr = photoValue != null ? photoValue.toString() : "";
                            parseAndSetTaskAndUser(exportRow, photoStr, taskNameCache, userNameCache, realNameCache);
                            
                            // 构建 relationsource
                            String relationsource = buildRelationSource(schemaName, tableName, parentIdValue, 
                                    tableMap, configString, baseService);
                            exportRow.put("relationsource", relationsource);
                            
                            exportDataList.add(exportRow);
                        }
                    }
                }
            }
        }

        if (exportDataList.isEmpty()) {
            return ResultMessage.failed("没有找到符合条件的数据").toString();
        }

        // 生成 Excel 文件
        String exportDir = CommonConstant.TEMP_FILE_PATHNAME + "/" + System.currentTimeMillis();
        File exportDirFile = new File(exportDir);
        exportDirFile.mkdirs();

        String excelFileName = task.getTaskName() + "_照片媒体导出.xlsx";
        File excelFile = new File(exportDir, excelFileName);
        
        try {
            createExcelFile(exportDataList, excelFile);
            
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.addHeader("Content-Disposition",
                    "attachment;fileName=" + new String(excelFileName.getBytes(StandardCharsets.UTF_8), "iso-8859-1"));
            
            // 将文件写入响应
            String result = OtherUtil.uploadFileByResponse(excelFile, response);
            
            // 清理临时文件
            FileUtils.deleteDirectory(exportDirFile);
            
            return CommonConstant.FAILED.equals(result) 
                    ? ResultMessage.failed("导出失败").toString() 
                    : ResultMessage.success(null).toString();
                    
        } catch (Exception e) {
            logger.error("导出 Excel 文件失败", e);
            FileUtils.deleteDirectory(exportDirFile);
            return ResultMessage.failed("导出失败：" + e.getMessage()).toString();
        }
    }

    /**
     * 创建 Excel 文件
     */
    private void createExcelFile(List<Map<String, Object>> dataList, File excelFile) throws IOException {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("照片媒体数据");

        // 创建样式
        // 表头样式：居中、加粗、有边框
        CellStyle headerStyle = workbook.createCellStyle();
        Font headerFont = workbook.createFont();
        headerFont.setBold(true);
        headerStyle.setFont(headerFont);
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headerStyle.setBorderTop(BorderStyle.THIN);
        headerStyle.setBorderBottom(BorderStyle.THIN);
        headerStyle.setBorderLeft(BorderStyle.THIN);
        headerStyle.setBorderRight(BorderStyle.THIN);
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        // 数据样式：居中、有边框
        CellStyle dataStyle = workbook.createCellStyle();
        dataStyle.setAlignment(HorizontalAlignment.CENTER);
        dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        dataStyle.setBorderTop(BorderStyle.THIN);
        dataStyle.setBorderBottom(BorderStyle.THIN);
        dataStyle.setBorderLeft(BorderStyle.THIN);
        dataStyle.setBorderRight(BorderStyle.THIN);

        // 创建表头
        Row headerRow = sheet.createRow(0);
        String[] headers = {"schema名称", "表名", "ID", "parentID", "photo", "media_id", "media_path", 
                            "longitude", "latitude", "altitude", "accuracy", "camera_angle", "camera_pitch", "camera_roll",
                            "任务名", "账号", "姓名", "relationsource"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }

        // 写入数据
        int rowNum = 1;
        for (Map<String, Object> rowData : dataList) {
            Row row = sheet.createRow(rowNum++);
            
            for (int i = 0; i < headers.length; i++) {
                String header = headers[i];
                Object value = rowData.get(header);
                Cell cell = row.createCell(i);
                cell.setCellStyle(dataStyle);
                
                if (value == null) {
                    cell.setBlank();
                } else if (value instanceof Number) {
                    cell.setCellValue(((Number) value).doubleValue());
                } else if (value instanceof Boolean) {
                    cell.setCellValue((Boolean) value);
                } else {
                    cell.setCellValue(value.toString());
                }
            }
        }

        // 自动调整列宽
        for (int i = 0; i < headers.length; i++) {
            sheet.autoSizeColumn(i);
            // 设置最小列宽
            int columnWidth = sheet.getColumnWidth(i);
            if (columnWidth < 2000) {
                sheet.setColumnWidth(i, 2000);
            } else if (columnWidth > 15000) {
                sheet.setColumnWidth(i, 15000);
            }
        }

        // 写入文件
        try (FileOutputStream fos = new FileOutputStream(excelFile)) {
            workbook.write(fos);
        } finally {
            workbook.close();
        }
    }

    /**
     * 从 media_path 或 photo 字段解析任务ID和用户ID，并查询数据库获取任务名、账号和姓名
     */
    private void parseAndSetTaskAndUser(Map<String, Object> exportRow, String pathStr, 
                                       Map<Integer, String> taskNameCache, Map<Integer, String> userNameCache,
                                       Map<Integer, String> realNameCache) {
        String taskName = "";
        String userName = "";
        String realName = "";
        
        if (pathStr != null && !pathStr.isEmpty()) {
            // 按 / 拆分路径
            String[] parts = pathStr.split("/");
            
            Integer taskId = null;
            Integer userId = null;
            
            // 查找 task_ 和 user_ 后的ID
            for (String part : parts) {
                if (part.startsWith("task_")) {
                    try {
                        String taskIdStr = part.substring(5); // 去掉 "task_" 前缀
                        taskId = Integer.parseInt(taskIdStr);
                    } catch (NumberFormatException e) {
                        logger.warn("无法解析任务ID: {}", part);
                    }
                } else if (part.startsWith("user_")) {
                    try {
                        String userIdStr = part.substring(5); // 去掉 "user_" 前缀
                        userId = Integer.parseInt(userIdStr);
                    } catch (NumberFormatException e) {
                        logger.warn("无法解析用户ID: {}", part);
                    }
                }
            }
            
            // 查询任务名
            if (taskId != null) {
                if (taskNameCache.containsKey(taskId)) {
                    taskName = taskNameCache.get(taskId);
                } else {
                    String queryTaskSql = "SELECT task_name FROM public.task WHERE id = " + taskId;
                    List<Map<String, Object>> taskResult = baseService.selectData(queryTaskSql);
                    if (taskResult != null && !taskResult.isEmpty()) {
                        Object taskNameObj = taskResult.get(0).get("task_name");
                        taskName = taskNameObj != null ? taskNameObj.toString() : "";
                        taskNameCache.put(taskId, taskName);
                    } else {
                        taskNameCache.put(taskId, "");
                    }
                }
            }
            
            // 查询用户名和姓名
            if (userId != null) {
                if (userNameCache.containsKey(userId) && realNameCache.containsKey(userId)) {
                    userName = userNameCache.get(userId);
                    realName = realNameCache.get(userId);
                } else {
                    String queryUserSql = "SELECT username, real_name FROM public.user_staff WHERE id = " + userId;
                    List<Map<String, Object>> userResult = baseService.selectData(queryUserSql);
                    if (userResult != null && !userResult.isEmpty()) {
                        Map<String, Object> userRow = userResult.get(0);
                        Object userNameObj = userRow.get("username");
                        userName = userNameObj != null ? userNameObj.toString() : "";
                        userNameCache.put(userId, userName);
                        
                        Object realNameObj = userRow.get("real_name");
                        realName = realNameObj != null ? realNameObj.toString() : "";
                        realNameCache.put(userId, realName);
                    } else {
                        userNameCache.put(userId, "");
                        realNameCache.put(userId, "");
                    }
                }
            }
        }
        
        exportRow.put("任务名", taskName);
        exportRow.put("账号", userName);
        exportRow.put("姓名", realName);
    }

    /**
     * 构建表层次关系JSON字符串
     * 
     * @param schemaName schema名称
     * @param currentTableName 当前表名
     * @param parentIdValue 父表ID值（可能为null）
     * @param tableMap 表配置映射
     * @param configString 配置字符串
     * @param baseService 数据库服务
     * @return JSON格式的层次关系字符串
     */
    private String buildRelationSource(String schemaName, String currentTableName, Object parentIdValue,
                                       Map<String, Table> tableMap, String configString, IBaseService baseService) {
        try {
            // 如果 parentID 为空，说明是根表，返回空对象
            if (parentIdValue == null || parentIdValue.toString().trim().isEmpty()) {
                return "{}";
            }

            // 查找当前表的父表
            String parentTableName = findParentTableName(currentTableName, tableMap);
            if (parentTableName == null) {
                return "{}";
            }

            // 构建当前层的关系
            Map<String, Object> relationMap = new HashMap<>();
            relationMap.put("parentTableName", parentTableName);
            relationMap.put("parentID", parentIdValue.toString());

            // 递归查找父表的父表
            Table parentTable = tableMap.get(parentTableName);
            if (parentTable != null) {
                String parentParentIdField = TableOperationUtil.getParentID(parentTable);
                if (parentParentIdField != null) {
                    // 查询父表记录，获取其 parentID
                    String parentTableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, parentTableName, false, false);
                    String parentPrimaryKey = TableOperationUtil.getPrimaryKey(parentTable);
                    if (parentPrimaryKey != null) {
                        // 获取主键字段的数据库类型
                        String parentPrimaryKeyDbType = null;
                        Map<String, Field> parentFields = parentTable.getFields();
                        if (parentFields != null) {
                            Field primaryKeyField = parentFields.get(parentPrimaryKey);
                            if (primaryKeyField != null) {
                                parentPrimaryKeyDbType = primaryKeyField.getDbType();
                            }
                        }
                        
                        // 构建安全的SQL查询，根据字段类型处理
                        String parentPrimaryKeyTransformed = PostgreSqlUtil.transformString(parentPrimaryKey);
                        String parentParentIdFieldTransformed = PostgreSqlUtil.transformString(parentParentIdField);
                        String parentIdValueStr = parentIdValue.toString();
                        
                        // 根据字段类型构建WHERE子句
                        String whereClause;
                        if (parentPrimaryKeyDbType != null && 
                            (parentPrimaryKeyDbType.toLowerCase().equals("integer") || 
                             parentPrimaryKeyDbType.toLowerCase().equals("long") ||
                             parentPrimaryKeyDbType.toLowerCase().equals("bigint") ||
                             parentPrimaryKeyDbType.toLowerCase().equals("double") ||
                             parentPrimaryKeyDbType.toLowerCase().equals("numeric"))) {
                            // 数字类型，不需要引号
                            whereClause = parentPrimaryKeyTransformed + " = " + parentIdValueStr;
                        } else {
                            // 字符串或其他类型，需要加引号并转义单引号
                            String escapedValue = parentIdValueStr.replace("'", "''");
                            whereClause = parentPrimaryKeyTransformed + " = '" + escapedValue + "'";
                        }
                        String selectParentSql = "SELECT " + parentParentIdFieldTransformed + " FROM " + parentTableNameInDb + " WHERE " + whereClause;
                        List<Map<String, Object>> parentResult = baseService.selectData(selectParentSql);
                        
                        if (parentResult != null && !parentResult.isEmpty()) {
                            Object parentParentIdValue = parentResult.get(0).get(parentParentIdField);
                            if (parentParentIdValue != null && !parentParentIdValue.toString().trim().isEmpty()) {
                                // 递归构建父表的父表关系
                                String parentParentRelation = buildRelationSource(schemaName, parentTableName, 
                                        parentParentIdValue, tableMap, configString, baseService);
                                if (!parentParentRelation.equals("{}")) {
                                    relationMap.put("parentParent", JSON.parseObject(parentParentRelation));
                                } else {
                                    relationMap.put("parentParent", new HashMap<>());
                                }
                            } else {
                                relationMap.put("parentParent", new HashMap<>());
                            }
                        } else {
                            relationMap.put("parentParent", new HashMap<>());
                        }
                    } else {
                        relationMap.put("parentParent", new HashMap<>());
                    }
                } else {
                    relationMap.put("parentParent", new HashMap<>());
                }
            } else {
                relationMap.put("parentParent", new HashMap<>());
            }

            return JSON.toJSONString(relationMap);
        } catch (Exception e) {
            logger.error("构建 relationsource 失败: {}", e.getMessage(), e);
            return "{}";
        }
    }

    /**
     * 查找指定表的父表名
     * 通过遍历所有表，找到哪些表的 associate 或 collection 字段指向当前表
     * 对于 _media 表，父表名就是去掉 _media 后缀的表名
     * 
     * @param childTableName 子表名
     * @param tableMap 表配置映射
     * @return 父表名，如果找不到返回 null
     */
    private String findParentTableName(String childTableName, Map<String, Table> tableMap) {
        if (childTableName == null || childTableName.trim().isEmpty()) {
            return null;
        }

        // 对于 _media 表，父表名就是去掉 _media 后缀的表名
        if (childTableName.endsWith("_media")) {
            String parentTableName = childTableName.substring(0, childTableName.length() - 6); // 去掉 "_media"
            // 验证父表是否存在于配置中
            if (tableMap != null && tableMap.containsKey(parentTableName)) {
                return parentTableName;
            }
        }

        if (tableMap == null || tableMap.isEmpty()) {
            return null;
        }

        // 遍历所有表，查找哪些表的 associate 或 collection 字段指向当前表
        for (Map.Entry<String, Table> entry : tableMap.entrySet()) {
            Table table = entry.getValue();
            if (table == null || table.getFields() == null) {
                continue;
            }

            // 检查该表的字段中是否有 associate 或 collection 指向当前表
            for (Map.Entry<String, Field> fieldEntry : table.getFields().entrySet()) {
                Field field = fieldEntry.getValue();
                if (field == null) {
                    continue;
                }

                // 检查 associate 字段
                String associate = field.getAssociate();
                if (associate != null && !associate.trim().isEmpty() && associate.equals(childTableName)) {
                    return entry.getKey();
                }

                // 检查 collection 字段
                String collection = field.getCollection();
                if (collection != null && !collection.trim().isEmpty() && collection.equals(childTableName)) {
                    return entry.getKey();
                }
            }
        }

        return null;
    }
}

