import type { EndUserCondition, Field } from "./data-types";

function getFieldConditions(
  fieldId: number,
  endUserConditions: EndUserCondition[]
): EndUserCondition[] {
  return endUserConditions.filter((condition) => {
    return condition.child_fields.some((child) => child.id === fieldId);
  });
}

function getAppliedConditions(
  fieldConditions: EndUserCondition[],
  allConditions: EndUserCondition[],
  fields: Field[]
): EndUserCondition[] {
  return fieldConditions.filter((condition) => {
    const parentField = fields.find(
      (field) => field.id === condition.parent_field_id
    );

    if (!parentField) {
      return false;
    }

    const parentFieldConditions = getFieldConditions(
      parentField.id,
      allConditions
    );

    // the condition is applied if the parent field value matches the condition value
    // and if the parent field has no conditions or if the parent field conditions are met
    return (
      parentField.value === condition.value &&
      (parentFieldConditions.length === 0 ||
        getAppliedConditions(parentFieldConditions, allConditions, fields)
          .length > 0)
    );
  });
}

export function getVisibleFields(
  fields: Field[],
  endUserConditions: EndUserCondition[]
): Field[] {
  if (endUserConditions.length === 0) {
    return fields;
  }

  return fields.reduce((acc: Field[], field) => {
    const fieldConditions = getFieldConditions(field.id, endUserConditions);

    if (fieldConditions.length === 0) {
      return [...acc, field];
    }

    const appliedConditions = getAppliedConditions(
      fieldConditions,
      endUserConditions,
      fields
    );

    if (appliedConditions.length > 0) {
      return [
        ...acc,
        {
          ...field,
          required: appliedConditions.some((condition) =>
            condition.child_fields.some(
              (child) => child.id == field.id && child.is_required
            )
          ),
        },
      ];
    }

    return acc;
  }, []);
}
