package com.hotent.enterpriseDeclare.controller.material;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hotent.base.annotation.ApiGroup;
import com.hotent.base.constants.ApiGroupConsts;
import com.hotent.base.model.CommonResult;
import com.hotent.base.util.StringUtil;
import com.hotent.enterpriseDeclare.manager.CostAuditPeriodRecordManager;
import com.hotent.enterpriseDeclare.manager.CostSurveyTemplateUploadDataManager;
import com.hotent.enterpriseDeclare.model.CostAuditPeriodRecord;
import com.hotent.enterpriseDeclare.model.CostSurveyTemplateUploadData;
import com.hotent.project.manager.CostProjectApprovalManager;
import com.hotent.project.manager.CostProjectTaskManager;
import com.hotent.project.manager.CostProjectTaskMaterialManager;
import com.hotent.project.model.CostProjectApproval;
import com.hotent.project.model.CostProjectTask;
import com.hotent.project.model.CostProjectTaskMaterial;
import com.hotent.surveyinfo.dao.CostSurveyFdTemplateHeadersDao;
import com.hotent.surveyinfo.dao.CostSurveyFdTemplateItemsDao;
import com.hotent.surveyinfo.manager.CostSurveyFdTemplateHeadersManager;
import com.hotent.surveyinfo.manager.CostSurveyFdTemplateManager;
import com.hotent.surveyinfo.manager.CostSurveyFdTemplateVersionManager;
import com.hotent.surveyinfo.model.*;
import com.hotent.surveyinfo.model.dto.CostItemData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 财务数据表
 *
 * @company 山西清众科技股份有限公司
 * @author 超级管理员
 * @since 2025-01-27
 */
@RestController
@RequestMapping("/api/surveyFdTemplate/v1/")
@Api(tags = "财务数据表")
@ApiGroup(group = {ApiGroupConsts.GROUP_COST})
public class CostProjectTaskSurveyFdTemplateController {

    @Autowired
    private CostSurveyFdTemplateManager templateManager;

    @Autowired
    private CostSurveyFdTemplateVersionManager versionManager;

    @Autowired
    private CostSurveyFdTemplateHeadersDao headersDao;

    @Autowired
    private CostSurveyFdTemplateItemsDao itemsDao;

    @Autowired
    private CostSurveyTemplateUploadDataManager uploadDataManager;

    @Autowired
    private CostProjectTaskMaterialManager costProjectTaskMaterialManager;

    @Autowired
    private CostSurveyFdTemplateHeadersManager costSurveyFdTemplateHeadersManager;

    @Autowired
    private CostAuditPeriodRecordManager costAuditPeriodRecordManager;

    @Autowired
    private CostProjectApprovalManager costProjectApprovalManager;

    @Autowired
    private CostProjectTaskManager costProjectTaskManager;

    /**
     * 企业报送-财务数据表-列表
     * @param taskId 任务ID
     * @return 财务数据表列表
     */
    @GetMapping(value="/listByTaskId")
    @ApiOperation(value = "根据任务ID获取财务数据表列表", httpMethod = "GET")
    public CommonResult<List<CostProjectTaskMaterial>> listByTaskId(
            @RequestParam(required = true) String taskId) throws Exception {
        
        QueryWrapper<CostProjectTaskMaterial> wrapper = new QueryWrapper<>();
        wrapper.eq("task_id", taskId);
        List<CostProjectTaskMaterial> materialList = costProjectTaskMaterialManager.list(wrapper);
        return CommonResult.<List<CostProjectTaskMaterial>>ok().value(materialList);
    }

