import { isGroup, type Group, type Rule } from './types';

const NEGATIVE = new Set(['isNot', 'notMatches']);
const RELATIVE_DATE = new Set(['inLast', 'notInLast']);

export function ruleError(rule: Rule): string | null {
  if (rule.operator === 'between') {
    if (rule.value.trim() === '' || (rule.value2 ?? '').trim() === '') return 'Both bounds are required.';
    return null;
  }
  if (RELATIVE_DATE.has(rule.operator)) {
    const t = rule.value.trim();
    if (!/^\d+$/.test(t) || Number(t) <= 0) return 'Enter a whole number greater than zero.';
    return null;
  }
  if (rule.value.trim() === '') return 'A value is required.';
  return null;
}

export function groupHasErrors(group: Group): boolean {
  return group.children.some((c) => (isGroup(c) ? groupHasErrors(c) : ruleError(c) !== null));
}

export function topGroupAllNegative(group: Group): boolean {
  const rules = group.children.filter((c): c is Rule => !isGroup(c));
  if (rules.length === 0 || rules.length !== group.children.length) return false;
  return rules.every((r) => NEGATIVE.has(r.operator));
}

export function normalizeGroup(group: Group): Group {
  const children = group.children.map((c) => (isGroup(c) ? normalizeGroup(c) : c));
  return { match: children.length < 2 ? 'all' : group.match, children };
}
