package com.ruoyi.web.calculate.service.impl;

import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.web.calculate.domain.CmcNonparallelismCorrection;
import com.ruoyi.web.calculate.service.ICmcNonparallelismCorrectionService;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 非平行差改正服务实现
 * 
 * @author qyx
 * @date 2026-06-22
 */
@Service
public class CmcNonparallelismCorrectionServiceImpl implements ICmcNonparallelismCorrectionService {

    // 扁率直接计算精度不够，在后面的椭球参数选择中用BigDecimal计算，下面的F是分母
    private static final double A_WGS84 = 6378137.0;
    private static final String F_WGS84 = "298.257223563";

    private static final double A_CGCS2000 = 6378137.0;
    private static final String F_CGCS2000 = "298.257222101";

    private static final double A_BJ54 = 6378245.0;
    private static final String F_BJ54 = "298.3";

    private static final double A_XA80 = 6378140.0;
    private static final String F_XA80 = "298.257";

    private static double A;
    private static double F;
    private static double E2;

    
    /**
     * 导入Excel数据（支持多个工作表和列映射）
     * 重构后：返回所有工作表信息，由前端选择工作表和配置字段映射
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importExcelData(MultipartFile file, List<String> sheetNames, String columnMappingsJson) {
        try {
            // 获取所有工作表名称
            List<String> allSheetNames = getSheetNames(file);
            
            // 存储每个工作表的信息
            List<Map<String, Object>> sheetInfoList = new ArrayList<>();
            
            // 读取每个工作表的表头和原始数据
            for (String sheetName : allSheetNames) {
                List<String> headers = readSheetHeaders(file, sheetName);
                List<Map<String, Object>> rawData = readRawSheetDataAsMap(file, sheetName, headers);
                
                Map<String, Object> sheetInfo = new HashMap<>();
                sheetInfo.put("sheetName", sheetName);
                sheetInfo.put("headers", headers);
                sheetInfo.put("rawData", rawData);
                sheetInfoList.add(sheetInfo);
            }

            // 构建返回结果（参考gausspositive格式，但支持多sheet）
            Map<String, Object> result = new HashMap<>();
            result.put("sheetNames", allSheetNames);
            result.put("sheetInfo", sheetInfoList);

            String message = String.format("导入成功！共%d个工作表", allSheetNames.size());
            return AjaxResult.success(message, result);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("导入失败：" + e.getMessage());
        }
    }
    
    /**
     * 读取工作表的表头信息
     * 
     * @param file Excel文件
     * @param sheetName 工作表名称
     * @return 表头列表
     */
    private List<String> readSheetHeaders(MultipartFile file, String sheetName) {
        List<String> headers = new ArrayList<>();
        
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = createWorkbook(inputStream, file.getOriginalFilename())) {
            // 查找指定名称的工作表
            Sheet sheet = workbook.getSheet(sheetName);
            
            if (sheet == null) {
                // 如果按名称找不到，尝试按索引查找
                try {
                    int sheetIndex = Integer.parseInt(sheetName);
                    sheet = workbook.getSheetAt(sheetIndex);
                } catch (NumberFormatException e) {
                    return headers;
                }
            }
            
            if (sheet == null) {
                return headers;
            }
            
            // 读取第一行作为表头
            org.apache.poi.ss.usermodel.Row headerRow = sheet.getRow(0);
            if (headerRow != null) {
                int lastCellNum = headerRow.getLastCellNum();
                for (int i = 0; i < lastCellNum; i++) {
                    String header = getCellStringValue(headerRow.getCell(i));
                    // 过滤掉null、空字符串和"null"字符串的表头，避免生成null键导致JSON序列化失败
                    if (header != null && !header.trim().isEmpty() && !"null".equalsIgnoreCase(header.trim())) {
                        headers.add(header);
                    }
                }
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return headers;
    }
    
    /**
     * 读取工作表的原始数据（从第二行开始），转换为Map格式
     * 
     * @param file Excel文件
     * @param sheetName 工作表名称
     * @param headers 表头列表
     * @return 原始数据列表（Map格式）
     */
    private List<Map<String, Object>> readRawSheetDataAsMap(MultipartFile file, String sheetName, List<String> headers) {
        List<Map<String, Object>> rawData = new ArrayList<>();
        
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = createWorkbook(inputStream, file.getOriginalFilename())) {
            // 查找指定名称的工作表
            Sheet sheet = workbook.getSheet(sheetName);
            
            if (sheet == null) {
                try {
                    int sheetIndex = Integer.parseInt(sheetName);
                    sheet = workbook.getSheetAt(sheetIndex);
                } catch (NumberFormatException e) {
                    return rawData;
                }
            }
            
            if (sheet == null) {
                return rawData;
            }
            
            // 从第二行开始读取数据
            int lastRowNum = sheet.getLastRowNum();
            for (int i = 1; i <= lastRowNum; i++) {
                org.apache.poi.ss.usermodel.Row row = sheet.getRow(i);
                if (row == null) continue;
                
                Map<String, Object> rowData = new HashMap<>();
                for (int j = 0; j < headers.size(); j++) {
                    rowData.put(headers.get(j), getCellStringValue(row.getCell(j)));
                }
                
                // 跳过空行
                boolean hasData = false;
                for (Object obj : rowData.values()) {
                    if (obj != null && !"".equals(obj.toString().trim())) {
                        hasData = true;
                        break;
                    }
                }
                if (hasData) {
                    rawData.add(rowData);
                }
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return rawData;
    }
    
    /**
     * 从指定工作表读取Excel数据
     * 
     * @param file Excel文件
     * @param sheetName 工作表名称
     * @return 数据列表
     */
    private List<CmcNonparallelismCorrection> importExcelFromSheet(MultipartFile file, String sheetName) {
        return importExcelFromSheet(file, sheetName, null);
    }
    
    /**
     * 从指定工作表读取Excel数据（支持列映射）
     * 
     * @param file Excel文件
     * @param sheetName 工作表名称
     * @param columnMapping 列映射配置（字段名 -> 列索引），为空则使用默认映射
     * @return 数据列表
     */
    private List<CmcNonparallelismCorrection> importExcelFromSheet(MultipartFile file, String sheetName, Map<String, Integer> columnMapping) {
        List<CmcNonparallelismCorrection> dataList = new ArrayList<>();
        
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = createWorkbook(inputStream, file.getOriginalFilename())) {
            // 查找指定名称的工作表
            Sheet sheet = workbook.getSheet(sheetName);
            
            if (sheet == null) {
                // 如果按名称找不到，尝试按索引查找
                try {
                    int sheetIndex = Integer.parseInt(sheetName);
                    sheet = workbook.getSheetAt(sheetIndex);
                } catch (NumberFormatException e) {
                    // 不是数字索引，返回空列表
                    return dataList;
                }
            }
            
            if (sheet == null) {
                return dataList;
            }
            
            // 直接使用POI解析Sheet数据
            int lastRowNum = sheet.getLastRowNum();
            // 从第二行开始读取（跳过表头）
            for (int i = 1; i <= lastRowNum; i++) {
                org.apache.poi.ss.usermodel.Row row = sheet.getRow(i);
                if (row == null) {
                    continue;
                }
                
                CmcNonparallelismCorrection item = new CmcNonparallelismCorrection();
                
                if (columnMapping != null && !columnMapping.isEmpty()) {
                    // 使用自定义列映射
                    // 测段高差计算字段
                    int colIndex = columnMapping.getOrDefault("startPointNo", -1);
                    if (colIndex >= 0) {
                        item.setStartPointNo(getCellStringValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("endPointNo", -1);
                    if (colIndex >= 0) {
                        item.setEndPointNo(getCellStringValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("distance", -1);
                    if (colIndex >= 0) {
                        item.setDistance(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("heightDifference", -1);
                    if (colIndex >= 0) {
                        item.setHeightDifference(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("scaleTrueLength", -1);
                    if (colIndex >= 0) {
                        item.setScaleTrueLength(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("level", -1);
                    if (colIndex >= 0) {
                        Integer levelValue = getCellIntegerValue(row.getCell(colIndex));
                        item.setLevel(levelValue != null ? levelValue : 0);
                    }
                    
                    // 不平行改正计算字段
                    colIndex = columnMapping.getOrDefault("pendingPoint", -1);
                    if (colIndex >= 0) {
                        item.setPendingPoint(getCellStringValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("coordinateX", -1);
                    if (colIndex >= 0) {
                        item.setCoordinateX(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("coordinateY", -1);
                    if (colIndex >= 0) {
                        item.setCoordinateY(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("heightH", -1);
                    if (colIndex >= 0) {
                        item.setHeightH(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("coordinateSystem", -1);
                    if (colIndex >= 0) {
                        item.setCoordinateSystem(getCellStringValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("zoneNo", -1);
                    if (colIndex >= 0) {
                        item.setZoneNo(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("bandWidth", -1);
                    if (colIndex >= 0) {
                        item.setBandWidth(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("latitudePosition", -1);
                    if (colIndex >= 0) {
                        item.setLatitudePosition(getCellStringValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("longitudePosition", -1);
                    if (colIndex >= 0) {
                        item.setLongitudePosition(getCellStringValue(row.getCell(colIndex)));
                    }
                    
                    colIndex = columnMapping.getOrDefault("projectionHeight", -1);
                    if (colIndex >= 0) {
                        item.setProjectionHeight(getCellDoubleValue(row.getCell(colIndex)));
                    }
                    
                } else {
                    // 使用默认列映射
                    // 测段高差计算字段（前7列）
                    item.setStartPointNo(getCellStringValue(row.getCell(0)));
                    item.setEndPointNo(getCellStringValue(row.getCell(1)));
                    item.setDistance(getCellDoubleValue(row.getCell(2)));
                    item.setHeightDifference(getCellDoubleValue(row.getCell(3)));
                    item.setScaleTrueLength(getCellDoubleValue(row.getCell(4)));
                    Integer levelValue = getCellIntegerValue(row.getCell(5));
                    item.setLevel(levelValue != null ? levelValue : 0);
                    // 不平行改正计算字段（后续列）
                    item.setPendingPoint(getCellStringValue(row.getCell(6)));
                    item.setCoordinateX(getCellDoubleValue(row.getCell(7)));
                    item.setCoordinateY(getCellDoubleValue(row.getCell(8)));
                    item.setHeightH(getCellDoubleValue(row.getCell(9)));
                    item.setCoordinateSystem(getCellStringValue(row.getCell(10)));
                    item.setZoneNo(getCellDoubleValue(row.getCell(11)));
                    item.setBandWidth(getCellDoubleValue(row.getCell(12)));
                    item.setLatitudePosition(getCellStringValue(row.getCell(13)));
                    item.setLongitudePosition(getCellStringValue(row.getCell(14)));
                    item.setProjectionHeight(getCellDoubleValue(row.getCell(15)));
                }
                
                dataList.add(item);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return dataList;
    }
    
    /**
     * 获取单元格的字符串值
     */
    private String getCellStringValue(org.apache.poi.ss.usermodel.Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                // 数字类型转字符串，避免科学计数法
                double numValue = cell.getNumericCellValue();
                if (numValue == Math.floor(numValue)) {
                    return String.valueOf((long) numValue);
                }
                return String.valueOf(numValue);
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    return cell.getStringCellValue();
                } catch (Exception e) {
                    return String.valueOf(cell.getNumericCellValue());
                }
            default:
                return null;
        }
    }
    
    /**
     * 获取单元格的Double值
     */
    private Double getCellDoubleValue(org.apache.poi.ss.usermodel.Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellType()) {
            case NUMERIC:
                return cell.getNumericCellValue();
            case STRING:
                try {
                    return Double.parseDouble(cell.getStringCellValue().trim());
                } catch (NumberFormatException e) {
                    return null;
                }
            default:
                return null;
        }
    }
    
    /**
     * 获取单元格的Integer值
     */
    private Integer getCellIntegerValue(org.apache.poi.ss.usermodel.Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellType()) {
            case NUMERIC:
                return (int) cell.getNumericCellValue();
            case STRING:
                try {
                    return Integer.parseInt(cell.getStringCellValue().trim());
                } catch (NumberFormatException e) {
                    return null;
                }
            default:
                return null;
        }
    }

    /**
     * 根据文件类型创建Workbook
     */
    private Workbook createWorkbook(InputStream inputStream, String fileName) throws Exception {
        if (fileName != null && fileName.endsWith(".xlsx")) {
            return new XSSFWorkbook(inputStream);
        } else {
            return new HSSFWorkbook(inputStream);
        }
    }

    /**
     * 获取Excel文件的所有工作表名称
     * 
     * @param file Excel文件
     * @return 工作表名称列表
     */
    @Override
    public List<String> getSheetNames(MultipartFile file) {
        List<String> sheetNames = new ArrayList<>();
        
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = createWorkbook(inputStream, file.getOriginalFilename())) {
            int numberOfSheets = workbook.getNumberOfSheets();
            for (int i = 0; i < numberOfSheets; i++) {
                sheetNames.add(workbook.getSheetName(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return sheetNames;
    }

    /**
     * 执行非平行差改正计算
     */
    @Override
    public List<CmcNonparallelismCorrection> calculateNonparallelismCorrection(
            List<CmcNonparallelismCorrection> dataList) {
        List<CmcNonparallelismCorrection> resultList = new ArrayList<>();
        initEllipsoidParams(dataList.get(0).getCoordinateSystem());
        int level = dataList.get(0).getLevel();
        double distanceFromStart = 0;

        for (int i = 0; i < dataList.size()-1; i++) {
            CmcNonparallelismCorrection item1 = dataList.get(i);
            CmcNonparallelismCorrection item2 = dataList.get(i + 1);
            double dist1 = item1.getDistance();
            double dist2 = item2.getDistance();
            double heightdiff1 = item1.getHeightDifference();
            double heightdiff2 = item2.getHeightDifference();
            double truelen1 = item1.getScaleTrueLength();
            double truelen2 = item2.getScaleTrueLength();
            double Z1 = item1.getHeightH();
            double Z2 = item2.getHeightH();
            double band1 = item1.getZoneNo();
            double height = item1.getHeightH();

            double averageDistance = (dist1 + dist2) / 2/1000;
            double scale1 = heightdiff1 * truelen1;
            double scale2 = heightdiff2 * truelen2;
            double averageScale = (scale1 - scale2) / 2;
            double roundTripDifference = (scale1 + scale2) * 1000;
            double tolerance = level == 2 ? 4 * Math.sqrt(averageDistance)
                    : level == 3 ? 12 * Math.sqrt(averageDistance) : 20 * Math.sqrt(averageDistance);
            double precisionStatistics = roundTripDifference * roundTripDifference / 4 / averageDistance;
            double qualityScore = calculateQualityScore(roundTripDifference, tolerance);

            // 计算正常重力值
            double gamma1 = calculategamma(item1);
            double gamma2 = calculategamma(item2);
            double gammam = (gamma1 + gamma2) / 2 - 0.1543 * (Z1 + Z2) / 2;
            double pointCorrection = -(gamma2 - gamma1) * (Z1 + Z2) / 2 / gammam;
            double correctedHeightDifference = averageScale + pointCorrection;
            double elevation = height + correctedHeightDifference;

            double distanceFromStart1 = i == 0 ? 0 : dataList.get(i - 1).getDistanceFromStart();
            distanceFromStart += averageDistance;
            double distanceFromStart2 = distanceFromStart;

            double heightMiddleError1 = level == 2 ? Math.sqrt(distanceFromStart1)
                    : level == 3 ? Math.sqrt(distanceFromStart1) * 3 : Math.sqrt(distanceFromStart1) * 5;
            double heightMiddleError2 = level == 2 ? Math.sqrt(distanceFromStart2)
                    : level == 3 ? Math.sqrt(distanceFromStart2) * 3 : Math.sqrt(distanceFromStart2) * 5;
            item1.setAverageDistance(averageDistance);
            item1.setScaleCorrectedHeightDiff(heightMiddleError1);
            item2.setScaleCorrectedHeightDiff(heightMiddleError2);
            item1.setAverageScaleCorrectedHeightDiff(averageScale);
            item1.setRoundTripDifference(roundTripDifference);
            item1.setTolerance(tolerance);
            item1.setPrecisionStatistics(precisionStatistics);
            item1.setQualityScore(qualityScore);
            item1.setPointCorrection(pointCorrection);
            item1.setCorrectedHeightDifference(correctedHeightDifference);
            item1.setElevation(height);
            item2.setElevation(elevation);
            item1.setDistanceFromStart(distanceFromStart1);
            item2.setDistanceFromStart(distanceFromStart2);
            item1.setHeightMiddleError(heightMiddleError1);
            item2.setHeightMiddleError(heightMiddleError2);
            resultList.add(item1);
            resultList.add(item2);
            i++;
        }

        return resultList;
    }

    // 选择椭球体参数
    private void initEllipsoidParams(String coordinateSystem) {
        String F_str;
        if ("CGCS2000".equalsIgnoreCase(coordinateSystem) || "国家2000".equalsIgnoreCase(coordinateSystem)
                || "2000".equalsIgnoreCase(coordinateSystem)) {
            A = A_CGCS2000;
            F_str = F_CGCS2000;
        } else if ("1954".equalsIgnoreCase(coordinateSystem) || "北京54".equalsIgnoreCase(coordinateSystem)
                || "Beijing54".equalsIgnoreCase(coordinateSystem)
                || "54".equalsIgnoreCase(coordinateSystem)) {
            A = A_BJ54;
            F_str = F_BJ54;
        } else if ("1980".equalsIgnoreCase(coordinateSystem) || "西安80".equalsIgnoreCase(coordinateSystem)
                || "Xian80".equalsIgnoreCase(coordinateSystem)
                || "80".equalsIgnoreCase(coordinateSystem)) {
            A = A_XA80;
            F_str = F_XA80;
        } else {
            A = A_WGS84;
            F_str = F_WGS84;
        }
        BigDecimal one = BigDecimal.ONE;
        BigDecimal divisor = new BigDecimal(F_str);
        BigDecimal db_F = one.divide(divisor, 20, RoundingMode.HALF_UP);

        // 计算 2 * F
        BigDecimal two = new BigDecimal("2");
        BigDecimal twoF = two.multiply(db_F);

        // 计算 F * F
        BigDecimal F_squared = db_F.multiply(db_F);

        // 计算 e2 = 2*F - F*F
        BigDecimal e2 = twoF.subtract(F_squared);
        E2 = e2.doubleValue();
        F = db_F.doubleValue();
    }

    /**
     * 根据往返较差和限差计算质量评分
     * 
     * @param diff  往返较差
     * @param limit 限差
     * @return 质量评分（0-100分），或 -1 表示不合格
     */
    public static double calculateQualityScore(double diff, double limit) {
        double absDiff = Math.abs(diff);

        // 分档区间阈值
        double threshold1 = limit / 3.0; // 33.3%
        double threshold2 = limit / 2.0; // 50%
        double threshold3 = limit / 4.0 * 3.0; // 75%

        if (absDiff <= threshold1) {
            // 第一档：100分
            return 100.0;
        } else if (absDiff <= threshold2) {
            // 第二档：90~100分（线性插值）
            double scoreMin = 90.0;
            double scoreMax = 100.0;
            double valueMin = threshold1;
            double valueMax = threshold2;
            return scoreMin + (scoreMax - scoreMin) / (valueMax - valueMin) * (absDiff - valueMin);
        } else if (absDiff <= threshold3) {
            // 第三档：75~90分（线性插值）
            double scoreMin = 75.0;
            double scoreMax = 90.0;
            double valueMin = threshold2;
            double valueMax = threshold3;
            return scoreMin + (scoreMax - scoreMin) / (valueMax - valueMin) * (absDiff - valueMin);
        } else if (absDiff <= limit) {
            // 第四档：60~75分（线性插值）
            double scoreMin = 60.0;
            double scoreMax = 75.0;
            double valueMin = threshold3;
            double valueMax = limit;
            return scoreMin + (scoreMax - scoreMin) / (valueMax - valueMin) * (absDiff - valueMin);
        } else {
            // 超限：不合格
            return -1.0;
        }
    }


    private double calculategamma(CmcNonparallelismCorrection item) {
        double X = item.getCoordinateX();
        double Y = item.getCoordinateY();
        double band = item.getZoneNo();
        double bandwidth = item.getBandWidth();
        String latitudePosition = item.getLatitudePosition();
        String longitudePosition = item.getLongitudePosition();
        double projectionHeight = item.getProjectionHeight();

        double x = latitudePosition.equals("S") ? 10000000 - X : X;
        double y = Y > 1.0E+7 ? Y - (int) Math.floor(Y / 1.0E+6) * 1.0E+6 - 500000 : Y - 500000;

        double bf = calculateBf(x, projectionHeight);
        double tf = Math.tan(bf);
        double ep2 = 1 / Math.pow(1 - F, 2) - 1;
        double etaf2 = ep2 * Math.pow(Math.cos(bf), 2);
        double Vf = Math.sqrt(1 + etaf2);
        double c = (A + projectionHeight) / (1 - F);
        double n = y * Vf / c;

        // 最终纬度 B
        double B = calculateB(bf, tf, etaf2, n);

        // 计算L
        double L = calculateL(bf, tf, etaf2, n, longitudePosition, bandwidth, band);
        // 大地经度和大地纬度
        double longitude = convertDecimalDegrees(L);
        double latitude = convertDecimalDegrees(B);
        item.setGeodeticLongitude(longitude);
        item.setGeodeticLatitude(latitude);

        double gamma = 978030 * (1 + 0.005302 * Math.pow(Math.sin(B / 180 * Math.PI), 2) - 
        0.000007 * Math.pow(Math.sin(2 * B / 180 * Math.PI), 2));
        return gamma;
    }

    // 计算bf
    private double calculateBf(double x, double projectionHeight) {
        double e2 = E2;
        double e4 = E2 * E2;
        double e6 = e4 * E2;
        double e8 = e6 * E2;
        double e10 = e8 * E2;
        double d = A + projectionHeight;
        // 计算子午线弧长系数
        double a0 = (d - d * e2) * (1
                + 3.0 / 4.0 * e2
                + 45.0 / 64.0 * e4
                + 175.0 / 256.0 * e6
                + 11025.0 / 16384.0 * e8
                + 43659.0 / 65536.0 * e10);

        double a2 = (d - d * e2) * (3.0 / 4.0 * e2
                + 45.0 / 64.0 * e4
                + 175.0 / 256.0 * e6
                + 11025.0 / 16384.0 * e8
                + 43659.0 / 65536.0 * e10);

        double a4 = (d - d * e2) * (15.0 / 32.0 * e4
                + 175.0 / 384.0 * e6
                + 3675.0 / 8192.0 * e8
                + 14553.0 / 32768.0 * e10);

        double a6 = (d - d * e2) * (35.0 / 96.0 * e6
                + 735.0 / 2048.0 * e8
                + 14553.0 / 40960.0 * e10);

        double a8 = (d - d * e2) * (315.0 / 1024.0 * e8
                + 6237.0 / 20480.0 * e10);

        double b = x / a0;
        double sinB = Math.sin(b);
        double cosB = Math.cos(b);
        double f = -(a2 * sinB + a4 * Math.pow(sinB, 3) + a6 * Math.pow(sinB, 5) + a8 * Math.pow(sinB, 7)) * cosB;

        for (int i = 0; i < 9; i++) {
            b = (x - f) / a0;
            sinB = Math.sin(b);
            cosB = Math.cos(b);
            f = -(a2 * sinB + a4 * Math.pow(sinB, 3) + a6 * Math.pow(sinB, 5) + a8 * Math.pow(sinB, 7)) * cosB;
            i++;
        }
        return b;
    }

    //计算B
    private double calculateB(double bf, double tf, double etaf2, double n) {        double n2 = n * n;
        double n4 = n2 * n2;
        double n6 = n4 * n2;
        // 计算底点纬度对应的值
        double term1 = bf * 180 / Math.PI; // 转为度
        // 计算括号内的各项
        double bracket = 90 * n2
                - 7.5 * (5 + 3 * tf * tf + etaf2 - 9 * etaf2 * tf * tf) * n4
                + 0.25 * (61 + 90 * tf * tf + 45 * tf * tf * tf * tf) * n6;
        // 计算第二项
        double term2 = (1 + etaf2) / Math.PI * tf * bracket;
        // 最终纬度 B
        double B = term1 - term2;
        return B;
    }

    //计算l
    private double calculateL(double bf, double tf, double etaf2, double n, String longitudePosition,
            double bandwidth, double band) {
        double n2 = n * n;
        double n3 = n2 * n;
        double n5 = n3 * n2;
        double tf2 = tf * tf;
        double tf4 = tf2 * tf2;
        // 括号内计算
        double bracket2 = 180 * n
                - 30 * (1 + 2 * tf2 + etaf2) * n3
                + 1.5 * (5 + 28 * tf2 + 24 * tf4) * n5;
        double l = 1 / Math.PI / Math.cos(bf) * bracket2;

        double L = "W".equals(longitudePosition)
                ? (bandwidth == 6 ? (band * bandwidth - 3 - l) : (band * bandwidth - l))
                : (bandwidth == 6 ? (l + band * bandwidth - 3) : (l + band * bandwidth));
        return L;
    }
    
    private static double convertDecimalDegrees(double decimalDegrees) {

        final double PRECISION = 1.2e-12; // 修正值
        final double SEC_PRECISION = 1e-11; // 秒的修正值

        // 提取度
        double degrees = Math.floor(decimalDegrees + PRECISION);
        // 提取分
        double minutesRaw = 60 * (decimalDegrees - degrees);
        double minutes = Math.floor(minutesRaw + PRECISION) / 100;
        // 提取秒（高精度）
        double secondsRaw = (decimalDegrees * 60 - Math.floor(decimalDegrees * 60 + PRECISION)) * 60;
        double seconds = Math.floor((secondsRaw + SEC_PRECISION) * 1000000) / 10000000000.0;
        
        return degrees + minutes + seconds;
    }
}