    /**
     * 企业报送-财务数据表-获取所需表格字段
     * @param surveyTemplateId 财务数据表模板ID
     * @return 指标项数据列表（带key-value拼接）
     */
    @GetMapping(value = "/listItemsByCurrentTemplateId")
    @ApiOperation(value = "根据财务数据表现行模板ID获取所有指标数据", httpMethod = "GET")
    public CommonResult<CostItemData> listItemsByCurrentTemplateId(
            @ApiParam(name = "surveyTemplateId", value = "关联的财务数据表ID", required = true)
            @RequestParam(required = true) String surveyTemplateId) throws Exception {

        // 根据模板ID查询现行版本信息
        CostSurveyFdTemplateVersion versionTemplate = versionManager.selectCurrentVersion(surveyTemplateId);
        if (versionTemplate == null) {
            return CommonResult.<CostItemData>ok().value(new CostItemData());
        }

        // 查询指标项和表头
        List<CostSurveyFdTemplateItems> items = itemsDao.selectBySurveyTemplateIdAndVersion(surveyTemplateId, versionTemplate.getId());
        List<CostSurveyFdTemplateHeaders> headList = costSurveyFdTemplateHeadersManager.listVisibleBySurveyTemplateIdAndVersion(surveyTemplateId, versionTemplate.getId());

        String filename = headList.stream().map(CostSurveyFdTemplateHeaders::getFieldName).collect(Collectors.joining(","));
        String filenids = headList.stream().map(CostSurveyFdTemplateHeaders::getId).collect(Collectors.joining(","));

        // 按 orderNum 分组
        Map<Integer, List<CostSurveyFdTemplateItems>> groupedByOrderNum = items.stream()
                .collect(Collectors.groupingBy(CostSurveyFdTemplateItems::getOrderNum));

        List<Map<String, String>> result = new ArrayList<>();

        for (Map.Entry<Integer, List<CostSurveyFdTemplateItems>> entry : groupedByOrderNum.entrySet()) {
            List<CostSurveyFdTemplateItems> group = entry.getValue();
            if (group.isEmpty()) continue;

            // 主项（取第一个）
            CostSurveyFdTemplateItems mainItem = group.get(0);

            String headersIds = "";
            String itemIds = "";
            // 构造 key-value 映射
            Map<String, String> keyValueMap = new HashMap<>();
            for (CostSurveyFdTemplateItems item : group) {
                if (item.getRkey() != null && item.getRvalue() != null) {
                    keyValueMap.put(item.getRkey(), item.getRvalue());
                    headersIds += item.getHeadersId() + ",";
                    itemIds += item.getId() + ",";
                }
            }
            if (!StringUtil.isEmpty(headersIds))
                headersIds = headersIds.substring(0, headersIds.length() - 1);

            if (!StringUtil.isEmpty(itemIds))
                itemIds = itemIds.substring(0, itemIds.length() - 1);

            // 将mainItem属性放入keyValueMap
            keyValueMap.put("id", mainItem.getId());
            keyValueMap.put("surveyTemplateId", mainItem.getSurveyTemplateId());
            keyValueMap.put("versionId", mainItem.getVersionId());
            keyValueMap.put("headersId", mainItem.getHeadersId());
            keyValueMap.put("cellCode", mainItem.getCellCode());
            keyValueMap.put("calculationFormula", mainItem.getCalculationFormula());
            keyValueMap.put("unit", mainItem.getUnit());
            keyValueMap.put("orderNum", mainItem.getOrderNum().toString());
            keyValueMap.put("jsonStr", mainItem.getJsonStr());
            keyValueMap.put("headersIds", headersIds);
            keyValueMap.put("itemIds", itemIds);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            keyValueMap.put("createTime", mainItem.getCreateTime() != null ? mainItem.getCreateTime().format(formatter) : null);
            keyValueMap.put("updateTime", mainItem.getUpdateTime() != null ? mainItem.getUpdateTime().format(formatter) : null);
            keyValueMap.put("createBy", mainItem.getCreateBy());
            keyValueMap.put("updateBy", mainItem.getUpdateBy());
            keyValueMap.put("projectId", mainItem.getProjectId());
            keyValueMap.put("orderText", mainItem.getOrderText());
            keyValueMap.put("calculationTemplateId", mainItem.getCalculationTemplateId());
            keyValueMap.put("rowid", mainItem.getRowid());
            keyValueMap.put("parentid", mainItem.getParentid());
            result.add(keyValueMap);
        }

        CostItemData data = new CostItemData();
        data.setFixedFields(filename);
        data.setItemlist(result);
        data.setFixedFieldids(filenids);
        return CommonResult.<CostItemData>ok().value(data);
    }

