// MoonGeo - 土力学/岩土工程库
// 主模块:包含核心计算功能

// ==================== 土压力计算 - 朗肯理论 ====================

///|
/// 朗肯主动土压力系数
/// K_a = tan²(45° - φ/2)
/// 参数: phi_deg - 内摩擦角 (度)
pub fn rankine_active_coefficient(phi_deg : Double) -> Double {
  let phi_rad = deg_to_rad(phi_deg)
  let tan_val = tan_approx(PI / 4.0 - phi_rad / 2.0)
  square(tan_val)
}

///|
/// 朗肯被动土压力系数
/// K_p = tan²(45° + φ/2)
pub fn rankine_passive_coefficient(phi_deg : Double) -> Double {
  let phi_rad = deg_to_rad(phi_deg)
  let tan_val = tan_approx(PI / 4.0 + phi_rad / 2.0)
  square(tan_val)
}

///|
/// 朗肯主动土压力 (无粘性土)
/// σ_a = K_a * γ * z
/// 参数: ka - 主动土压力系数, gamma - 土容重 (kN/m³), z - 深度 (m)
pub fn rankine_active_pressure(
  ka : Double,
  gamma : Double,
  z : Double,
) -> Double {
  ka * gamma * z
}

///|
/// 朗肯主动土压力 (粘性土)
/// σ_a = K_a * γ * z - 2c√K_a
/// 参数: ka, gamma, z, c - 粘聚力 (kPa)
pub fn rankine_active_pressure_cohesive(
  ka : Double,
  gamma : Double,
  z : Double,
  c : Double,
) -> Double {
  let term = ka * gamma * z - 2.0 * c * ka.sqrt()
  max(0.0, term)
}

///|
/// 朗肯被动土压力 (无粘性土)
/// σ_p = K_p * γ * z
pub fn rankine_passive_pressure(
  kp : Double,
  gamma : Double,
  z : Double,
) -> Double {
  kp * gamma * z
}

///|
/// 朗肯被动土压力 (粘性土)
/// σ_p = K_p * γ * z + 2c√K_p
pub fn rankine_passive_pressure_cohesive(
  kp : Double,
  gamma : Double,
  z : Double,
  c : Double,
) -> Double {
  kp * gamma * z + 2.0 * c * kp.sqrt()
}

///|
/// 朗肯主动土压力合力 (无粘性土,矩形分布)
/// E_a = 0.5 * K_a * γ * H²
/// 参数: ka, gamma, h - 墙高 (m)
pub fn rankine_active_force(ka : Double, gamma : Double, h : Double) -> Double {
  0.5 * ka * gamma * square(h)
}

///|
/// 朗肯主动土压力合力作用点 (距墙底)
/// y = H / 3
pub fn rankine_active_force_position(h : Double) -> Double {
  h / 3.0
}

///|
/// 朗肯主动土压力 (有超载)
/// σ_a = K_a * (γ * z + q)
/// 参数: ka, gamma, z, q - 超载 (kPa)
pub fn rankine_active_pressure_surcharge(
  ka : Double,
  gamma : Double,
  z : Double,
  q : Double,
) -> Double {
  ka * (gamma * z + q)
}

// ==================== 土压力计算 - 库仑理论 ====================

///|
/// 库仑主动土压力系数
/// K_a = cos²(φ - α) / [cos²α * cos(α + δ) * (1 + √(sin(φ+δ)sin(φ-β)/(cos(α+δ)cos(α-β)))²)]
/// 简化公式(α=0, β=0, δ=0时退化为朗肯)
/// 参数: phi_deg - 内摩擦角, alpha_deg - 墙背倾角, beta_deg - 填土坡角, delta_deg - 墙土摩擦角
pub fn coulomb_active_coefficient(
  phi_deg : Double,
  alpha_deg : Double,
  beta_deg : Double,
  delta_deg : Double,
) -> Double {
  let phi = deg_to_rad(phi_deg)
  let alpha = deg_to_rad(alpha_deg)
  let beta = deg_to_rad(beta_deg)
  let delta = deg_to_rad(delta_deg)
  let cos_phi_alpha = cos_approx(phi - alpha)
  let cos_alpha = cos_approx(alpha)
  let cos_alpha_delta = cos_approx(alpha + delta)
  let sin_phi_delta = sin_approx(phi + delta)
  let sin_phi_beta = sin_approx(phi - beta)
  let cos_alpha_beta = cos_approx(alpha - beta)
  let numerator = square(cos_phi_alpha)
  let denom1 = square(cos_alpha) * cos_alpha_delta
  let sqrt_term = (sin_phi_delta *
  sin_phi_beta /
  (cos_alpha_delta * cos_alpha_beta)).sqrt()
  let denom2 = square(1.0 + sqrt_term)
  if abs(denom1 * denom2) < EPSILON {
    return 0.0
  }
  numerator / (denom1 * denom2)
}

