import type { ExtractionCatalog } from './voice.providers';

/** Locale-specific guidance. Only the tooth vocabulary and numbering habits differ. */
const LOCALE_NOTES: Record<string, string> = {
  fa: [
    'The clinician is speaking Persian. A tooth number can be said as a whole number',
    '("بیست و شش" = 26), digit by digit ("دو شش" = 26), or with a lead-in',
    '("دندون شماره ۲۶"). Digits may arrive in Persian or Latin script — either way, copy',
    'the number into "fdi" as two Latin digits. The descriptive form is quadrant-relative:',
    '"شش بالا راست" = upper right six -> arch "upper", side "patient_right", position 6.',
  ].join(' '),
  nl: [
    'The clinician is speaking Dutch, where FDI is standard. "zesentwintig" and "26" are',
    'tooth 26. The descriptive form is "rechtsboven zes" = upper right six.',
  ].join(' '),
  en: [
    'The clinician is speaking English and uses FDI. "twenty-six", "two six" and "26" are',
    'all tooth 26. The descriptive form is "upper right six".',
  ].join(' '),
};

function codeList(entries: { code: string; label: string }[]): string {
  if (entries.length === 0) return '(none available)';
  return entries.map((e) => `- ${e.code} = ${e.label}`).join('\n');
}

export function buildExtractionPrompt(
  transcript: string,
  catalog: ExtractionCatalog,
  localeHint: string,
) {
  const localeNote = LOCALE_NOTES[localeHint] ?? LOCALE_NOTES.en;

  const system = [
    'You extract structured dental treatment data from a transcript of a clinician speaking.',
    'You are a parser, not an assistant: report only what was said.',
    '',
    'HARD RULES',
    '1. Never invent a code. treatmentType, prosthesisDefaultType and prosthesisOverrides[].type',
    '   must be codes from the lists below. labId must be an id from the lab list. If what you',
    '   heard is not in a list, use null.',
    '2. "side" is always the PATIENT\'s side. The patient\'s upper right is quadrant 1. Never',
    "   flip to the viewer's point of view.",
    '3. Never do calendar arithmetic. Report the deadline as it was said, using due.kind.',
    '   If no deadline was mentioned, use due.kind = "none".',
    '4. Copy the exact spoken words for each tooth into "spoken", so the clinician can see',
    '   what was heard.',
    '5. If you are unsure about a value, use null. A missing field is recoverable; a wrong',
    '   one is not.',
    '',
    'TOOTH NUMBERS',
    'A number the clinician says for a tooth IS that tooth\'s FDI code. Put it in "fdi" as',
    'two digits. FDI is built from the two digits:',
    "  first digit  = quadrant, from the PATIENT's own point of view —",
    '                 1 upper right, 2 upper left, 3 lower left, 4 lower right.',
    '                 (5-8 are those same four quadrants in primary/deciduous teeth.)',
    '  second digit = position from the midline — 1 central incisor ... 8 third molar.',
    'So 26 is the upper left first molar, and 47 is the lower right second molar.',
    '',
    '- Use "arch" + "side" + "position" only when the tooth is DESCRIBED rather than',
    '  numbered ("upper right six" -> arch "upper", side "patient_right", position 6).',
    '- A single digit is a position, never an FDI code. If a single digit is said with no',
    '  quadrant words at all, set "position" and leave "arch" and "side" null. Never pick a',
    '  quadrant that was not said.',
    '- If a number is given AND the quadrant is spelled out as well, still use "fdi".',
    '- Not every number is a tooth. Dates, counts and quantities ("two teeth", "the 26th")',
    '  are not teeth, and must never appear in the teeth list.',
    '',
    localeNote,
    '',
    'TREATMENT TYPE CODES',
    codeList(catalog.treatmentTypes),
    '',
    'PROSTHESIS TYPE CODES',
    codeList(catalog.prosthesisTypes),
    '',
    'LABS THIS CLINIC CAN SEND TO',
    catalog.labs.length > 0
      ? catalog.labs.map((l) => `- ${l.id} = ${l.name}`).join('\n')
      : '(none linked — labId must be null)',
    '',
    'OTHER FIELDS',
    '- connectedSpans: only for bridges or splinted units. Endpoints inclusive.',
    '- comment: clinical notes, in the language spoken. Omit the parts already captured as',
    '  treatment type, teeth or deadline.',
    '- labMatchExact: true only when the spoken name matched a lab name exactly.',
  ].join('\n');

  return [
    { role: 'system' as const, content: system },
    { role: 'user' as const, content: transcript },
  ];
}
