package com.ruoyi.project.sems.controller;

import com.alibaba.fastjson.JSON;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.document.ChartUtil;
import com.ruoyi.common.utils.document.DocumentHandler;
import com.ruoyi.common.utils.document.PDFTemplateUtil;
import com.ruoyi.common.utils.document.PDFUtil;
import com.ruoyi.common.utils.file.ExcelUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.officeConvert.OfficeConvertController;
import com.ruoyi.project.sems.domain.TMeasureRecord;
import com.ruoyi.project.sems.domain.TMeasureStress;
import com.ruoyi.project.sems.domain.TMeasureThickness;
import com.ruoyi.project.sems.mapper.TMeasureStressMapper;
import com.ruoyi.project.sems.service.ITMeasureRecordService;
import com.ruoyi.project.sems.service.ITMeasureThicknessService;
import freemarker.template.Template;
import io.jsonwebtoken.lang.Assert;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.jfree.data.category.DefaultCategoryDataset;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 定点测厚Controller
 *
 * @author ruoyi
 * @date 2021-07-07
 */
@RestController
@RequestMapping("/sems/thickness")
public class TMeasureThicknessController extends BaseController {
    @Autowired
    private ITMeasureThicknessService tMeasureThicknessService;
    @Autowired
    private ITMeasureRecordService tMeasureRecordService;
    @Autowired
    private OfficeConvertController officeConvertController;
    @Resource
    private TMeasureStressMapper tMeasureStressMapper;

    // 美标（ASME）与国标B系列外径对照表（单位：mm）
    private static final Map<Double, Double> INCH_TO_MM_MAP = new HashMap<>();

    static {
        // 基础尺寸（0.5"~4"）
        INCH_TO_MM_MAP.put(0.5, 21.3);   // 1/2英寸 → 21.3mm（国标B系列与ASME一致）[1,2](@ref)
        INCH_TO_MM_MAP.put(0.75, 26.7);  // 3/4英寸 → 26.7mm（国标B系列与ASME一致）
        INCH_TO_MM_MAP.put(1.0, 33.4);   // 1英寸 → 33.4mm（国标B系列与ASME一致）[1,2](@ref)
        INCH_TO_MM_MAP.put(1.5, 48.3);   // 1.5英寸 → 48.3mm（国标B系列与ASME一致）[1,2](@ref)
        INCH_TO_MM_MAP.put(2.0, 57.0);   // 2英寸 → 国标B系列57.0mm（ASME为60.3mm）[2,3](@ref)
        INCH_TO_MM_MAP.put(3.0, 88.9);   // 3英寸 → 88.9mm（国标B系列与ASME一致）[1,2](@ref)
        INCH_TO_MM_MAP.put(4.0, 114.3);  // 4英寸 → 114.3mm（国标B系列与ASME一致）
        INCH_TO_MM_MAP.put(5.0, 141.3);  // 5英寸
        // 扩展尺寸（6"~20"）
        INCH_TO_MM_MAP.put(6.0, 168.3);  // 6英寸 → 168.3mm（国标B系列与ASME一致）[2](@ref)
        INCH_TO_MM_MAP.put(8.0, 219.1);  // 8英寸 → 219.1mm（国标B系列与ASME一致）[2](@ref)
        INCH_TO_MM_MAP.put(10.0, 273.0); // 10英寸 → 273.0mm（国标B系列与ASME一致）[2](@ref)
        INCH_TO_MM_MAP.put(12.0, 323.9); // 12英寸 → 323.9mm（国标B系列与ASME一致）[2](@ref)
        INCH_TO_MM_MAP.put(14.0, 355.6); // 14英寸 → 355.6mm（国标B系列与ASME一致）[2](@ref)
        INCH_TO_MM_MAP.put(16.0, 406.4); // 16英寸 → 406.4mm（国标B系列与ASME一致）[2](@ref)
        INCH_TO_MM_MAP.put(18.0, 457.0); // 18英寸 → 457.0mm（国标B系列与ASME一致）[2](@ref)
        INCH_TO_MM_MAP.put(20.0, 508.0); // 20英寸 → 508.0mm（国标B系列与ASME一致）[2](@ref)
    }

    private final Long alarmtype = 1080L;//特种设备预警ID

