/// 工具函数模块
/// 提供数值计算、数组操作、查找交点等工具函数

///|
/// 查找两个数组的交点索引
/// 返回交点的索引数组(在交点之前的索引)
pub fn nearest_intersection_idx(
  a : Array[Double],
  b : Array[Double],
) -> Array[Int] {
  if a.length() != b.length() {
    []
  } else {
    let diff = Array::make(a.length(), 0.0)
    for i = 0; i < a.length(); i = i + 1 {
      diff[i] = a[i] - b[i]
    }
    let sign_changes = Array::make(0, 0)
    for i = 0; i < diff.length() - 1; i = i + 1 {
      let sign1 = if diff[i] >= 0.0 { 1 } else { -1 }
      let sign2 = if diff[i + 1] >= 0.0 { 1 } else { -1 }
      if sign1 != sign2 {
        sign_changes.push(i)
      }
    }
    sign_changes
  }
}

///|
/// 计算一维数组的一阶导数(使用中心差分)
/// f: 函数值数组
/// x: 坐标数组(可选,如果为None则使用均匀间距)
/// 返回导数数组
pub fn first_derivative(f : Array[Double], x : Array[Double]?) -> Array[Double] {
  let n = f.length()
  if n < 2 {
    []
  } else {
    let delta = match x {
      Some(x_arr) => {
        let d = Array::make(n - 1, 0.0)
        for i = 0; i < n - 1; i = i + 1 {
          d[i] = x_arr[i + 1] - x_arr[i]
        }
        d
      }
      None => Array::make(n - 1, 1.0) // 均匀间距为1
    }
    let deriv = Array::make(n, 0.0)

    // 左边界:前向差分
    if n > 1 {
      deriv[0] = (f[1] - f[0]) / delta[0]
    }

    // 中间点:中心差分
    for i = 1; i < n - 1; i = i + 1 {
      let h = (delta[i - 1] + delta[i]) / 2.0
      deriv[i] = (f[i + 1] - f[i - 1]) / (2.0 * h)
    }

    // 右边界:后向差分
    if n > 1 {
      deriv[n - 1] = (f[n - 1] - f[n - 2]) / delta[n - 2]
    }
    deriv
  }
}

///|
/// 计算一维数组的二阶导数
pub fn second_derivative(
  f : Array[Double],
  x : Array[Double]?,
) -> Array[Double] {
  let n = f.length()
  if n < 3 {
    Array::make(n, 0.0)
  } else {
    let delta = match x {
      Some(x_arr) => {
        let d = Array::make(n - 1, 0.0)
        for i = 0; i < n - 1; i = i + 1 {
          d[i] = x_arr[i + 1] - x_arr[i]
        }
        d
      }
      None => Array::make(n - 1, 1.0)
    }
    let deriv2 = Array::make(n, 0.0)

    // 左边界
    if n > 2 {
      let h = delta[0]
      deriv2[0] = (f[2] - 2.0 * f[1] + f[0]) / (h * h)
    }

    // 中间点
    for i = 1; i < n - 1; i = i + 1 {
      let h = (delta[i - 1] + delta[i]) / 2.0
      deriv2[i] = (f[i + 1] - 2.0 * f[i] + f[i - 1]) / (h * h)
    }

    // 右边界
    if n > 2 {
      let h = delta[n - 2]
      deriv2[n - 1] = (f[n - 1] - 2.0 * f[n - 2] + f[n - 3]) / (h * h)
    }
    deriv2
  }
}

///|
/// 移除 NaN 值(返回非 NaN 值的数组)
/// 注意:MoonBit 的 Double 可能不支持 NaN,这里提供接口以备将来扩展
pub fn remove_nans(arr : Array[Double]) -> Array[Double] {
  // MoonBit 目前 Double 不支持 NaN,这里返回原数组
  // 如果将来支持,可以添加 NaN 检查逻辑
  arr
}

///|
/// 判断两个值是否接近(类似 numpy.isclose)
pub fn is_close(a : Double, b : Double, rtol? : Double, atol? : Double) -> Bool {
  let rtol_val = match rtol {
    Some(v) => v
    None => 0.00001
  }
  let atol_val = match atol {
    Some(v) => v
    None => 0.00000001
  }
  let diff = if a > b { a - b } else { b - a }
  diff <= atol_val + rtol_val * (if a > b { a } else { b })
}