///|
/// 库仑主动土压力合力
/// E_a = 0.5 * K_a * γ * H²
pub fn coulomb_active_force(ka : Double, gamma : Double, h : Double) -> Double {
  0.5 * ka * gamma * square(h)
}

// ==================== 静止土压力 ====================

///|
/// 静止土压力
/// σ_0 = K_0 * γ * z
/// 参数: k0 - 静止土压力系数, gamma - 土容重, z - 深度
pub fn at_rest_pressure(k0 : Double, gamma : Double, z : Double) -> Double {
  k0 * gamma * z
}

///|
/// 静止土压力系数 (经验公式)
/// K_0 = 1 - sin(φ)
pub fn at_rest_coefficient(phi_deg : Double) -> Double {
  let phi_rad = deg_to_rad(phi_deg)
  1.0 - sin_approx(phi_rad)
}

// ==================== 地基承载力 ====================

///|
/// 太沙基承载力系数 N_c
/// N_c = (N_q - 1) * cot(φ) (当 φ > 0)
/// N_c = 5.7 (当 φ = 0)
pub fn terzaghi_nc(phi_deg : Double) -> Double {
  if abs(phi_deg) < EPSILON {
    return 5.7
  }
  let phi_rad = deg_to_rad(phi_deg)
  let nq = terzaghi_nq(phi_deg)
  (nq - 1.0) / tan_approx(phi_rad)
}

///|
/// 太沙基承载力系数 N_q
/// N_q = e^(πtanφ) * tan²(45° + φ/2)
pub fn terzaghi_nq(phi_deg : Double) -> Double {
  if abs(phi_deg) < EPSILON {
    return 1.0
  }
  let phi_rad = deg_to_rad(phi_deg)
  let exp_term = exp_approx(PI * tan_approx(phi_rad))
  let tan_term = square(tan_approx(PI / 4.0 + phi_rad / 2.0))
  exp_term * tan_term
}

///|
/// 太沙基承载力系数 N_γ
/// N_γ ≈ 2(N_q + 1)tan(φ) (简化)
pub fn terzaghi_ngamma(phi_deg : Double) -> Double {
  if abs(phi_deg) < EPSILON {
    return 0.0
  }
  let phi_rad = deg_to_rad(phi_deg)
  let nq = terzaghi_nq(phi_deg)
  2.0 * (nq + 1.0) * tan_approx(phi_rad)
}

///|
/// 太沙基极限承载力 (条形基础)
/// q_u = c*N_c + q*N_q + 0.5*γ*B*N_γ
/// 参数: c - 粘聚力 (kPa), q - 基础埋深处超载 (kPa), gamma - 土容重 (kN/m³), b - 基础宽度 (m), phi_deg - 内摩擦角
pub fn terzaghi_bearing_capacity(
  c : Double,
  q : Double,
  gamma : Double,
  b : Double,
  phi_deg : Double,
) -> Double {
  let nc = terzaghi_nc(phi_deg)
  let nq = terzaghi_nq(phi_deg)
  let ngamma = terzaghi_ngamma(phi_deg)
  c * nc + q * nq + 0.5 * gamma * b * ngamma
}

///|
/// 太沙基承载力 (考虑基础形状修正)
/// 矩形基础: q_u = c*N_c*s_c + q*N_q*s_q + 0.5*γ*B*N_γ*s_γ
/// 参数: sc, sq, sgamma - 形状系数
pub fn terzaghi_bearing_capacity_shape(
  c : Double,
  q : Double,
  gamma : Double,
  b : Double,
  phi_deg : Double,
  sc : Double,
  sq : Double,
  sgamma : Double,
) -> Double {
  let nc = terzaghi_nc(phi_deg)
  let nq = terzaghi_nq(phi_deg)
  let ngamma = terzaghi_ngamma(phi_deg)
  c * nc * sc + q * nq * sq + 0.5 * gamma * b * ngamma * sgamma
}

///|
/// 汉森承载力系数 N_c
pub fn hansen_nc(phi_deg : Double) -> Double {
  terzaghi_nc(phi_deg) // 与太沙基相同
}

