package com.ruoyi.caltools.controller;

import com.ruoyi.caltools.model.FlowProps;
import com.ruoyi.caltools.model.GasProps;
import com.ruoyi.caltools.model.WaterDeepCalParams;
import com.ruoyi.caltools.model.WaterDeepCalResult;
import com.ruoyi.caltools.service.DetailService;
import com.ruoyi.caltools.service.GBT11062Service;
import com.ruoyi.caltools.service.ThermService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.controller.UnitConvert;
import org.apache.juli.logging.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.ruoyi.caltools.controller.GasController.Crit;

@RestController
@RequestMapping("/WaterDeepCalc")
public class WaterDeepCalController {

    private static final Double G = 9.81;           // 重力加速度
    private static final Double R = 8.314;          // 通用气体常数

    @Autowired
    private UnitConvert unitConvert=new UnitConvert();

    @PostMapping("/calculatedepth")
    public AjaxResult calculatedepth(@RequestBody FlowProps flowProps) {
        GasProps gasProps = new GasProps();
        //大气压力转换成Pa
        double tempPatm = unitConvert.ConvertUniter("pressure", flowProps.getdPatm(), flowProps.getdPatmUnit(), 0);
        //压力转换成Pa
        double tempPf = unitConvert.ConvertUniter("pressure", flowProps.getdPf(), flowProps.getdPfUnit(), 0);

        //压力转换成Pa
        double tempDP = unitConvert.ConvertUniter("pressure", flowProps.getdDp(), flowProps.getdDpUnit(), 0);
        //温度转换成K
        double tempTf = unitConvert.ConvertUniter("temperature", flowProps.getdTf(), flowProps.getdTfUnit(), 2);
        if (flowProps.getdPfType() == 0)  //0是表压
        {
            gasProps.dPf = tempPatm + tempPf;
            flowProps.setdPf(tempPatm + tempPf);
        } else {
            gasProps.dPf = tempPf;
            flowProps.setdPf(tempPf);
        }
        gasProps.dTf = tempTf;
        flowProps.setdDp(tempDP);
        flowProps.setdTf(tempTf);
        gasProps.dCbtj = flowProps.getdCbtj();
        switch (gasProps.dCbtj)
        {
            case 2:
                gasProps.setdPb(101325);
                gasProps.setdTb( 273.15);
                flowProps.setdPb_M(101325);
                flowProps.setdTb_M(273.15);
                break;
            case 1:

                gasProps.setdPb(101325);
                gasProps.setdTb( 288.15);
                flowProps.setdPb_M(101325);
                flowProps.setdTb_M(288.15);
                break;
            case 0:

                gasProps.setdPb(101325);
                gasProps.setdTb( 293.15);
                flowProps.setdPb_M(101325);
                flowProps.setdTb_M(293.15);
                break;
        }

        String[] stringArray = flowProps.getdngComponents().split("_");
        double[] doubleArray = new double[stringArray.length];        // 遍历字符串数组，将每个元素转换为 double 类型
        for (int i = 0; i < stringArray.length; i++) {
            try {
                doubleArray[i] = Double.parseDouble(stringArray[i]) / 100;
            } catch (NumberFormatException e) {
                // 处理转换异常
                System.err.println("无法将字符串 " + stringArray[i] + " 转换为 double 类型: " + e.getMessage());
            }
        }
        gasProps.adMixture = doubleArray;
        GasController.ngCalcVoid(flowProps, gasProps); //计算临界流函数所有参数都计算了
        WaterDeepCalParams request=new WaterDeepCalParams();
        request.setSurfacePressure(flowProps.getdPf());
        request.setSurfaceTemperature(flowProps.getdTf());
        request.setConstantLayerDepth(flowProps.getdVFlowMax());
        request.setMeasuredTime(flowProps.getdVFlowMin());
        request.setTemperatureGradient(flowProps.getdVFlowCon());
        request.setGasProps(gasProps);
        WaterDeepCalResult response = calculateCorrectedDepth(request);
        return  AjaxResult.success(response);
    }

