import { isNullishOrEmpty } from "./utils";

// Tri-estado para PATCH: unset | set(Some) | set(None)
export class PatchField<T> {
  private constructor(
    private readonly _isSet: boolean,
    private readonly _value?: T | null
  ) {}

  static unset<T>(): PatchField<T> {
    return new PatchField<T>(false);
  }

  static set<T>(value: T | null): PatchField<T> {
    return new PatchField<T>(true, value);
  }

  get isSet(): boolean {
    return this._isSet;
  }

  /** Devuelve el valor crudo (puede ser null) si isSet=true */
  get value(): T | null | undefined {
    return this._value;
  }

  /** Ejecuta una función solo si isSet=true */
  ifSet(fn: (v: T | null) => void): void {
    if (this._isSet) fn(this._value ?? null);
  }
}

export function toPatchField<T>(value: T | null | undefined): PatchField<T> {
  if (value === undefined) return PatchField.unset<T>();
  // "" => null
  if (isNullishOrEmpty(value)) return PatchField.set<T>(null);
  return PatchField.set<T>(value as T);
}
