import type { FdiToothId } from '@/types/treatment';
import type { VoiceApplySelection, VoiceExtractionResult } from '@/types/voice';

/** Which rows the review sheet renders at all — a row with nothing extracted is noise. */
export function voiceRowAvailability(result: VoiceExtractionResult) {
  return {
    treatmentType: result.treatmentType != null,
    teeth: result.teeth.length > 0,
    comment: Boolean(result.comment?.trim()),
    prosthesis: result.prosthesis != null,
    lab: result.labId != null,
    dueDate: result.dueDate != null,
  };
}

/**
 * Which rows start ticked.
 *
 * Everything available ticks itself, with two deliberate exceptions:
 *
 * - **lab, when the name only approximately matched.** Shipping a case to a lab is the one
 *   extracted value whose error leaves the building, so it always requires a deliberate tick.
 * - **prosthesis, when the map is incomplete.** A prosthesis detail with an untyped tooth
 *   cannot ship at all, so applying it would just move the failure to dispatch.
 */
export function initialVoiceSelection(result: VoiceExtractionResult): VoiceApplySelection {
  const available = voiceRowAvailability(result);
  return {
    treatmentType: available.treatmentType,
    teeth: available.teeth,
    comment: available.comment,
    prosthesis: available.prosthesis && result.prosthesis?.complete === true,
    lab: available.lab && result.labMatchExact,
    dueDate: available.dueDate,
  };
}

/** How many rows will actually be applied — drives the confirm button's label. */
export function countSelected(selection: VoiceApplySelection): number {
  return Object.values(selection).filter(Boolean).length;
}

/** Teeth that are part of a bridge, for the read-only chart's connection marks. */
export function connectedTeethFromResult(result: VoiceExtractionResult): Set<FdiToothId> {
  const connected = new Set<FdiToothId>();
  for (const group of result.toothSelectionGroups) {
    if (group.kind !== 'connected') continue;
    for (const tooth of group.teeth) connected.add(tooth);
  }
  return connected;
}

/**
 * Whether the sheet has anything worth showing.
 *
 * A recording that produced nothing usable should say so plainly rather than present an
 * empty form of checkboxes.
 */
export function hasAnythingToApply(result: VoiceExtractionResult): boolean {
  return Object.values(voiceRowAvailability(result)).some(Boolean);
}