    /**
     * 计算深度处的温度
     */
    private Double temperatureAtDepth(Double depth, Double surfaceTemp,
                                      Double gradient, Double constantLayerDepth) {
        if (depth <= constantLayerDepth) {
            return surfaceTemp;
        } else {
            return surfaceTemp + gradient * (depth - constantLayerDepth);
        }
    }
    /**
     * 改进的压力计算：使用密度积分
     */
    private Double pressureAtDepth(Double depth, Double surfacePressure,
                                   Double surfaceTemp, Double gradient,
                                   Double constantLayerDepth, GasProps gasProps) {
        if (depth <= 0) {
            return surfacePressure;
        }

        int segments = 100;  // 积分段数
        Double dz = depth / segments;
        Double currentPressure = surfacePressure;

        // 克隆GasProps以避免修改原始对象
        GasProps tempGasProps = cloneGasProps(gasProps);

        for (int i = 0; i < segments; i++) {
            Double currentDepth = i * dz + dz/2;  // 使用中点
            Double currentTemp = temperatureAtDepth(currentDepth, surfaceTemp,
                    gradient, constantLayerDepth);

            // 设置当前温度和压力
            tempGasProps.dTf = currentTemp;
            tempGasProps.dPf = currentPressure;

            // 更新气体参数
            Crit(tempGasProps, 0);

            // 使用实际密度计算压力增量
            Double density = tempGasProps.getdRhof();  // 使用计算得到的密度

            // 压力增量：dP = ρ * g * dz
            Double dP = density * G * dz;
            currentPressure += dP;

            // 防止压力异常
            if (currentPressure <= 0) {
                currentPressure = surfacePressure * 1.1;  // 给一个安全值
            }
        }

        return currentPressure;
    }

    /**
     * 计算给定深度的理论传播时间
     */
    private Double calculateTheoreticalTime(Double depth, WaterDeepCalParams request,WaterDeepCalResult response) {
        if (depth <= 0) return 0.0;

        int segments = Math.max(50, (int)(depth / 10));  // 根据深度调整分段数
        segments = Math.min(segments, 200);  // 不超过200段

        Double dz = depth / segments;
        Double totalTime = 0.0;

        // 克隆GasProps以避免修改原始对象
        GasProps tempGasProps = cloneGasProps(request.getGasProps());

        List<String> tempSegmentsData=new ArrayList<>();

        for (int i = 0; i < segments; i++) {
            Double currentDepth = i * dz + dz/2;  // 中点

            // 计算中点温度
            Double temp = temperatureAtDepth(currentDepth, request.getSurfaceTemperature(),
                    request.getTemperatureGradient(), request.getConstantLayerDepth());

            // 计算中点压力
//            Double pressure = pressureAtDepth(currentDepth, request.getSurfacePressure(),
//                    request.getSurfaceTemperature(), request.getTemperatureGradient(),
//                    request.getConstantLayerDepth(), tempGasProps);
          Double pressure = request.getSurfacePressure();

            // 设置气体参数
            tempGasProps.dTf = temp;
            tempGasProps.dPf = pressure;

            // 计算声速
            Crit(tempGasProps, 0);
            Double soundVelocity = tempGasProps.dSOS;
            // 检查声速有效性
            if (soundVelocity <= 0 || Double.isNaN(soundVelocity)) {
                soundVelocity = 300.0;  // 默认声速
            }

            totalTime += dz / soundVelocity;
            String tempStr= ( "总段数:"+segments+",段序号:"+ Integer.toString(i + 1)+",段长度:"+ FormatUtil.format(dz, Optional.of(2))+",该段声速:"+ FormatUtil.format(tempGasProps.dSOS,Optional.of(2))+",该段时间"+FormatUtil.format(dz/soundVelocity,Optional.of(2))+",该段温度:"+FormatUtil.format(temp-273.15,Optional.of(2))+",总深度:"+FormatUtil.format( currentDepth,Optional.of(2))+",总时间:"+FormatUtil.format(totalTime,Optional.of(2))+"\n");
            tempSegmentsData.add(tempStr);
//            System.out.printf(tempStr);
        }
        response.setDataSegment(tempSegmentsData);
        return 2 * totalTime;  // 往返时间
    }