///|
/// 汉森承载力系数 N_q
pub fn hansen_nq(phi_deg : Double) -> Double {
  terzaghi_nq(phi_deg) // 与太沙基相同
}

///|
/// 汉森承载力系数 N_γ
/// N_γ = 1.5(N_q - 1)tan(φ)
pub fn hansen_ngamma(phi_deg : Double) -> Double {
  if abs(phi_deg) < EPSILON {
    return 0.0
  }
  let phi_rad = deg_to_rad(phi_deg)
  let nq = terzaghi_nq(phi_deg)
  1.5 * (nq - 1.0) * tan_approx(phi_rad)
}

///|
/// 地基承载力设计值
/// f = q_u / F_s
/// 参数: qu - 极限承载力 (kPa), fs - 安全系数
pub fn bearing_capacity_design(qu : Double, fs : Double) -> Double {
  if fs <= 0.0 {
    return 0.0
  }
  qu / fs
}

// ==================== 沉降计算 ====================

///|
/// 分层总和法 - 单层压缩量
/// s_i = (a_v / (1 + e_0)) * σ_z * H_i
/// 参数: av - 压缩系数 (MPa⁻¹), e0 - 初始孔隙比, sigma_z - 附加应力 (kPa), hi - 层厚 (m)
/// 注意: 需要单位统一,σ_z(kPa) 转 MPa
pub fn settlement_layer(
  av : Double,
  e0 : Double,
  sigma_z : Double,
  hi : Double,
) -> Double {
  if abs(1.0 + e0) < EPSILON {
    return 0.0
  }
  // σ_z 从 kPa 转为 MPa
  let sigma_z_mpa = sigma_z / 1000.0
  av * sigma_z_mpa * hi / (1.0 + e0)
}

///|
/// 分层总和法 - 使用压缩模量
/// s_i = σ_z * H_i / E_s
/// 参数: es - 压缩模量 (MPa), sigma_z - 附加应力 (kPa), hi - 层厚 (m)
/// 注意: 需要单位统一,σ_z(kPa) 转 MPa
pub fn settlement_layer_es(
  es : Double,
  sigma_z : Double,
  hi : Double,
) -> Double {
  if es <= 0.0 {
    return 0.0
  }
  // σ_z 从 kPa 转为 MPa
  let sigma_z_mpa = sigma_z / 1000.0
  sigma_z_mpa * hi / es
}

///|
/// 总沉降量 (分层总和法)
/// s = Σ s_i
pub fn total_settlement(settlements : Array[Double]) -> Double {
  let mut sum = 0.0
  for i = 0; i < settlements.length(); i = i + 1 {
    sum = sum + settlements[i]
  }
  sum
}

///|
/// 基础中心点下附加应力 (均布荷载)
/// σ_z = p * I_c
/// 参数: p - 基底压力 (kPa), ic - 应力影响系数
pub fn additional_stress_center(p : Double, ic : Double) -> Double {
  p * ic
}

///|
/// 基础角点下附加应力系数 (Boussinesq解,简化)
/// I_c = 1 / (2π) * [z³/(r²+z²)^(5/2)]
/// 这里使用简化公式
pub fn stress_influence_coefficient_simplified(
  z : Double,
  b : Double,
) -> Double {
  if z <= 0.0 || b <= 0.0 {
    return 0.0
  }
  // 简化: I_c ≈ 0.25 (当 z/b = 1 时)
  // 更精确需要查表或数值计算
  let ratio = z / b
  if ratio <= 0.5 {
    0.9
  } else if ratio <= 1.0 {
    0.7
  } else if ratio <= 2.0 {
    0.5
  } else {
    0.3
  }
}

// ==================== 边坡稳定 ====================

///|
/// 瑞典圆弧法 - 安全系数
/// F_s = Σ(c*l + W*cos(α)*tan(φ)) / Σ(W*sin(α))
/// 参数: c - 粘聚力, phi_deg - 内摩擦角, slices - 条块数组 [(l, w, alpha_deg), ...]
pub fn swedish_circle_safety_factor(
  c : Double,
  phi_deg : Double,
  slices : Array[(Double, Double, Double)],
) -> Double {
  let phi_rad = deg_to_rad(phi_deg)
  let tan_phi = tan_approx(phi_rad)
  let mut numerator = 0.0
  let mut denominator = 0.0
  for i = 0; i < slices.length(); i = i + 1 {
    let (l, w, alpha_deg) = slices[i]
    let alpha_rad = deg_to_rad(alpha_deg)
    let cos_alpha = cos_approx(alpha_rad)
    let sin_alpha = sin_approx(alpha_rad)
    numerator = numerator + c * l + w * cos_alpha * tan_phi
    denominator = denominator + w * sin_alpha
  }
  if abs(denominator) < EPSILON {
    return 0.0
  }
  numerator / denominator
}

