export type DrillPoint = { x: number; y: number; z: number; ppm: number };

const DEFAULT_EPS = 1e-6;

/**
 * MVP "kriging": inverse distance weighting (IDW) as in Module B spec.
 */
export function krigingInterpolation(
  points: DrillPoint[],
  targetX: number,
  targetY: number,
  targetZ: number,
  power = 2
): number {
  if (points.length === 0) {
    throw new Error('krigingInterpolation: no drill points');
  }
  let totalWeight = 0;
  let weightedPpm = 0;
  for (const point of points) {
    const dx = point.x - targetX;
    const dy = point.y - targetY;
    const dz = point.z - targetZ;
    let distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
    if (distance < DEFAULT_EPS) {
      return point.ppm;
    }
    const weight = 1 / Math.pow(distance, power);
    totalWeight += weight;
    weightedPpm += point.ppm * weight;
  }
  if (totalWeight < DEFAULT_EPS) {
    throw new Error('krigingInterpolation: zero total weight');
  }
  return weightedPpm / totalWeight;
}

/** Confidence 0–100: higher when nearest drill hole is close (within ~3 block lengths). */
export function confidenceFromNearestDrill(
  points: DrillPoint[],
  targetX: number,
  targetY: number,
  targetZ: number,
  blockSizeM: number
): number {
  let minD = Infinity;
  for (const p of points) {
    const d = Math.sqrt(
      Math.pow(p.x - targetX, 2) + Math.pow(p.y - targetY, 2) + Math.pow(p.z - targetZ, 2)
    );
    if (d < minD) minD = d;
  }
  const ref = Math.max(blockSizeM * 3, 1);
  const ratio = Math.min(1, ref / (minD + 1e-6));
  return Math.round(Math.min(100, ratio * 100));
}