    /**
     * 改进的迭代算法
     */
    public WaterDeepCalResult calculateCorrectedDepth(WaterDeepCalParams request) {
        WaterDeepCalResult response = new WaterDeepCalResult();

        try {
            // 验证输入参数
            if (request.getMeasuredTime() <= 0) {
                response.setStatus("ERROR: 测量时间必须大于0");
                return response;
            }

            if (request.getSurfacePressure() <= 0) {
                response.setStatus("ERROR: 表面压力必须大于0");
                return response;
            }

            // 计算井口声速
            Crit(request.getGasProps(), 0);
            Double surfaceSoundVelocity = request.getGasProps().dSOS;

            // 检查声速有效性
            if (surfaceSoundVelocity <= 0 || Double.isNaN(surfaceSoundVelocity)) {
                surfaceSoundVelocity = 300.0;  // 默认值
            }

            // 初始估计深度
            Double initialEstimate = surfaceSoundVelocity * request.getMeasuredTime() / 2;

            // 迭代求解
            Double lowerBound = initialEstimate * 0.5;  // 下界：初始估计的一半
            Double upperBound = initialEstimate * 2.0;  // 上界：初始估计的两倍

            // 如果初始估计不合理，调整边界
            if (initialEstimate < 0) {
                lowerBound = 0.0;
                upperBound = 10000.0;  // 假设最大深度10000米
            }

            Double currentDepth = initialEstimate;
            List<Double> iterationHistory = new ArrayList<>();
            Integer iterations = 0;

            // 二分法迭代
            while (iterations < request.getMaxIterations()) {
                iterationHistory.add(currentDepth);
                // 计算理论时间
                Double theoreticalTime = calculateTheoreticalTime(currentDepth, request,response);
                Double error = theoreticalTime - request.getMeasuredTime();

                // 检查收敛
                if (Math.abs(error) < request.getTolerance()) {
                    break;
                }

                // 更新边界
                if (error > 0) {
                    // 理论时间 > 测量时间，说明深度估计过大
                    upperBound = currentDepth;
                } else {
                    // 理论时间 < 测量时间，说明深度估计过小
                    lowerBound = currentDepth;
                }

                // 计算新的深度估计
                Double newDepth = (lowerBound + upperBound) / 2;

                // 检查是否收敛或变化很小
                if (Math.abs(newDepth - currentDepth) < request.getTolerance()) {
                    currentDepth = newDepth;
                    break;
                }

                currentDepth = newDepth;
                iterations++;

                // 安全检查
                if (upperBound - lowerBound < 0.001) {
                    break;
                }
            }

            // 计算修正因子
            Double correctionFactor = currentDepth / initialEstimate;

            // 设置响应
            response.setCorrectedDepth(currentDepth);
            response.setInitialEstimate(initialEstimate);
            response.setCorrectionFactor(correctionFactor);
            response.setIterations(iterations);
            response.setIterationHistory(iterationHistory);
            response.setInitialSOS(surfaceSoundVelocity);

            if (iterations < request.getMaxIterations()) {
                response.setStatus("CONVERGED");
            } else {
                response.setStatus("MAX_ITERATIONS_REACHED");
            }

        } catch (Exception e) {
            response.setStatus("ERROR: " + e.getMessage());
        }

        return response;
    }
    /**
     * 克隆GasProps对象
     */
    private GasProps cloneGasProps(GasProps original) {
        GasProps cloned = new GasProps();

        // 复制基本属性
        cloned.dPf = original.dPf;
        cloned.dTf = original.dTf;
        cloned.dPb = original.dPb;
        cloned.dTb = original.dTb;
        cloned.dMrx = original.dMrx;
        cloned.dCbtj = original.dCbtj;

        // 复制数组
        if (original.adMixture != null) {
            cloned.adMixture = original.adMixture.clone();
        }

        return cloned;
    }

}
