import { Result, UndefinedOr } from "@repo/rdx-utils";
import { ResultCollection, RuleValidator } from "../helpers";

export interface IFieldCriteria {
  toJSON(): string;
  toString(): string;
  toObject(): Record<string, any>;
}

export class FieldCriteria extends StringValueObject implements IFieldCriteria {
  toJSON(): string {
    throw new Error("Method not implemented.");
  }
  toString(): string {
    throw new Error("Method not implemented.");
  }
  toObject(): Record<string, any> {
    throw new Error("Method not implemented.");
  }
  public static create(value: UndefinedOr<string>) {
    const validatedProps = FieldCriteria.validate(value);

    if (validatedProps.isFailure) {
      return Result.fail(validatedProps.error);
    }

    return Result.ok<FieldCriteria>(new FieldCriteria(String(value)));
  }

  protected static validate(value: UndefinedOr<string>) {
    if (RuleValidator.validate(RuleValidator.RULE_NOT_NULL_OR_UNDEFINED, value).isSuccess) {
      const stringOrError = RuleValidator.validate(RuleValidator.RULE_IS_TYPE_STRING, value);

      if (stringOrError.isFailure) {
        return stringOrError;
      }
    }

    const fieldString = String(value);

    const fieldsOrErrors = new ResultCollection();

    // biome-ignore lint/complexity/noForEach: <explanation>
    this.parseFieldString(fieldString).forEach((token: string[]) => {
      const fieldOrError = Field.create({
        field: token[2],
        operator: String(token[3]).toUpperCase(),
        value: token[4],
      });

      fieldsOrErrors.add(fieldOrError);
    });

    if (fieldsOrErrors.hasSomeFaultyResult()) {
      return fieldsOrErrors.getFirstFaultyResult() as Result<never, Error>;
    }

    return Result.ok(fieldString);
  }
}