///|
/// 简化Bishop法 - 安全系数 (迭代求解,这里提供单次计算)
/// F_s = Σ[(c*b + W*tan(φ)) / m_α] / Σ(W*sin(α))
/// 其中 m_α = cos(α) + sin(α)*tan(φ)/F_s
pub fn bishop_safety_factor_iteration(
  c : Double,
  phi_deg : Double,
  slices : Array[(Double, Double, Double)],
  fs_initial : Double,
) -> Double {
  let phi_rad = deg_to_rad(phi_deg)
  let tan_phi = tan_approx(phi_rad)
  let mut numerator = 0.0
  let mut denominator = 0.0
  for i = 0; i < slices.length(); i = i + 1 {
    let (b, w, alpha_deg) = slices[i]
    let alpha_rad = deg_to_rad(alpha_deg)
    let cos_alpha = cos_approx(alpha_rad)
    let sin_alpha = sin_approx(alpha_rad)
    let m_alpha = cos_alpha + sin_alpha * tan_phi / fs_initial
    if abs(m_alpha) > EPSILON {
      numerator = numerator + (c * b + w * tan_phi) / m_alpha
    }
    denominator = denominator + w * sin_alpha
  }
  if abs(denominator) < EPSILON {
    return 0.0
  }
  numerator / denominator
}

// ==================== 渗透性 ====================

///|
/// 达西定律 - 渗流速度
/// v = k * i
/// 参数: k - 渗透系数 (m/s), i - 水力梯度
pub fn darcy_velocity(k : Double, i : Double) -> Double {
  k * i
}

///|
/// 达西定律 - 渗流量
/// Q = k * i * A
/// 参数: k - 渗透系数, i - 水力梯度, a - 过流面积 (m²)
pub fn darcy_flow_rate(k : Double, i : Double, a : Double) -> Double {
  k * i * a
}

///|
/// 水力梯度
/// i = Δh / L
/// 参数: delta_h - 水头差 (m), l - 渗流路径长度 (m)
pub fn hydraulic_gradient(delta_h : Double, l : Double) -> Double {
  if l <= 0.0 {
    return 0.0
  }
  delta_h / l
}

///|
/// 渗透系数 (经验公式,根据有效粒径)
/// k ≈ C * d₁₀²
/// 参数: d10 - 有效粒径 (mm), c - 经验系数
pub fn permeability_from_d10(d10 : Double, c : Double) -> Double {
  c * square(d10)
}

///|
/// 临界水力梯度 (流土)
/// i_cr = (γ_sat - γ_w) / γ_w = (G_s - 1) / (1 + e)
/// 参数: gs - 土粒比重, e - 孔隙比
pub fn critical_hydraulic_gradient(gs : Double, e : Double) -> Double {
  if abs(1.0 + e) < EPSILON {
    return 0.0
  }
  (gs - 1.0) / (1.0 + e)
}

///|
/// 判断是否发生流土
/// i > i_cr
pub fn is_piping(i : Double, i_cr : Double) -> Bool {
  i > i_cr
}

// ==================== 固结理论 ====================

///|
/// 固结度 (一维固结,时间因子法)
/// U = 1 - (8/π²) * Σ[1/(2n-1)² * exp(-(2n-1)²π²T_v/4)]
/// 简化: U ≈ 2√(T_v/π) (当 T_v < 0.2)
/// U ≈ 1 - (8/π²) * exp(-π²T_v/4) (当 T_v > 0.2)
pub fn consolidation_degree(tv : Double) -> Double {
  if tv < 0.2 {
    2.0 * (tv / PI).sqrt()
  } else {
    let exp_term = exp_approx(-square(PI) * tv / 4.0)
    1.0 - 8.0 / square(PI) * exp_term
  }
}

///|
/// 时间因子
/// T_v = C_v * t / H²
/// 参数: cv - 固结系数 (m²/s), t - 时间 (s), h - 排水距离 (m)
pub fn time_factor(cv : Double, t : Double, h : Double) -> Double {
  if h <= 0.0 {
    return 0.0
  }
  cv * t / square(h)
}