    /**
     * 企业报送-财务数据表-在线填报
     * @param dataList 数据列表
     * @return 保存结果
     */
    @PostMapping(value = "/saveUploadData")
    @ApiOperation(value = "保存财务数据表模板上传数据", httpMethod = "POST")
    public CommonResult<String> saveUploadData(
            @RequestBody List<CostSurveyTemplateUploadData> dataList) throws Exception {

        if (dataList == null || dataList.isEmpty()) {
            return CommonResult.<String>error().message("数据列表不能为空");
        }

        // 从第一条数据中提取信息
        CostSurveyTemplateUploadData firstData = dataList.get(0);
        String materialId = firstData.getRefId();
        String surveyTemplateId = firstData.getSurveyTemplateId();

        // 判断模板类型
        String templateType = null;
        if (StringUtil.isNotEmpty(surveyTemplateId)) {
            CostSurveyFdTemplate template = templateManager.getDetail(surveyTemplateId);
            if (template != null) {
                templateType = template.getTemplateType();
            }
        } else if (StringUtil.isNotEmpty(materialId)) {
            CostProjectTaskMaterial material = costProjectTaskMaterialManager.getById(materialId);
            if (material != null && StringUtil.isNotEmpty(material.getTemplateId())) {
                CostSurveyFdTemplate template = templateManager.getDetail(material.getTemplateId());
                if (template != null) {
                    templateType = template.getTemplateType();
                }
            }
        }

        // 如果是动态表(3)，需要检查periodRecordId
        if ("3".equals(templateType)) {
            String periodRecordId = firstData.getPeriodRecordId();
            if (StringUtil.isEmpty(periodRecordId)) {
                return CommonResult.<String>error().message("动态表需要先创建监审期间记录，periodRecordId不能为空");
            }
        }

        // 设置 type=2 表示财务表
        for (CostSurveyTemplateUploadData data : dataList) {
            data.setType("2");
        }

        uploadDataManager.saveData(dataList);

        // 更新材料上传状态
        if (StringUtil.isNotEmpty(materialId)) {
            CostProjectTaskMaterial material = costProjectTaskMaterialManager.getById(materialId);
            if (material != null) {
                material.setIsUpload("1");
                material.setUploadTime(LocalDateTime.now());
                costProjectTaskMaterialManager.updateById(material);
            }
        }

        return CommonResult.<String>ok().message("保存数据成功");
    }

    /**
     * 企业报送-财务数据表-在线填报记录查看
     * @param materialId 材料ID
     * @param periodRecordId 监审期间记录ID（动态表使用，可选）
     * @return 数据列表
     */
    @GetMapping(value = "/getUploadData")
    @ApiOperation(value = "查询财务数据表模板上传数据", httpMethod = "GET")
    public CommonResult<List<CostSurveyTemplateUploadData>> getUploadData(
            @ApiParam(name = "materialId", value = "材料ID", required = true)
            @RequestParam(required = true) String materialId,
            @ApiParam(name = "periodRecordId", value = "监审期间记录ID（动态表使用）")
            @RequestParam(required = false) String periodRecordId) throws Exception {

        if (StringUtil.isEmpty(materialId)) {
            return CommonResult.<List<CostSurveyTemplateUploadData>>error().message("materialId不能为空");
        }

        // 根据materialId查询数据，过滤type=2（财务表）
        QueryWrapper<CostSurveyTemplateUploadData> wrapper = new QueryWrapper<>();
        wrapper.eq("ref_id", materialId)
               .eq("type", "2")
               .eq("is_deleted", "0");
        
        // 如果指定了监审期间记录ID，添加过滤条件
        if (StringUtil.isNotEmpty(periodRecordId)) {
            wrapper.eq("period_record_id", periodRecordId);
        }
        
        wrapper.orderByAsc("rowid", "rkey");
        List<CostSurveyTemplateUploadData> dataList = uploadDataManager.list(wrapper);
        
        return CommonResult.<List<CostSurveyTemplateUploadData>>ok().value(dataList);
    }