    /**
     * 查询定点测厚列表
     */
    @PreAuthorize("@ss.hasPermi('sems:thickness:list')")
    @GetMapping("/list")
    public TableDataInfo list(TMeasureThickness tMeasureThickness) {
        logger.info(JSON.toJSONString(tMeasureThickness));
        startPage();
        List<TMeasureThickness> list = tMeasureThicknessService.selectTMeasureThicknessList(tMeasureThickness);
        for (TMeasureThickness m : list) {
            //最新测厚
            List<TMeasureRecord> measureRecords = tMeasureRecordService.queryRecords(m.getId().toString());
            if (measureRecords.size() > 0) {
                m.setFirstMeasureDate(measureRecords.get(measureRecords.size() - 1).getMeasureDate());
                m.setNewMeasureDate(measureRecords.get(0).getMeasureDate());
//                BigDecimal measureCycle = new BigDecimal(m.getMeasureCycle());
//                BigDecimal yearNum = new BigDecimal("31536000000");
//                Long cycle = measureCycle.multiply(yearNum).longValue();
//                Long newTime = measureRecords.get(0).getMeasureDate().getTime();
//                Long nextTime = newTime;
//                Date dat = new Date(nextTime);
//                GregorianCalendar nextMeasureDate = new GregorianCalendar();
//                nextMeasureDate.setTime(dat);
//                java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("yyyy-MM-dd");
//                m.setNextMeasureDate(format.format(nextMeasureDate.getTime()));
            } else {
                m.setFirstMeasureDate(null);
                m.setNewMeasureDate(null);
                m.setNextMeasureDate(null);
            }
            //寿命预警
            if (m.getNextWarnDate() != null && !StringUtils.isEmpty(m.getEstRemain())) {
                int day = this.formatDate(m.getNextWarnDate(), new Date());
                BigDecimal remain = new BigDecimal(m.getEstRemain()).multiply(new BigDecimal("365")).setScale(4, BigDecimal.ROUND_HALF_DOWN);
                logger.info(day + "::::" + remain);
                if (remain.compareTo(new BigDecimal(day)) == -1) {
                    m.setWarnFlag(1);
                } else {
                    m.setWarnFlag(0);
                }
            } else {
                m.setWarnFlag(0);
            }
        }
        return getDataTable(list);
    }

