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. Tooth references are usually quadrant-relative:',
    '"شش بالا راست" = upper right six -> arch "upper", side "patient_right", position 6.',
    'Digits may appear in Persian or Latin script. Two-digit FDI notation ("یک چهار") does',
    'occur — use the "fdi" field only for that.',
    'A bare "دندون دو" carries no quadrant: report position 2 with arch and side null.',
  ].join(' '),
  nl: [
    'The clinician is speaking Dutch and uses FDI notation, which is standard in the',
    'Netherlands. "rechtsboven zes" = upper right six. A bare two-digit number is FDI.',
  ].join(' '),
  en: [
    'The clinician is speaking English. IMPORTANT: a bare two-digit number is ambiguous,',
    'because Universal numbering and FDI disagree ("tooth 14" is a different tooth in each).',
    'Set "fdi" ONLY when the speaker made the notation explicit (e.g. "FDI one four").',
    'Otherwise describe the tooth with arch/side/position, or leave it unresolved.',
  ].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. Never output an FDI tooth code unless the speaker used FDI notation. Prefer',
    '   arch + side + position.',
    '3. "side" is always the PATIENT\'s side. The patient\'s upper right is quadrant 1. Never',
    "   flip to the viewer's point of view.",
    '4. Never do calendar arithmetic. Report the deadline as it was said, using due.kind.',
    '   If no deadline was mentioned, use due.kind = "none".',
    '5. Copy the exact spoken words for each tooth into "spoken", so the clinician can see',
    '   what was heard.',
    '6. If you are unsure about a value, use null. A missing field is recoverable; a wrong',
    '   one is not.',
    '7. A tooth number spoken WITHOUT a quadrant ("دندون دو", "tooth two") does not identify',
    '   a tooth — four teeth carry that position. Still report it: set "position" and leave',
    '   "arch" and "side" null. Never pick a quadrant that was not said.',
    '',
    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 },
  ];
}