///|
/// 固结沉降 (最终沉降)
/// s_f = m_v * σ_z * H
/// 参数: mv - 体积压缩系数 (MPa⁻¹), sigma_z - 附加应力 (kPa), h - 层厚 (m)
/// 注意: 需要单位统一,σ_z(kPa) 转 MPa
pub fn consolidation_settlement_final(
  mv : Double,
  sigma_z : Double,
  h : Double,
) -> Double {
  // σ_z 从 kPa 转为 MPa
  let sigma_z_mpa = sigma_z / 1000.0
  mv * sigma_z_mpa * h
}

///|
/// 固结沉降 (任意时刻)
/// s_t = U * s_f
pub fn consolidation_settlement_time(u : Double, sf : Double) -> Double {
  u * sf
}

///|
/// 固结系数
/// C_v = k / (m_v * γ_w)
/// 参数: k - 渗透系数 (m/s), mv - 体积压缩系数 (MPa⁻¹), gamma_w - 水容重 (kN/m³)
pub fn consolidation_coefficient(
  k : Double,
  mv : Double,
  gamma_w : Double,
) -> Double {
  if mv <= 0.0 || gamma_w <= 0.0 {
    return 0.0
  }
  k / (mv * gamma_w * 0.001) // 单位转换
}

// ==================== 土的物理性质 ====================

///|
/// 孔隙比
/// e = V_v / V_s = (n / (1 - n))
/// 参数: n - 孔隙率
pub fn void_ratio(n : Double) -> Double {
  if n >= 1.0 || n <= 0.0 {
    return 0.0
  }
  n / (1.0 - n)
}

///|
/// 孔隙率
/// n = V_v / V = e / (1 + e)
pub fn porosity(e : Double) -> Double {
  if e < 0.0 {
    return 0.0
  }
  e / (1.0 + e)
}

///|
/// 饱和度
/// S_r = V_w / V_v * 100%
/// 参数: vw - 水的体积, vv - 孔隙体积
pub fn degree_of_saturation(vw : Double, vv : Double) -> Double {
  if vv <= 0.0 {
    return 0.0
  }
  clamp(vw / vv * 100.0, 0.0, 100.0)
}

///|
/// 干密度
/// ρ_d = ρ / (1 + w)
/// 参数: rho - 湿密度 (kg/m³), w - 含水量 (%)
pub fn dry_density(rho : Double, w : Double) -> Double {
  if w < 0.0 {
    return 0.0
  }
  rho / (1.0 + w / 100.0)
}

///|
/// 饱和密度
/// ρ_sat = (G_s + e) * ρ_w / (1 + e)
/// 参数: gs - 土粒比重, e - 孔隙比, rho_w - 水的密度
pub fn saturated_density(gs : Double, e : Double, rho_w : Double) -> Double {
  if abs(1.0 + e) < EPSILON {
    return 0.0
  }
  (gs + e) * rho_w / (1.0 + e)
}

///|
/// 浮容重
/// γ' = γ_sat - γ_w
pub fn submerged_unit_weight(gamma_sat : Double, gamma_w : Double) -> Double {
  gamma_sat - gamma_w
}

// ==================== 有效应力原理 ====================

///|
/// 有效应力
/// σ' = σ - u
/// 参数: sigma - 总应力 (kPa), u - 孔隙水压力 (kPa)
pub fn effective_stress(sigma : Double, u : Double) -> Double {
  sigma - u
}

///|
/// 总应力 (自重应力)
/// σ = γ * z
pub fn total_stress(gamma : Double, z : Double) -> Double {
  gamma * z
}

///|
/// 孔隙水压力 (静水压力)
/// u = γ_w * h_w
pub fn pore_water_pressure(gamma_w : Double, hw : Double) -> Double {
  gamma_w * hw
}

// ==================== 辅助函数 ====================

///|
/// 计算土压力合力作用点 (考虑超载)
pub fn earth_pressure_force_position_with_surcharge(
  h : Double,
  q : Double,
  gamma : Double,
) -> Double {
  if abs(gamma * h + q) < EPSILON {
    return h / 3.0
  }
  // 梯形分布合力作用点
  let top = q
  let bottom = gamma * h + q
  let y = h * (2.0 * top + bottom) / (3.0 * (top + bottom))
  y
}

///|
/// 判断土压力分布类型
/// 返回: "active", "passive", "at_rest"
pub fn earth_pressure_type(
  ka : Double,
  kp : Double,
  k0 : Double,
  k_actual : Double,
) -> String {
  if approx_equal(k_actual, ka, 0.01) {
    "active"
  } else if approx_equal(k_actual, kp, 0.01) {
    "passive"
  } else if approx_equal(k_actual, k0, 0.01) {
    "at_rest"
  } else {
    "unknown"
  }
}