    /**
     * 批量导入
     */
    @PreAuthorize("@ss.hasPermi('sems:thickness:add')")
    @Log(title = "侧厚批量导入", businessType = BusinessType.INSERT)
    @PostMapping("/importData")
    public AjaxResult importData(@RequestParam("file") MultipartFile file) throws IOException {
        //获取操作人员ID
        Long userId = getUserId();
        //报错行数统计
        List<Integer> failRow = new ArrayList<Integer>();
        Workbook workbook = ExcelUtils.getWorkBook(file);
        Sheet sheet = workbook.getSheetAt(0);
        List<TMeasureThickness> list = new ArrayList<TMeasureThickness>();
        //字典查询

        int rowNum = sheet.getPhysicalNumberOfRows();
        int failNumber = 0;
        for (int i = 1; i < rowNum; i++) {
            try {
                logger.info("读取行数：" + i);
                Row row = sheet.getRow(i);
                int cellNum = row.getLastCellNum();
                TMeasureThickness entity = new TMeasureThickness();
                for (int j = 0; j < cellNum; j++) {
                    Cell cell = row.getCell(j);
                    if (cell == null) {
                        continue;
                    }
                    String cellValue = ExcelUtils.getCellValue(cell);
                    logger.info("cellValue:" + cellValue);
                    if (j == 0) {
                        //序号
                    } else if (j == 1) {
                        entity.setPlantCode(cellValue);//装置名称
                    } else if (j == 2) {
                        entity.setUnitCode(cellValue);//单元名称
                    } else if (j == 3) {
                        entity.setTagno(cellValue);//单位内编号
                    } else if (j == 4) {
                        entity.setPosition(cellValue);//测厚部位CML
                    } else if (j == 5) {
                        entity.setLoopNo(cellValue);//回路编号
                    } else if (j == 6) {
                        entity.setMeasureNo(cellValue);//检测编号
                    } else if (j == 7) {
                        entity.setEquipmentName(cellValue);//设备/管线名称
                    } else if (j == 8) {
                        entity.setMaterial(cellValue);//材质
                    } else if (j == 9) {
                        entity.setNominalTickness(cellValue);//公称壁厚(mm)
                    } else if (j == 10) {
                        entity.setThicknessMin(cellValue);//最小允许壁厚(mm)
                    } else if (j == 11) {
                        entity.setStCorrosion(cellValue);//短期腐蚀速率(mm/year)
                    } else if (j == 12) {
                        entity.setLtCorrosion(cellValue);//长期腐蚀速率(mm/year)
                    } else if (j == 13) {
                        entity.setMeasureCycle(cellValue);//长期腐蚀速率(mm/year)
                    } else if (j == 14) {
                        if (cellValue.length() > 3) {//下次测厚日期
                            entity.setNextWarnDate(new SimpleDateFormat(DateUtils.getDateFormat(cellValue)).parse(cellValue));
                        }
                    } else if (j == 15) {
                        entity.setInspectionMethod(cellValue);//检测方法
                    } else if (j == 16) {
                        entity.setCorAllowance(cellValue);//腐蚀裕度(mm)
                    } else if (j == 17) {
                        entity.setOriginalThickness(cellValue);//原始壁厚(mm)
                    } else if (j == 18) {
                        entity.setMedium(cellValue);//介质
                    } else if (j == 19) {
                        entity.setPressure(cellValue);//压力(MPa)
                    } else if (j == 20) {
                        entity.setSpecification(cellValue); //规格
                    } else if (j == 21) {
                        entity.setFlowRate(cellValue);//流速(m/s)
                    } else if (j == 22) {
                        //温度(℃)
                        entity.setTemperature(cellValue);
                    } else if (j == 23) {
                        //腐蚀类型
                        entity.setCorrosionType(cellValue);
                    } else if (j == 24) {
                        entity.setAnalysis(cellValue);//原因分析
                    } else if (j == 25) {
                        entity.setMethodCause(cellValue);//治理方法及依据
                    } else if (j == 26) {
                        entity.setEffectTracing(cellValue); //效果跟踪
                    } else if (j == 27) {
                        entity.setRaiser(cellValue);//提出人
                    } else if (j == 28) {
                        if (cellValue.length() > 3) {//提出时间
                            entity.setRaiserDate(new SimpleDateFormat(DateUtils.getDateFormat(cellValue)).parse(cellValue));
                        }
                    } else if (j == 29) {
                        entity.setOtherContent(cellValue);//其他检测方法内容
                    } else if (j == 30) {
                        entity.setRecorder(cellValue);//记录人
                    } else if (j == 31) {
                        if (cellValue.length() > 3) {//记录时间
                            entity.setRecorderDate(new SimpleDateFormat(DateUtils.getDateFormat(cellValue)).parse(cellValue));
                        }
                    } else if (j == 32) {
                        entity.setRemarks(cellValue);//备注
                    }
                }
                entity.setCreateBy(userId.toString());
                logger.info("entity:" + entity);
                list.add(entity);
            } catch (Exception e) {
                failNumber++;
                logger.info("e:" + JSON.toJSONString(e));
                failRow.add(i + 1);
            }
        }
        int successNumber = 0;
        int failNum = 0;
        for (TMeasureThickness t : list
        ) {
            failNum++;
            try {
                tMeasureThicknessService.insertTMeasureThickness(t);
                successNumber++;
            } catch (Exception e) {
                failNumber++;
                logger.info("e:" + e);
                failRow.add(failNum + 1);
            }
        }
        logger.info("list:" + JSON.toJSONString(list));
        logger.info("successNumber:" + String.valueOf(successNumber));
        logger.info("failNumber:" + String.valueOf(failNumber));
        logger.info("failRow:" + String.valueOf(failRow));
        return AjaxResult.success(String.valueOf(successNumber), failRow);
    }