    /**
     * 企业报送-财务数据表-动态表-新增监审期间记录
     * @param record 监审期间记录
     * @return 保存结果
     */
    @PostMapping(value = "/addPeriodRecord")
    @ApiOperation(value = "新增监审期间记录（动态表使用）", httpMethod = "POST")
    public CommonResult<CostAuditPeriodRecord> addPeriodRecord(
            @ApiParam(name = "record", value = "监审期间记录", required = true)
            @RequestBody CostAuditPeriodRecord record) throws Exception {

        if (record == null) {
            return CommonResult.<CostAuditPeriodRecord>error().message("记录不能为空");
        }

        if (StringUtil.isEmpty(record.getTaskId())) {
            return CommonResult.<CostAuditPeriodRecord>error().message("taskId不能为空");
        }

        if (StringUtil.isEmpty(record.getAuditPeriod())) {
            return CommonResult.<CostAuditPeriodRecord>error().message("auditPeriod不能为空");
        }

        // 校验项目监审期间
        CostProjectTask task = costProjectTaskManager.getById(record.getTaskId());
        CostProjectApproval approval = costProjectApprovalManager.getById(task.getProjectId());
        if (approval == null) {
            return CommonResult.<CostAuditPeriodRecord>error().message("项目不存在");
        }
        
        if (!Arrays.asList(approval.getAuditPeriod().split(",")).contains(record.getAuditPeriod())) {
            return CommonResult.<CostAuditPeriodRecord>error().message("项目所属监审期间不存在");
        }

        // 检查是否已存在相同的期间记录
        CostAuditPeriodRecord existRecord = costAuditPeriodRecordManager.getOne(
                new QueryWrapper<CostAuditPeriodRecord>()
                        .eq("type","2")
                        .eq("task_id", record.getTaskId())
                        .eq("audit_period", record.getAuditPeriod())
        );
        if (existRecord != null) {
            return CommonResult.<CostAuditPeriodRecord>error().message("该监审期间记录已存在");
        }


        // 设置填报时间为当前时间
        if (record.getReportingTime() == null) {
            record.setReportingTime(java.time.LocalDateTime.now());
        }
        record.setUploadId(record.getUploadId());
        record.setIsDeleted("0");
        record.setType("2");
        costAuditPeriodRecordManager.save(record);

        return CommonResult.<CostAuditPeriodRecord>ok().value(record).message("新增监审期间记录成功");
    }

    /**
     * 企业报送-财务数据表-动态表-查询监审期间记录列表
     * @param queryData 查询条件（包含uploadId和auditedUnitId）
     * @return 记录列表
     */
    @PostMapping(value = "/listPeriodRecord")
    @ApiOperation(value = "查询监审期间记录列表（动态表使用）", httpMethod = "POST", notes = "查询监审期间记录列表，返回记录列表")
    public CommonResult<List<CostAuditPeriodRecord>> listPeriodRecord(
            @ApiParam(name = "queryData", value = "查询条件", required = true)
            @RequestBody CostAuditPeriodRecord queryData) throws Exception {

        if (queryData == null || StringUtil.isEmpty(queryData.getUploadId()) || StringUtil.isEmpty(queryData.getAuditedUnitId())) {
            return CommonResult.<List<CostAuditPeriodRecord>>ok().message(null);
        }

        List<CostAuditPeriodRecord> recordList = costAuditPeriodRecordManager.listByUploadIdAndAuditedUnitId(queryData.getUploadId(), queryData.getAuditedUnitId(),"2");
        return CommonResult.<List<CostAuditPeriodRecord>>ok().value(recordList);
    }

    /**
     * 企业报送-财务数据表-动态表-删除监审期间记录
     * @param id 记录ID
     * @return 删除结果
     */
    @PostMapping(value = "/deletePeriodRecord")
    @ApiOperation(value = "删除监审期间记录（动态表使用）", httpMethod = "POST")
    public CommonResult<String> deletePeriodRecord(
            @ApiParam(name = "id", value = "记录ID", required = true)
            @RequestParam String id) throws Exception {

        if (StringUtil.isEmpty(id)) {
            return CommonResult.<String>error().message("id不能为空");
        }

        CostAuditPeriodRecord record = costAuditPeriodRecordManager.getById(id);
        if (record != null) {
            record.setIsDeleted("1");
            costAuditPeriodRecordManager.updateById(record);
            
            // 同时删除该期间下的所有上传数据
            QueryWrapper<CostSurveyTemplateUploadData> wrapper = new QueryWrapper<>();
            wrapper.eq("period_record_id", id)
                   .eq("type", "2");
            CostSurveyTemplateUploadData updateData = new CostSurveyTemplateUploadData();
            updateData.setIsDeleted("1");
            uploadDataManager.update(updateData, wrapper);
        }

        return CommonResult.<String>ok().message("删除监审期间记录成功");
    }

