import type {Attendance, StaffMember} from '@/features/staff/types/staff';

/**
 * Domain rules for the staff module.
 *
 * These were inline in StaffGrid's useMemo. They are rules, not rendering:
 * "the roster is ordered by who is carrying the store" is a product decision
 * that a redesign of the grid must not be able to change by accident, and a
 * second surface (the leaderboard, an export, a mobile view) has to be able to
 * reuse it without copying a filter chain out of a component.
 *
 * Framework-free on purpose — no React, no Astryx — so it is unit-testable and
 * survives any change to how staff are displayed.
 */

export type StaffFilter = Attendance | 'all';

export interface StaffQuery {
  filter: StaffFilter;
  /** Free text, matched against name and role. */
  search: string;
}

/**
 * Filter, then rank.
 *
 * Best performers first: the roster's default question is "who is carrying
 * this store", not "who was added first". Ordering by score rather than name
 * is the single decision that makes the grid answer it without a sort control.
 */
export function selectStaff(
  staff: StaffMember[],
  {filter, search}: StaffQuery,
): StaffMember[] {
  const q = search.trim().toLowerCase();
  return staff
    .filter(
      (m) =>
        (filter === 'all' || m.attendance === filter) &&
        (q === '' ||
          m.name.toLowerCase().includes(q) ||
          m.role.toLowerCase().includes(q)),
    )
    .sort((a, b) => b.performanceScore - a.performanceScore);
}

/** How many people are in each attendance state. Drives the filter counts. */
export function countByAttendance(
  staff: StaffMember[],
): Record<StaffFilter, number> {
  const counts: Record<StaffFilter, number> = {
    all: staff.length,
    present: 0,
    late: 0,
    absent: 0,
    leave: 0,
  };
  for (const member of staff) counts[member.attendance] += 1;
  return counts;
}