    /**
     * 导出定点测厚列表
     */
    @PreAuthorize("@ss.hasPermi('sems:thickness:export')")
    @Log(title = "定点测厚", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult export(TMeasureThickness tMeasureThickness) {
        List<TMeasureThickness> list = tMeasureThicknessService.selectTMeasureThicknessList(tMeasureThickness);
        ExcelUtil<TMeasureThickness> util = new ExcelUtil<TMeasureThickness>(TMeasureThickness.class);
        return util.exportExcel(list, "thickness");
    }

    /**
     * 获取定点测厚详细信息
     */
    @PreAuthorize("@ss.hasPermi('sems:thickness:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        //生成图表
        String chartUrl = "/profile/" + this.getRecordUrl(id.toString());
        TMeasureThickness t = tMeasureThicknessService.selectTMeasureThicknessById(id);
        t.setRecordUrl(chartUrl);
        return AjaxResult.success(t);
    }

    /**
     * 新增定点测厚
     */
    @PreAuthorize("@ss.hasPermi('sems:thickness:add')")
    @Log(title = "定点测厚", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TMeasureThickness tMeasureThickness) {
        return toAjax(tMeasureThicknessService.insertTMeasureThickness(tMeasureThickness));
    }

    /**
     * 修改定点测厚
     */
    @PreAuthorize("@ss.hasPermi('sems:thickness:edit')")
    @Log(title = "定点测厚", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TMeasureThickness tMeasureThickness) {
        tMeasureThickness.setThicknessMin(calculateTsd(tMeasureThickness));
        return toAjax(tMeasureThicknessService.updateTMeasureThickness(tMeasureThickness));
    }

    /**
     * 删除定点测厚
     */
    @PreAuthorize("@ss.hasPermi('sems:thickness:remove')")
    @Log(title = "定点测厚", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(tMeasureThicknessService.deleteTMeasureThicknessByIds(ids));
    }

    /**
     * 定点测厚图片上传
     */
    @Log(title = "定点测厚图片上传", businessType = BusinessType.UPDATE)
    @PostMapping("/uploadFile")
    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        if (!file.isEmpty()) {
            String avatar = FileUploadUtils.upload(RuoYiConfig.getFilePath("/thickness"), file);
            return AjaxResult.success(avatar);
        }
        return AjaxResult.error("上传图片异常，请联系管理员");
    }