    /**
     * 企业报送-财务数据表-审核
     * @param material 材料对象（包含审核状态）
     * @return 审核结果
     */
    @PostMapping(value="/review")
    @ApiOperation(value = "财务数据表审核", httpMethod = "POST")
    public CommonResult<String> review(@RequestBody CostProjectTaskMaterial material) {
        CostProjectTaskMaterial existMaterial = costProjectTaskMaterialManager.getById(material.getId());
        if (existMaterial != null) {
            existMaterial.setAuditedStatus(material.getAuditedStatus());
            costProjectTaskMaterialManager.updateById(existMaterial);
        }
        return CommonResult.<String>ok().message("审核成功");
    }

    /**
     * 导出财务数据表Excel
     * @param surveyTemplateId 模板ID
     * @param versionId 版本ID（可选）
     * @param response HTTP响应对象
     */
    @GetMapping(value = "/exportExcel")
    @ApiOperation(value = "导出财务数据表Excel", httpMethod = "GET")
    public void exportExcel(
            @ApiParam(name = "surveyTemplateId", value = "模板ID", required = true)
            @RequestParam(required = true) String surveyTemplateId,
            @ApiParam(name = "versionId", value = "版本ID")
            @RequestParam(required = false) String versionId,
            HttpServletResponse response) throws Exception {

        CostSurveyFdTemplate template = templateManager.get(surveyTemplateId);
        if (template == null) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到指定的财务数据表模板");
            return;
        }

        CostSurveyFdTemplateVersion currentVersion = StringUtil.isNotEmpty(versionId) ?
                versionManager.get(versionId) : versionManager.selectCurrentVersion(surveyTemplateId);

