import type { DataReIm } from '../types/index.ts';

export interface ReimPhaseCorrectionOptions {
  /**
   * Apply the phase correction from the last element of the array
   * @default false
   */
  reverse?: boolean;
  /**
   * Apply the phase correction directly in the input data
   * @default false
   */
  inPlace?: boolean;
}

/**
 * Phase correction filter.
 * @param data - complex spectrum
 * @param phi0 - angle in radians for zero order phase correction.
 * @param phi1 - angle in radians for first order phase correction.
 * @param options - options.
 * @returns a new object {re:[], im:[]} unless inPlace=true.
 */
export function reimPhaseCorrection(
  data: DataReIm,
  phi0 = 0,
  phi1 = 0,
  options: ReimPhaseCorrectionOptions = {},
): DataReIm {
  const { reverse = false, inPlace = false } = options;

  phi0 = Number.isFinite(phi0) ? phi0 : 0;
  phi1 = Number.isFinite(phi1) ? phi1 : 0;

  const length = data.re.length;

  // Decide target arrays
  const re = data.re;
  const im = data.im;

  const outRe = inPlace ? re : new Float64Array(length);
  const outIm = inPlace ? im : new Float64Array(length);

  let firstAngle = phi0;
  let delta = phi1 / length;

  if (reverse) {
    delta *= -1;
    firstAngle += phi1;
  }

  const alpha = 2 * Math.sin(delta / 2) ** 2;
  const beta = Math.sin(delta);

  let cosTheta = Math.cos(firstAngle);
  let sinTheta = Math.sin(firstAngle);

  for (let i = 0; i < length; i++) {
    const r = re[i];
    const ii = im[i];

    outRe[i] = r * cosTheta - ii * sinTheta;
    outIm[i] = ii * cosTheta + r * sinTheta;

    // Recursive angle update (stable incremental rotation)
    const newCosTheta = cosTheta - (alpha * cosTheta + beta * sinTheta);
    const newSinTheta = sinTheta - (alpha * sinTheta - beta * cosTheta);

    cosTheta = newCosTheta;
    sinTheta = newSinTheta;
  }

  return { re: outRe, im: outIm };
}