///|
/// 比较值是否大于或接近目标值(用于容差比较)
pub fn greater_or_close(
  a : Double,
  value : Double,
  rtol? : Double,
  atol? : Double,
) -> Bool {
  a > value || is_close(a, value, rtol?, atol?)
}

///|
/// 比较值是否小于或接近目标值
pub fn less_or_close(
  a : Double,
  value : Double,
  rtol? : Double,
  atol? : Double,
) -> Bool {
  a < value || is_close(a, value, rtol?, atol?)
}

///|
/// 查找数组中的峰值(局部最大值或最小值)
/// arr: 输入数组
/// maxima: true 查找最大值,false 查找最小值
/// 返回峰值索引数组
pub fn find_peaks(arr : Array[Double], maxima? : Bool) -> Array[Int] {
  let maxima_val = match maxima {
    Some(v) => v
    None => true
  }
  let peaks = Array::make(0, 0)
  let n = arr.length()
  if n < 3 {
    peaks
  } else {
    for i = 1; i < n - 1; i = i + 1 {
      let is_peak = if maxima_val {
        arr[i] > arr[i - 1] && arr[i] > arr[i + 1]
      } else {
        arr[i] < arr[i - 1] && arr[i] < arr[i + 1]
      }
      if is_peak {
        peaks.push(i)
      }
    }
    peaks
  }
}

///|
/// 查找数组中值在指定范围内的索引
pub fn find_indices_in_range(
  arr : Array[Double],
  min_val : Double,
  max_val : Double,
) -> Array[Int] {
  let indices = Array::make(0, 0)
  for i = 0; i < arr.length(); i = i + 1 {
    if arr[i] >= min_val && arr[i] <= max_val {
      indices.push(i)
    }
  }
  indices
}

///|
/// 线性插值
/// x: 要插值的 x 坐标
/// x_arr: 已知 x 坐标数组(必须单调递增)
/// y_arr: 对应的 y 值数组
/// 返回插值结果
pub fn linear_interpolate(
  x : Double,
  x_arr : Array[Double],
  y_arr : Array[Double],
) -> Double? {
  let n = x_arr.length()
  if n != y_arr.length() || n < 2 {
    None
  } else if x < x_arr[0] || x > x_arr[n - 1] {
    None // 超出范围
  } else {
    // 查找 x 所在的区间
    let mut i = 0
    while i < n - 1 && x_arr[i + 1] < x {
      i = i + 1
    }
    if i >= n - 1 {
      Some(y_arr[n - 1])
    } else {
      let x0 = x_arr[i]
      let x1 = x_arr[i + 1]
      let y0 = y_arr[i]
      let y1 = y_arr[i + 1]
      let dx = x1 - x0
      if dx == 0.0 {
        Some(y0)
      } else {
        let t = (x - x0) / dx
        Some(y0 + t * (y1 - y0))
      }
    }
  }
}

///|
/// 计算数组的统计信息
pub struct Stats {
  min : Double
  max : Double
  mean : Double
  sum : Double
}

///|
pub fn array_stats(arr : Array[Double]) -> Stats {
  if arr.length() == 0 {
    Stats::{ min: 0.0, max: 0.0, mean: 0.0, sum: 0.0 }
  } else {
    let mut min_val : Double = arr[0]
    let mut max_val : Double = arr[0]
    let mut sum_val : Double = 0.0
    for i = 0; i < arr.length(); i = i + 1 {
      let val : Double = arr[i]
      if val < min_val {
        min_val = val
      }
      if val > max_val {
        max_val = val
      }
      sum_val = sum_val + val
    }
    let mean_val : Double = sum_val / Double::from_int(arr.length())
    Stats::{ min: min_val, max: max_val, mean: mean_val, sum: sum_val }
  }
}

///|
/// 计算数组的梯度(一阶导数,均匀间距)
pub fn gradient(arr : Array[Double]) -> Array[Double] {
  first_derivative(arr, None)
}