        if (currentVersion == null) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到指定的模板版本");
            return;
        }

        List<CostSurveyFdTemplateHeaders> headersList = headersDao.selectBySurveyTemplateIdAndVersion(
                surveyTemplateId, currentVersion.getId()).stream()
                .filter(header -> StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible()))
                .sorted(Comparator.comparing(header -> {
                    String orderNum = header.getOrderNum();
                    return StringUtil.isEmpty(orderNum) ? Integer.MAX_VALUE :
                           Integer.parseInt(orderNum.replaceAll("\\D", "0"));
                }))
                .collect(Collectors.toList());

        if (headersList.isEmpty()) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到表头信息");
            return;
        }

        List<CostSurveyFdTemplateItems> itemsList = itemsDao.selectBySurveyTemplateIdAndVersion(
                surveyTemplateId, currentVersion.getId());

        Workbook workbook = new XSSFWorkbook();
        String sheetName = currentVersion.getSurveyTemplateName() != null ?
                currentVersion.getSurveyTemplateName() : "财务数据表";
        Sheet sheet = workbook.createSheet(sheetName);

        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < headersList.size(); i++) {
            headerRow.createCell(i).setCellValue(headersList.get(i).getFieldName());
        }

        if (itemsList != null && !itemsList.isEmpty()) {
            Map<String, Integer> headerIndexMap = new HashMap<>();
            for (int i = 0; i < headersList.size(); i++) {
                headerIndexMap.put(headersList.get(i).getId(), i);
            }
            fillExcelData(sheet, itemsList, headerIndexMap, template.getTemplateType());
        }

        for (int i = 0; i < headersList.size(); i++) {
            sheet.autoSizeColumn(i);
            sheet.setColumnWidth(i, Math.max(sheet.getColumnWidth(i), 3000));
        }

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = sheetName + "_" + System.currentTimeMillis() + ".xlsx";
        response.setHeader("Content-Disposition", "attachment; filename=" +
                URLEncoder.encode(fileName, "UTF-8"));

        workbook.write(response.getOutputStream());
        workbook.close();
    }

    /**
     * 导入财务数据表Excel数据
     */
    @PostMapping(value = "/importExcel")
    @ApiOperation(value = "导入财务数据表Excel数据", httpMethod = "POST")
    public CommonResult<String> importExcel(
            @ApiParam(name = "file", value = "Excel文件", required = true)
            @RequestParam("file") MultipartFile file,
            @ApiParam(name = "surveyTemplateId", value = "模板ID", required = true)
            @RequestParam(required = true) String surveyTemplateId,
            @ApiParam(name = "taskId", value = "任务ID", required = true)
            @RequestParam(required = true) String taskId,
            @ApiParam(name = "materialId", value = "材料ID", required = true)
            @RequestParam(required = true) String materialId,
            @ApiParam(name = "periodRecordId", value = "监审期间记录ID")
            @RequestParam(required = false) String periodRecordId) throws Exception {

        if (file == null || file.isEmpty()) {
            return CommonResult.<String>error().message("上传文件不能为空");
        }

        String fileName = file.getOriginalFilename();
        if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
            return CommonResult.<String>error().message("文件格式不正确，请上传Excel文件");
        }

        CostSurveyFdTemplate template = templateManager.get(surveyTemplateId);
        if (template == null) {
            return CommonResult.<String>error().message("未找到指定的财务数据表模板");
        }

        CostSurveyFdTemplateVersion currentVersion = versionManager.selectCurrentVersion(surveyTemplateId);
        if (currentVersion == null) {
            return CommonResult.<String>error().message("未找到启用的模板版本");
        }

        List<CostSurveyFdTemplateHeaders> headersList = headersDao.selectBySurveyTemplateIdAndVersion(
                surveyTemplateId, currentVersion.getId()).stream()
                .filter(header -> StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible()))
                .collect(Collectors.toList());

        if (headersList.isEmpty()) {
            return CommonResult.<String>error().message("未找到表头信息");
        }

        Map<String, CostSurveyFdTemplateHeaders> headerNameMap = headersList.stream()
                .filter(header -> StringUtil.isNotEmpty(header.getFieldName()))
                .collect(Collectors.toMap(
                    header -> header.getFieldName().trim(),
                    header -> header
                ));

        Workbook workbook = null;
        try (InputStream inputStream = file.getInputStream()) {
            workbook = fileName.endsWith(".xlsx") ?
                new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream);

            Sheet sheet = workbook.getSheetAt(0);
            if (sheet == null || sheet.getPhysicalNumberOfRows() < 2) {
                return CommonResult.<String>error().message("Excel文件没有数据");
            }

            Row headerRow = sheet.getRow(0);
            if (headerRow == null) {
                return CommonResult.<String>error().message("Excel文件第一行为空");
            }

            Map<Integer, CostSurveyFdTemplateHeaders> columnIndexMap = new HashMap<>();
            for (int i = 0; i < headerRow.getLastCellNum(); i++) {
                Cell cell = headerRow.getCell(i);
                if (cell != null) {
                    String cellValue = getCellStringValue(cell);
                    if (StringUtil.isNotEmpty(cellValue)) {
                        CostSurveyFdTemplateHeaders header = headerNameMap.get(cellValue.trim());
                        if (header != null) {
                            columnIndexMap.put(i, header);
                        }
                    }
                }
            }

            if (columnIndexMap.isEmpty()) {
                return CommonResult.<String>error().message("Excel表头与模板表头不匹配");
            }

            List<CostSurveyTemplateUploadData> dataList = new ArrayList<>();
            int dataRowCount = 0;

            for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                Row dataRow = sheet.getRow(rowIndex);
                if (dataRow == null || isEmptyRow(dataRow)) continue;

                String currentRowId = "1".equals(template.getTemplateType()) ?
                    "row_" + System.currentTimeMillis() : "row_" + rowIndex;

                for (Map.Entry<Integer, CostSurveyFdTemplateHeaders> entry : columnIndexMap.entrySet()) {
                    Cell cell = dataRow.getCell(entry.getKey());
                    String cellValue = getCellStringValue(cell);

                    if (StringUtil.isNotEmpty(cellValue)) {
                        CostSurveyTemplateUploadData uploadData = createUploadData(
                                surveyTemplateId, taskId, materialId, currentRowId,
                                entry.getValue(), cellValue, periodRecordId);
                        dataList.add(uploadData);
                    }
                }
                dataRowCount++;
            }

            if (dataList.isEmpty()) {
                return CommonResult.<String>error().message("Excel文件中没有有效数据");
            }

            uploadDataManager.saveData(dataList);
            CostProjectTaskMaterial material = costProjectTaskMaterialManager.getById(materialId);
            material.setIsUpload("1");
            material.setUploadTime(LocalDateTime.now());
            costProjectTaskMaterialManager.updateById(material);

            return CommonResult.<String>ok().message("导入成功，共导入 " + dataRowCount + " 行数据");
        } catch (Exception e) {
            return CommonResult.<String>error().message("导入失败：" + e.getMessage());
        } finally {
            if (workbook != null) {
                workbook.close();
            }
        }
    }

    // ==================== 私有辅助方法 ====================

    private void fillExcelData(Sheet sheet, List<CostSurveyFdTemplateItems> itemsList,
                              Map<String, Integer> headerIndexMap, String templateType) {
        if ("1".equals(templateType)) {
            // 单表：所有数据在一行
            Row dataRow = sheet.createRow(1);
            for (CostSurveyFdTemplateItems item : itemsList) {
                Integer colIndex = headerIndexMap.get(item.getHeadersId());
                if (colIndex != null) {
                    dataRow.createCell(colIndex).setCellValue(getItemValue(item));
                }
            }
        } else {
            // 固定表和动态表：按rowid分组
            Map<String, List<CostSurveyFdTemplateItems>> itemsByRowId = itemsList.stream()
                    .filter(item -> StringUtil.isNotEmpty(item.getRowid()))
                    .collect(Collectors.groupingBy(CostSurveyFdTemplateItems::getRowid));

            int rowNum = 1;
            for (Map.Entry<String, List<CostSurveyFdTemplateItems>> entry : itemsByRowId.entrySet()) {
                Row dataRow = sheet.createRow(rowNum++);
                for (CostSurveyFdTemplateItems item : entry.getValue()) {
                    Integer colIndex = headerIndexMap.get(item.getHeadersId());
                    if (colIndex != null) {
                        dataRow.createCell(colIndex).setCellValue(getItemValue(item));
                    }
                }
            }
        }
    }

    private String getItemValue(CostSurveyFdTemplateItems item) {
        return StringUtil.isNotEmpty(item.getRvalue()) ? item.getRvalue() :
               StringUtil.isNotEmpty(item.getJsonStr()) ? item.getJsonStr() : "";
    }

    private CostSurveyTemplateUploadData createUploadData(String surveyTemplateId, String taskId,
                                                          String materialId, String rowid,
                                                          CostSurveyFdTemplateHeaders header,
                                                          String value, String periodRecordId) {
        CostSurveyTemplateUploadData uploadData = new CostSurveyTemplateUploadData();
        uploadData.setSurveyTemplateId(surveyTemplateId);
        uploadData.setTaskId(taskId);
        uploadData.setRefId(materialId);
        uploadData.setType("2");
        uploadData.setRowid(rowid);
        uploadData.setRkey(StringUtil.isNotEmpty(header.getFieldEname()) ?
                          header.getFieldEname() : header.getFieldName());
        uploadData.setRvalue(value);
        if (StringUtil.isNotEmpty(periodRecordId)) {
            uploadData.setPeriodRecordId(periodRecordId);
        }
        uploadData.setIsDeleted("0");
        return uploadData;
    }

    private String getCellStringValue(Cell cell) {
        if (cell == null) return "";

        switch (cell.getCellType()) {
            case STRING: return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    double numericValue = cell.getNumericCellValue();
                    return numericValue == (long) numericValue ?
                           String.valueOf((long) numericValue) : String.valueOf(numericValue);
                }
            case BOOLEAN: return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    return cell.getStringCellValue();
                } catch (Exception e) {
                    try {
                        return String.valueOf(cell.getNumericCellValue());
                    } catch (Exception ex) {
                        return "";
                    }
                }
            default: return "";
        }
    }

    private boolean isEmptyRow(Row row) {
        for (int colIndex = 0; colIndex < row.getLastCellNum(); colIndex++) {
            Cell cell = row.getCell(colIndex);
            if (cell != null && StringUtil.isNotEmpty(getCellStringValue(cell))) {
                return false;
            }
        }
        return true;
    }
}