    @RequestMapping("/measure/exportPDF")
    public String measure(@RequestParam String id, HttpServletRequest request, HttpServletResponse response) {
        OutputStream out = null;
        try {
            getRecordUrl(id);
            out = response.getOutputStream();
            logger.info("id:" + id);
            //获取信息，就是上面的结构
            HashMap<String, Object> map = new HashMap<>();
            DocumentHandler dh = new DocumentHandler();
            Template t = dh.getTemplate();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            TMeasureThickness measureThicknessEntity = tMeasureThicknessService.selectTMeasureThicknessById(Long.parseLong(id));
            //生成图表
            String chartUrl = this.getRecordUrl(id);
            map.put("chartUrl", chartUrl);
            logger.info(chartUrl);
            //测量方法
            String[] inspectionMethod = measureThicknessEntity.getInspectionMethod().split(",");
            logger.info("inspectionMethod:" + inspectionMethod);
            for (String m : inspectionMethod) {
                if (m.equals("1")) {
                    measureThicknessEntity.setMethodUT(true);
                }
                if (m.equals("2")) {
                    measureThicknessEntity.setMethodPEC(true);
                }
                if (m.equals("3")) {
                    measureThicknessEntity.setMethodRT(true);
                }
                if (m.equals("4")) {
                    measureThicknessEntity.setMethodEMAT(true);
                }
                if (m.equals("5")) {
                    measureThicknessEntity.setMethodOther(true);
                }
            }
            map.put("measure", measureThicknessEntity);
            logger.info("measure:" + measureThicknessEntity);
            if (StringUtils.isNotEmpty(measureThicknessEntity.getPhoto())) {
                String[] photos = measureThicknessEntity.getPhoto().split(",");
                if (photos.length == 1) {
                    map.put("photo1", photos[0].replaceAll("/profile/", ""));
                } else if (photos.length == 2) {
                    map.put("photo1", photos[0].replaceAll("/profile/", ""));
                    map.put("photo2", photos[1].replaceAll("/profile/", ""));
                } else if (photos.length == 3) {
                    map.put("photo1", photos[0].replaceAll("/profile/", ""));
                    map.put("photo2", photos[1].replaceAll("/profile/", ""));
                    map.put("photo3", photos[2].replaceAll("/profile/", ""));
                }
            }
            if (StringUtils.isNotEmpty(measureThicknessEntity.getLocationUrl())) {
                String[] locationUrls = measureThicknessEntity.getLocationUrl().split(",");
                if (locationUrls.length == 1) {
                    map.put("locationUrl1", locationUrls[0].replaceAll("/profile/", ""));
                } else if (locationUrls.length == 2) {
                    map.put("locationUrl1", locationUrls[0].replaceAll("/profile/", ""));
                    map.put("locationUrl2", locationUrls[1].replaceAll("/profile/", ""));
                    logger.info(locationUrls[0]);
                } else if (locationUrls.length == 3) {
                    map.put("locationUrl1", locationUrls[0].replaceAll("/profile/", ""));
                    map.put("locationUrl2", locationUrls[1].replaceAll("/profile/", ""));
                    map.put("locationUrl3", locationUrls[2].replaceAll("/profile/", ""));
                }
            }
            //测量记录分行
            List<TMeasureRecord> measureRecords = tMeasureRecordService.queryRecords(id);
            List<List<TMeasureRecord>> result = new ArrayList<List<TMeasureRecord>>();
            int sourceSize = measureRecords.size();
            int size = (measureRecords.size() / 7) + 1;
            if (measureRecords.size() % 7 == 0) {
                size = size - 1;
            }
            for (int i = 0; i < size; i++) {
                List<TMeasureRecord> subset = new ArrayList<TMeasureRecord>();
                for (int j = i * 7; j < (i + 1) * 7; j++) {
                    if (j < sourceSize) {
                        subset.add(measureRecords.get(j));
                    }
                }
                if (subset.size() < 7) {
                    int supplement = 7 - subset.size();
                    for (int m = 0; m < supplement; m++) {
                        TMeasureRecord nullRecord = new TMeasureRecord();
                        subset.add(nullRecord);
                    }
                }
                result.add(subset);
            }
            map.put("result", result);
            logger.info("result:" + result);
            String name = measureThicknessEntity.getPlantCode() + "-" + measureThicknessEntity.getTagno() + "-" + measureThicknessEntity.getPosition();
            PDFTemplateUtil.exportPdf("measureFMaker.ftl", name + ".pdf", "file:" + RuoYiConfig.getProfile(), map, response);
//             PDFTemplateUtil.exportPdf("measureFMaker.ftl", name + ".pdf",RuoYiConfig.getProfile(), map, response);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null)
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        return null;
    }

    public String getRecordUrl(String id) {
        try {
            TMeasureThickness measureThicknessEntity = tMeasureThicknessService.selectTMeasureThicknessById(Long.parseLong(id));
            List<TMeasureRecord> measureRecords = tMeasureRecordService.queryRecords(id);
            Collections.reverse(measureRecords);
            //种类数据集
            DefaultCategoryDataset dataset = new DefaultCategoryDataset();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            for (TMeasureRecord t : measureRecords
            ) {
                dataset.addValue(t.getMeasureValue(), "数值Value", sdf.format(t.getMeasureDate()));
                if (measureThicknessEntity.getThicknessMin() != null) {
                    dataset.addValue(Double.parseDouble(measureThicknessEntity.getThicknessMin()), "最小允许壁厚", sdf.format(t.getMeasureDate()));
                }
            }
            String url = RuoYiConfig.getProfile() + "/" + id + ".jpg";
            ChartUtil.createLinePort("", dataset, "", "", url);

        } catch (Exception e) {
            logger.error("生成图片错误");
            logger.error(JSON.toJSONString(e));
        }
        return id + ".jpg";
    }

    private int formatDate(Date nowDate, Date sqlDate) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String newDate = df.format(nowDate);
        String sqlDate1 = df.format(sqlDate);
        try {
            nowDate = df.parse(newDate);
            sqlDate = df.parse(sqlDate1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Long time = nowDate.getTime();
        Long time2 = sqlDate.getTime();
        int day = (int) ((time - time2) / (24 * 3600 * 1000));
        return day;
    }

    /**
     * @param id
     * @return
     * @throws IOException
     */
    @GetMapping("/wordView/{id}")
    public AjaxResult wordView(@PathVariable Long id) throws IOException {
        //根据ID查询并生成
        String url = PreView(id);

        return AjaxResult.success(url);
    }


    /**
     * @param id 生成文件名
     * @return
     * @throws IOException
     */
    public String PreView(Long id) throws IOException {
        //根据ID查询并生成
        TMeasureThickness t = tMeasureThicknessService.selectTMeasureThicknessById(id);
        String url = this.createcheck(t);
        if (StringUtils.isNotEmpty(t.getCheckUrl())) {
            //合并PDF
            logger.info("url:" + url);
            // 将路径字符串转换为Path对象
            Path path = Paths.get(url);
            // 获取文件名
            String fileName = path.getFileName().toString();
            fileName = officeConvertController.wordTransPdf(url);
            String filePathOne = RuoYiConfig.getProfile() + "/" + fileName.replace("/profile", "");
            String filePathTwo = RuoYiConfig.getProfile() + "/" + t.getCheckUrl().replace("/profile", "");
            String newPdfPath = "sems/measure/" + t.getId() + ".pdf";
            logger.info("newPdfPath:" + newPdfPath);
            logger.info("filePathOne:" + filePathOne);
            logger.info("filePathTwo:" + filePathTwo);
            PDFUtil.mergeTwoPdfs(filePathOne, filePathTwo, RuoYiConfig.getProfile() + "/" + newPdfPath);
            return "/profile/" + newPdfPath;
        }
        return url;
    }

    /**
     * 生成wordt
     */
    public String createcheck(TMeasureThickness tMeasureThickness) throws IOException {
        //生成word
        //渲染文本
        Map<String, Object> params = getWordData(tMeasureThickness);
        // 模板路径
        String templatePath = "static/word/sems/measure/cehou.docx";
        // 生成word的路径
        String fileDir = RuoYiConfig.getProfile() + "/" + "sems/measure";
        // 生成word的文件名称
        String fileName = tMeasureThickness.getPlantCode() + "_" + tMeasureThickness.getId() + ".docx";
        String wordPath = this.createWord(templatePath, fileDir, fileName, params);
        return wordPath;
    }

    /**
     * 获取word数据
     */
    public Map<String, Object> getWordData(TMeasureThickness thickness) {
        Map<String, Object> params = new HashMap<>();

        params.put("plantCode", Texts.of(thickness.getPlantCode()).fontSize(10).create());
        params.put("unitCode", Texts.of(thickness.getUnitCode()).fontSize(10).create());
        params.put("tagno", Texts.of(thickness.getTagno()).fontSize(10).create());
        params.put("position", Texts.of(thickness.getPosition()).fontSize(10).create());
        params.put("recorder", Texts.of(thickness.getRecorder()).fontSize(10).create());
        params.put("recorderDate", Texts.of(DateUtils.dateTime(thickness.getRecorderDate())).fontSize(10).create());
        params.put("loopNo", Texts.of(thickness.getLoopNo()).fontSize(10).create());
        params.put("installDate", Texts.of(DateUtils.dateTime(thickness.getInstallDate())).fontSize(10).create());
        params.put("equipmentName", Texts.of(thickness.getEquipmentName()).fontSize(10).create());
        params.put("material", Texts.of(thickness.getMaterial()).fontSize(10).create());

        params.put("corAllowance", Texts.of(thickness.getCorAllowance()).fontSize(10).create());
        params.put("originalThickness", Texts.of(thickness.getOriginalThickness()).fontSize(10).create());
        params.put("medium", Texts.of(thickness.getMedium()).fontSize(10).create());
        params.put("pressure", Texts.of(thickness.getPressure()).fontSize(10).create());
        params.put("specification", Texts.of(thickness.getSpecification()).fontSize(10).create());
        params.put("flowRate", Texts.of(thickness.getFlowRate()).fontSize(10).create());
        params.put("temperature", Texts.of(thickness.getTemperature()).fontSize(10).create());
        params.put("corrosionType", Texts.of(thickness.getCorrosionType()).fontSize(10).create());
        params.put("nominalTickness", Texts.of(thickness.getNominalTickness()).fontSize(10).create());
        params.put("thicknessMin", Texts.of(thickness.getThicknessMin()).fontSize(10).create());
        params.put("stCorrosion", Texts.of(thickness.getStCorrosion()).fontSize(10).create());
        params.put("ltCorrosion", Texts.of(thickness.getLtCorrosion()).fontSize(10).create());
        params.put("estRemain", Texts.of(thickness.getEstRemain()).fontSize(10).create());
        params.put("methodCause", Texts.of(thickness.getMethodCause()).fontSize(10).create());
        params.put("effectTracing", Texts.of(thickness.getEffectTracing()).fontSize(10).create());
        params.put("raiser", Texts.of(thickness.getRaiser()).fontSize(10).create());
        params.put("raiserDate", Texts.of(DateUtils.dateTime(thickness.getRaiserDate())).fontSize(10).create());
        params.put("inspectionMethod", Texts.of(thickness.getInspectionMethod()).fontSize(10).create());


        if (StringUtils.isNotEmpty(thickness.getLocationUrl())) {
            String[] urlArr = thickness.getLocationUrl().split(",");
            if (urlArr.length > 0) {
                params.put("location1", Pictures.ofLocal(fileName(urlArr[0])).size(240, 240).create());
            }
            if (urlArr.length > 1) {
                params.put("location2", Pictures.ofLocal(fileName(urlArr[1])).size(240, 240).create());
            }
            if (urlArr.length > 2) {
                params.put("location3", Pictures.ofLocal(fileName(urlArr[2])).size(240, 240).create());
            }
        }
        if (StringUtils.isNotEmpty(thickness.getPhoto())) {
            String[] pArr = thickness.getPhoto().split(",");
            if (pArr.length > 0) {
                params.put("corrosion1", Pictures.ofLocal(fileName(pArr[0])).size(240, 240).create());
            }
            if (pArr.length > 1) {
                params.put("corrosion2", Pictures.ofLocal(fileName(pArr[1])).size(240, 240).create());
            }
            if (pArr.length > 2) {
                params.put("corrosion3", Pictures.ofLocal(fileName(pArr[2])).size(240, 240).create());
            }
        }
        String trendUrl = "/" + getRecordUrl(thickness.getId() + "");
        logger.info("trendUrl:" + trendUrl);
        params.put("trend", Pictures.ofLocal(fileName(trendUrl)).size(600, 300).create());

        //测量记录分行
        List<TMeasureRecord> measureRecords = tMeasureRecordService.queryRecords(thickness.getId() + "");
        RowRenderData[] rowList = new RowRenderData[measureRecords.size() + 1];
        rowList[0] = Rows.of("日期Date", "数值Value").textColor("FFFFFF")
                .bgColor("4472C4").center().create();
        List rows = new ArrayList();
        int i = 0;
        for (TMeasureRecord m : measureRecords
        ) {
            i++;
            rowList[i] = Rows.create(DateUtils.dateTime(m.getMeasureDate()), m.getMeasureValue() + "");
        }

        params.put("table", Tables.of(rowList).create());
        // 渲染文本
        return params;
    }

    /**
     * @param templatePath word模板文件路径
     * @param fileDir      生成的文件存放地址
     * @param fileName     生成的文件名
     * @param paramMap     参数集合
     * @return 返回word生成的路径
     */
    public String createWord(String templatePath, String fileDir, String fileName, Map<String, Object> paramMap) throws IOException {
        Assert.notNull(templatePath, "word模板文件路径不能为空");
        Assert.notNull(fileDir, "生成的文件存放地址不能为空");
        Assert.notNull(fileName, "生成的文件名不能为空");
        File dir = new File(fileDir);
        if (!dir.exists()) {
            logger.info("目录不存在，创建文件夹{}!", fileDir);
            dir.mkdirs();
        }
        fileName = fileName.replaceAll("/", "_"); //替换文件中敏感字段
        logger.info("目录文件{}!", fileName);
        String filePath = fileDir + "/" + fileName;
        logger.info("目录{}!", filePath);
        // 读取模板渲染参数
        InputStream is = getClass().getClassLoader().getResourceAsStream(templatePath);
        XWPFTemplate template = XWPFTemplate.compile(is).render(paramMap);
        try {
            // 将模板参数写入路径
            template.writeToFile(filePath);
            template.close();
        } catch (Exception e) {
            logger.error("生成word异常{}", e.getMessage());
            e.printStackTrace();
        }
        String pathFileName = FileUploadUtils.getPathFileName(RuoYiConfig.getFilePath("/" + "sems/measure"), fileName);
        return pathFileName;
    }

    /**
     * @param
     * @return 映射签名的文件名
     * @throws IOException
     */
    public String fileName(String filepath) {
        String newFilePath = filepath.replace("/profile", "");
        String pathName = RuoYiConfig.getProfile() + newFilePath;
        return pathName;
    }

    /**
     * 将字符串转换为 double 数值，支持多种格式（如逗号/小数点分隔符、千位分隔符等）
     *
     * @param valueStr 输入的字符串（如 "2.5", "1,200.75", "3,14"）
     * @return 转换后的 double 数值
     * @throws ParseException 如果无法解析字符串
     */
    public static double parseStringToDouble(String valueStr) throws ParseException {
        // 移除可能的千位分隔符（如 "1,000" -> "1000"）
        String sanitized = valueStr.replaceAll("[,']", ""); // 适配逗号或单引号作为千位分隔符

        // 适配不同地区的小数点格式（如 "3,14" 转换为 3.14）
        NumberFormat format = NumberFormat.getInstance(Locale.getDefault());
        return format.parse(sanitized).doubleValue();
    }


    /**
     * 将带单位的英寸字符串转换为国标B系列外径（毫米）
     *
     * @param input 输入字符串（如 "6\"", "2.5in", "3.14inch"）
     * @return 国标B系列对应的外径（毫米）
     * @throws ParseException           如果输入格式无法解析
     * @throws IllegalArgumentException 如果尺寸未在对照表中定义
     */
    public static double convertInchStringToMillimeters(String input) throws ParseException, IllegalArgumentException {
        // 1. 移除单位符号和空格
        String sanitized = input.trim()
                .replaceAll("[\"iInN]$", "")  // 移除末尾的 "、in、inch
                .replaceAll("\\s+", "");      // 移除中间空格

        // 2. 解析为 double 类型的英寸值
        double inches = parseStringToDouble(sanitized);

        // 3. 查找对照表并返回毫米值
        if (INCH_TO_MM_MAP.containsKey(inches)) {
            return INCH_TO_MM_MAP.get(inches);
        } else {
            throw new IllegalArgumentException("尺寸 " + inches + " 英寸未在对照表中定义");
        }
    }

    /**
     * 计算管道壁厚的通用方法（输入参数均为 String 类型）
     */
    public String calculateTsd(TMeasureThickness thickness) {
        try {
            // 转换所有参数为 double
            double p = 0;

            p = parseStringToDouble(thickness.getDesPressure());

            double d0 = convertInchStringToMillimeters(thickness.getSpecification());
            double ej = 1;
            double y = 0.4;

            TMeasureStress stress = tMeasureStressMapper.selectTMeasureStressByName(thickness.getMaterial());
            double c2 = 1.5;
            if (stress.getIsSteel() == 1) {
                c2 = 1;
            }
            String stStress = "";
            double desTemp = parseStringToDouble(thickness.getDesTemp());
            if (desTemp <= 40) {
                stStress = stress.getC40();
            } else if (desTemp <= 65) {
                stStress = stress.getC65();
            } else if (desTemp <= 100) {
                stStress = stress.getC100();
            } else if (desTemp <= 125) {
                stStress = stress.getC125();
            } else if (desTemp <= 150) {
                stStress = stress.getC150();
            } else if (desTemp <= 175) {
                stStress = stress.getC175();
            } else if (desTemp <= 200) {
                stStress = stress.getC200();
            } else if (desTemp <= 225) {
                stStress = stress.getC225();
            } else if (desTemp <= 250) {
                stStress = stress.getC250();
            } else if (desTemp <= 275) {
                stStress = stress.getC275();
            } else if (desTemp <= 300) {
                stStress = stress.getC300();
            } else if (desTemp <= 325) {
                stStress = stress.getC325();
            } else if (desTemp <= 350) {
                stStress = stress.getC350();
            } else if (desTemp <= 375) {
                stStress = stress.getC375();
            } else if (desTemp <= 400) {
                stStress = stress.getC400();
            } else if (desTemp <= 425) {
                stStress = stress.getC425();
            } else if (desTemp <= 450) {
                stStress = stress.getC450();   // 允许返回 null
            } else if (desTemp <= 475) {
                stStress = stress.getC475();   // 允许返回 null
            } else if (desTemp <= 500) {
                stStress = stress.getC500();   // 允许返回 null
            } else if (desTemp <= 525) {
                stStress = stress.getC525();   // 允许返回 null
            } else if (desTemp <= 550) {
                stStress = stress.getC550();   // 允许返回 null
            } else if (desTemp <= 575) {
                stStress = stress.getC575();   // 允许返回 null
            } else if (desTemp <= 600) {
                stStress = stress.getC600();   // 允许返回 null
            } else {
                stStress = stress.getC600();   // 超过 600 仍用 c600
            }

            double sT = parseStringToDouble(stStress);

            // 计算壁厚公式
            double numerator = p * d0;
            double denominator = 2 * (sT * ej + p * y);
            double tds = (numerator / denominator) + c2;
            // 使用BigDecimal四舍五入到两位小数
            return  BigDecimal.valueOf(tds)
                    .setScale(2, RoundingMode.HALF_UP).toString();
        } catch (Exception e) {
            e.printStackTrace();
            return thickness.getThicknessMin();
        }
    }


}
