export function toNumberSet(values: number[] | undefined | null) {
  const out = new Set<number>();
  if (!values) return out;
  for (const value of values) {
    if (Number.isFinite(value)) {
      out.add(value);
    }
  }
  return out;
}

export function mergeNumberSets(...sets: Set<number>[]) {
  const out = new Set<number>();
  for (const s of sets) {
    for (const v of s) {
      out.add(v);
    }
  }
  return out;
}

export function makeSetSignature(values: Set<number>) {
  return Array.from(values).sort((a, b) => a - b).join(',');
}

export function toSafeNumber(value: unknown): number | null {
  if (typeof value === 'number' && Number.isFinite(value)) return value;
  return null;
}

export function toIntMmsi(value: unknown): number | null {
  const n = toSafeNumber(value);
  if (n == null) return null;
  return Math.trunc(n);
}

export function isFiniteNumber(x: unknown): x is number {
  return typeof x === 'number' && Number.isFinite(x);
}

export const toNumberArray = (values: unknown): number[] => {
  if (values == null) return [];
  if (Array.isArray(values)) {
    return values as unknown as number[];
  }
  if (typeof values === 'number' && Number.isFinite(values)) {
    return [values];
  }
  if (typeof values === 'string') {
    const value = toSafeNumber(Number(values));
    return value == null ? [] : [value];
  }
  if (typeof values === 'object') {
    if (typeof (values as { [Symbol.iterator]?: unknown })?.[Symbol.iterator] === 'function') {
      try {
        return Array.from(values as Iterable<unknown>) as number[];
      } catch {
        return [];
      }
    }
  }
  return [];
};

export const makeUniqueSorted = (values: unknown) => {
  const maybeArray = toNumberArray(values);
  const normalized = Array.isArray(maybeArray) ? maybeArray : [];
  const unique = Array.from(new Set(normalized.filter((value) => Number.isFinite(value))));
  unique.sort((a, b) => a - b);
  return unique;
};

export const equalNumberArrays = (a: number[], b: number[]) => {
  if (a.length !== b.length) return false;
  for (let i = 0; i < a.length; i += 1) {
    if (a[i] !== b[i]) return false;
  }
  return true;
};
