<?php

/**
 * Concise MLA/MS AKT style reference for the main SBA AI reviewer only.
 * Distilled from prompts/generator_prompt.php, prompts/sba_skill_definitions.php,
 * and validators/style_validator.php — not used for generation or variant/RISr.
 */

/**
 * Core MLA/MS AKT reviewer reference (all specialties and conditions).
 */
function buildSbaAiReviewerMlaStyleReferenceCore(): string
{
    $lines = [
        'MLA / MS AKT STYLE REFERENCE (local source of truth for style — overrides generic model habits)',
        '',
        '**General SBA assessment criteria (apply from the draft text, any specialty)**',
        '- **Clinical accuracy:** keyed answer correct and complete for the vignette and urgency painted in the stem.',
        '- **One-best-answer fairness:** exactly one defensible best option; no other option equally or more appropriate on the facts given.',
        '- **Homogeneous options:** all five in the **same decision family** for the lead-in (diagnoses, tests, management actions, interpretations, etc.).',
        '- **Skill alignment:** lead-in, options, and key match **Current skill** — not a different skill disguised in the same batch slot.',
        '- **Safe clinical sequencing:** avoid unsafe or delayed care presented as correct unless the item explicitly tests that error.',
        '- **Plausible distractors:** borderline-student mistakes; not obvious throwaways unless deliberately testing under-treatment.',
        '- **Year level:** metadata for curation/labelling only — **do not** judge an item too hard or too easy solely because the label is Year 4, Year 5, Year 6, or MLA Final Year.',
        '- **Justification:** ~3–4 sentences; why the key is best and why major distractors fail **for this vignette**; consistent with stem and key.',
        '',
        '**Item design**',
        '- One clear clinical decision; exactly **one best answer** among five homogeneous options.',
        '- **Similar option length**; avoid one line much longer than the others.',
        '- Stem: concise (**~40–80 words** where possible); **clinical narrative only** — the exam question belongs in the **lead-in** only.',
        '- Lead-in: clear, specific, aligned with **Current skill**; usually opens with **What** or **Which** and ends with **?**.',
        '',
        '**Wording (stem / options)**',
        '- Prefer **“has …”** / **“with …”** over **“history of …”** where meaning is unchanged.',
        '- Avoid **“observations show”**, **“vital signs show”**, **“His/Her observations are:”** — use direct measurements.',
        '- Where observations matter, use **MS AKT order**: temperature, pulse, blood pressure, respiratory rate, oxygen saturation (only numbers that change the answer).',
        '- UK English; **man/woman/boy/girl** (not male/female patient labels).',
        '- **Room-air saturations:** **“oxygen saturation is 98% breathing air”** is **correct MS AKT wording** — **never** flag it as a style problem. Flag or correct: **“on air”**, **“on room air”**, **“on breathing air”**, **“saturating 98% on room air”** → **“oxygen saturation is 98% breathing air”**.',
        '',
        '**Title & justification**',
        '- **Neutral clinical titles** for any condition — short labels that describe the clinical focus (e.g. “Acute asthma exacerbation”, “Suspected pulmonary embolism”, “Type 2 diabetes monitoring”).',
        '- **Never suggest** titles beginning **“Management of …”**, **“Initial management of …”**, **“Escalation in … management”**, or similar formulaic phrasing.',
        '- Avoid **“underlying issue”**, **“The vignette presents …”**, **“Option A is the best choice”**, **“directly addresses”** in justifications.',
        '',
        '**Score calibration (overall_readiness_percent and mla_compliance_percent)**',
        '- **85–95%:** strong tutor-review draft; only minor edits.',
        '- **75–84%:** good tutor-review draft; some revisions needed.',
        '- **65–74%:** useful but needs significant tutor editing.',
        '- **50–64%:** major issues affecting fairness, style, or clinical clarity.',
        '- **Below 50%:** unsafe, inaccurate, wrong skill, or poor one-best-answer quality.',
        '- **MLA compliance** should follow the same bands; do **not** score below **75%** for title length or trivial wording alone if clinical content is sound.',
        '',
        '**clinical_accuracy_rating**',
        '- **good:** key correct and complete; distractors fair.',
        '- **acceptable_with_minor_edits:** key clinically correct and complete; weak or obvious distractors or minor polish needed — **not** unsafe.',
        '- **borderline:** arguable key, incomplete key for the lead-in, or fairness concerns short of unsafe.',
        '- **unsafe_or_inaccurate:** wrong or incomplete **key**, **defensible distractor**, wrong skill, or **unsafe sequencing as correct** — **not** because a rule warning disagrees with the stem.',
        '',
        '**Rule-based warnings (secondary — see workflow step 3)**',
        '- Automated validator output only; **never** the primary basis for your review.',
        '- Compare **after** your independent reading; agree only when the draft supports the warning.',
        '- Record in **agreed_rule_warning_codes** / **possible_false_positive_rule_warning_codes**; put your own findings in **independent_concerns**.',
    ];

    return implode("\n", $lines);
}

/**
 * Calibration guidance: weak distractors vs unsafe key, related options, false positives, distractor examples.
 */
function buildSbaAiReviewerCalibrationAddendum(): string
{
    return implode("\n", [
        '',
        '**CALIBRATION — weak distractors vs unsafe key (read carefully)**',
        '- **Separate two problems:** (A) the **keyed answer** is wrong, incomplete, unsafe, or unfair vs the stem; (B) the **key is sound** but **distractors** are weak, obvious, or need polish.',
        '- For (B) only: **clinical_accuracy_rating** = **acceptable_with_minor_edits** (or **good** if minor); **overall_readiness_percent** usually **70–80%**; **one_best_answer_rating** = **good** or **borderline** — **not** **unsafe_or_inaccurate** and **not** readiness **below 65%**.',
        '- Reserve **unsafe_or_inaccurate**, readiness **below 50%**, and **high**-priority **safety_concerns** for (A): wrong/incomplete key, **defensible distractor**, wrong skill, or **dangerous sequencing keyed as correct**.',
        '- **safety_concerns** = problems with the **key** or genuine unfairness — **not** “distractors too easy” alone (those belong in **style_concerns** or **independent_concerns**).',
        '',
        '**Related but distinct options (Diagnosis / Interpretation)**',
        '- Options in the **same diagnostic family** are **valid** when each is a **distinct** diagnosis or interpretation on the stem facts.',
        '- **Acceptable related pairs:** NSTEMI vs STEMI; unstable angina vs stable angina; different ACS phenotypes when cues differ.',
        '- **Do not** flag “too similar” **high priority** only because labels are related — flag only if options are **semantically overlapping**, **ambiguous**, or **both could reasonably be correct** on the given stem.',
        '',
        '**Upper GI / peptic ulcer — Diagnosis (site specificity)**',
        '- If the stem supports **peptic ulcer bleed** or broad upper GI bleeding but does **not** localise **gastric** vs **duodenal** site, the key must **not** be **gastric ulcer** or **duodenal ulcer** — prefer **peptic ulcer bleed** or **peptic ulcer disease** as the lead-in requires.',
        '- **Respect Tutor comments** that instruct not to distinguish gastric from duodenal ulcer unless the stem supports that distinction.',
        '- Agree with validator codes **diagnosis.overspecific_gastric_ulcer_unsupported_by_stem** / **diagnosis.overspecific_duodenal_ulcer_unsupported_by_stem** when the keyed site-specific label is not supported by stem cues.',
        '',
        '**ABG interpretation — bicarbonate and compensation**',
        '- When **pH is low**, **PCO2 is high**, and **bicarbonate is above the reference range**, do **not** accept justification that bicarbonate is **within normal range** or that there is **no metabolic compensation**.',
        '- Correct reasoning: acknowledge **possible metabolic compensation** (raised bicarbonate) while still identifying **respiratory acidosis** if **pH remains low**.',
        '- Agree with **interpretation.abg_bicarbonate_compensation_denied** when the draft denies compensation despite elevated bicarbonate on the stem.',
        '- **COPD / chronic hypercapnia:** when the stem shows **COPD** with **raised PCO2**, **low pH** and **raised bicarbonate**, avoid simplistic keyed labels such as **“acute respiratory acidosis with metabolic compensation”**. Prefer **type 2 respiratory failure with respiratory acidosis** or **acute-on-chronic type 2 respiratory failure** when options and timing support it. Agree with **interpretation.abg_copd_type2_respiratory_failure_wording** when warranted.',
        '',
        '**Observations (MS AKT order)**',
        '- Prefer direct measurements — **not** “observations show/include/reveal”.',
        '- When most observations are given, order: **temperature, pulse, BP, respiratory rate, oxygen saturation**.',
        '- Prefer **“has [condition]”** over **“with known [condition]”** for current comorbidities.',
        '',
        '**Replacement distractor suggestions (mandatory quality rules)**',
        '- When distractor quality is a main issue, **recommended_changes** must include **2–4 example replacement concepts** in **suggested_change** — never only “replace weak distractors”.',
        '- Each suggestion must be **clearly wrong on this stem** but **clinically coherent** (a plausible borderline-student mistake).',
        '- **Do not** suggest options that **contradict core definitions** (e.g. unstable angina **with elevated troponin** — troponin elevation supports MI, not unstable angina).',
        '- **Do not** suggest **synonymous or overlapping** labels with the key (e.g. “acute MI due to ST elevation” **and** “STEMI” as separate options).',
        '- **Do not** suggest **obvious throwaway** or **nonsensical unsafe** lines unless the item explicitly tests that error — see forbidden lists per condition below.',
        '- Prefer **subtle sequencing / priority errors** over cartoonishly unsafe one-liners.',
        '',
        '**Initial septic shock — good replacement concepts:** start vasopressors before adequate fluid resuscitation; give IV fluids and delay antibiotics pending **senior** assessment; start IV antibiotics but defer fluid resuscitation; request critical care review before initiating immediate resuscitation; give repeated fluid boluses without reassessing response.',
        '**Initial septic shock — do NOT suggest as replacements:** oral antibiotics and observe; antipyretics and reassess; oxygen therapy only; monitor without treatment; **any culture-based antibiotic delay** (e.g. delay/wait/await/withhold antibiotics **until cultures** or **pending culture results**).',
        '**Refractory septic shock — good concepts:** further fluids without reassessing responsiveness; broaden antibiotics without treating refractory hypotension; delay source control despite ongoing shock; ward-level review instead of critical care escalation.',
        '**Massive PE with shock — good concepts:** anticoagulation alone without reperfusion/escalation; urgent CTPA before treatment despite haemodynamic instability; oxygen/analgesia without reperfusion planning; vasopressor support without treating the PE.',
        '**CAP prescribing — good concepts:** antibiotic contraindicated by allergy; broader-spectrum antibiotic not indicated for mild disease; antibiotic class duplication; non-first-line antibiotic without indication.',
        '',
        '**Validator false positives (always check draft text)**',
        '- If a warning **contradicts** the stem or key, put it in **possible_false_positive_rule_warning_codes** as `"code — brief reason"` and **do not** lower **clinical_accuracy_rating** or readiness because of it.',
        '- **SpO₂ 96% on breathing air** / **oxygen saturation is 96% breathing air** → acceptable wording; **not** a style error; reject hypoxia-related warnings when saturations are normal.',
        '- **uk.oxygen_saturation_is** (if present in rule warnings) → treat as **false positive** when the text is **“oxygen saturation is …% breathing air”**.',
        '- **prescribing_allergy_contradiction** → false positive when justification says **without/no penicillin allergy** with stem **no known drug allergies** — that is valid first-line reasoning.',
        '- **No IV fluids/antibiotics yet** → not refractory hypotension **after treatment**; initial fluids plus IV antibiotics can be a **complete** key.',
        '- Key clearly includes **IV fluids and broad-spectrum IV antibiotics** → do not agree that the key omits those components.',
        '- **options.high_similarity** → often false positive when options are **distinct** related diagnoses/interpretations on the stem (e.g. **NSTEMI vs STEMI** when troponin elevated and no ST elevation; **unstable angina with normal troponin** as distractor when troponin is elevated). Agree only if two options could **both reasonably be correct**.',
        '',
        '**Generic skill-framework checks (all conditions — apply from the draft)**',
        '- **Skill drift:** lead-in, options, and key must match **Selected skill** — flag investigation lines under Diagnosis, management under Interpretation, etc.',
        '- **Demographic consistency:** sex-specific risk factors (oral contraceptives, pregnancy, oestrogen) must match stated sex unless explicitly explained.',
        '- **Option homogeneity:** all five options in the same decision family; flag mixed diagnosis/investigation/management families.',
        '- **Overlapping correct answers:** broad class plus specific example in one set (e.g. “initiate anticoagulation” and “start LMWH”) — flag unless the item explicitly tests that distinction.',
        '- **Definitive investigation result:** when CTPA/troponin/ECG shows a definitive finding, key should be **definitive** (e.g. pulmonary embolism, NSTEMI) — not only “high probability” or “likely”.',
        '- **Diagnosis skill:** options are diagnoses only; omit unnecessary affect labels; avoid “no significant past medical history”.',
        '- **Investigation skill:** options are tests only; stem supports the keyed test (e.g. CTPA needs sufficient PE probability).',
        '- **Interpretation skill:** no treatment/next-step options; plausible distractors only.',
        '- **Management vs Emergency:** stable routine management vs immediate emergency actions — do not duplicate the same concept across skills in a batch.',
        '- **Weak vs obviously wrong distractors:** weak = polish; **obviously impossible** on the stem = fairness problem.',
    ]);
}

/**
 * Optional sepsis emergency addendum — only when condition or warnings are sepsis-related.
 */
function buildSbaAiReviewerSepsisEmergencyAddendum(): string
{
    return implode("\n", [
        '',
        '**Optional — sepsis Emergency Management (apply only when the vignette is sepsis/septic shock emergency care)**',
        '- Complete initial shock key when both present: IV/intravenous fluids + broad-spectrum IV/intravenous antibiotics (start/initiate/give/bundle wording).',
        '- Initial shock (no fluids/antibiotics yet, SpO₂ normal e.g. 96% on breathing air): fluids plus antibiotics can be a **complete** key — **not** hypoxic.',
        '- Persistent shock **after** adequate fluids and IV antibiotics in the stem: vasopressor or critical care escalation can be complete.',
        '- Hypoxic sepsis (SpO₂ clearly low, treatment not yet given): oxygen plus fluids plus IV antibiotics is usually complete.',
        '- Source control after resuscitation when obstruction/peritonism/collection is clear: urgent surgical/urological source control may be the key.',
        '- SpO₂ **below 92%**, or **below 94%** only with acute respiratory compromise — **not** 96% on breathing air.',
        '- Reject validator hypoxia/refractory warnings that conflict with these facts.',
        '- **Distractor suggestions for initial shock:** use **subtle sequencing errors** from the calibration list — **never** culture-delay, oral antibiotics/observe, oxygen-only, or monitor-without-treatment lines as your **suggested replacements**.',
    ]);
}

function sbaAiReviewerConditionLooksCap(string $conditionName): bool
{
    if (!function_exists('sbaGeneratorConditionLooksCommunityAcquiredPneumonia')) {
        $capPath = dirname(__DIR__) . '/sba_cap_prescribing_concepts.php';
        if (is_readable($capPath)) {
            require_once $capPath;
        }
    }

    return function_exists('sbaGeneratorConditionLooksCommunityAcquiredPneumonia')
        && sbaGeneratorConditionLooksCommunityAcquiredPneumonia($conditionName);
}

function buildSbaAiReviewerCapSkillAddendum(): string
{
    return implode("\n", [
        '',
        '**Optional — community-acquired pneumonia (CAP) mixed-skill batch**',
        '- **Emergency Management + hypoxia:** when SpO₂ is **below about 92%** on air, the keyed emergency answer should usually include **oxygen** with resuscitation — **not** fluids plus antibiotics alone while **oxygen therapy** is a distractor.',
        '- **Interpretation:** **severe CAP** requires physiological severity cues in the stem (SpO₂, RR, BP, confusion, urea, CURB-65/CRB-65) — do not agree that **severe infection** is supported when only CRP/WBC/CXR are given.',
        '- **Management vs Prescribing:** Management should use **broader strategies**; **five antibiotic drug names only** belongs under **Prescribing** — flag Management items that are essentially antibiotic selection.',
        '- **Monitoring:** options should be **follow-up monitoring** (SpO₂, RR, temperature, symptoms, treatment response) — not CT/blood cultures as routine monitoring.',
        '- **Prescribing allergy false positive:** **“without penicillin allergy”** / **“no penicillin/cillin allergy”** in the justification when the stem denies allergies is **valid reasoning** — not a contradiction.',
        '- **Emergency distractors:** avoid **oxygen-only** throwaways when the key is a combined bundle omitting oxygen in hypoxic CAP.',
    ]);
}

function sbaAiReviewerConditionLooksPe(string $conditionName): bool
{
    if (!function_exists('sbaGeneratorConditionLooksPulmonaryEmbolism')) {
        require_once __DIR__ . '/sba_pe_emergency_concepts.php';
    }

    return sbaGeneratorConditionLooksPulmonaryEmbolism(trim($conditionName));
}

function buildSbaAiReviewerPeEmergencyAddendum(): string
{
    return implode("\n", [
        '',
        '**Optional — PE Emergency Management (when vignette is pulmonary embolism emergency care)**',
        '- **Thrombolysis/reperfusion** requires **haemodynamic instability** in the stem (hypotension, shock, peri-arrest, obstructive collapse). **Hypoxia alone is not enough** — flag keys that thrombolyse stable hypoxic PE.',
        '- **Massive / shocked PE:** keyed answer should normally include **oxygen plus urgent thrombolysis/reperfusion** when SpO₂ is low — not IV fluids plus thrombolysis while “oxygen plus thrombolysis” sits as a distractor under a generic immediate-management lead-in.',
        '- **Thrombolysis contraindicated:** key **urgent alternative reperfusion escalation** — **not** thrombolysis; prefer generic critical-care escalation wording over forcing surgical-versus-catheter choice unless that is the explicit learning point.',
        '- **Stable PE:** anticoagulation may be appropriate when the stem is **not** shocked.',
        '- **Options:** homogeneous emergency actions — sceptical of CTPA-first, oral anticoagulant, antibiotic, or monitor-only distractors in massive PE.',
        '- Reject **sepsis-style** incomplete-key or antibiotic warnings that do not fit PE.',
    ]);
}

function sbaAiReviewerConditionLooksAcs(string $conditionName, string $presentation = ''): bool
{
    $blob = mb_strtolower(trim($conditionName . ' ' . $presentation));

    return (bool) preg_match(
        '/\b(?:acute\s+coronary\s+syndrome|acs|stemi|nstemi|myocardial\s+infarction|angina|chest\s+pain)\b/i',
        $blob
    );
}

function buildSbaAiReviewerAcsInterpretationAddendum(): string
{
    return implode("\n", [
        '',
        '**Optional — ACS Interpretation / Diagnosis (apply when the vignette is ACS or chest pain with ECG/troponin interpretation)**',
        '- **NSTEMI** and **STEMI** are **distinct** diagnoses — a valid set may include both as separate options when the stem differentiates them (e.g. no ST elevation + raised troponin → NSTEMI keyed, STEMI as distractor).',
        '- **Do not** use both **“STEMI”** and **“acute myocardial infarction due to ST-segment elevation”** (or near-synonyms) as **separate** options — they overlap semantically.',
        '- **Never suggest** replacement distractors such as **“unstable angina with elevated troponin”** — elevated troponin supports **myocardial infarction**, not unstable angina.',
        '- **Coherent ACS distractor pool** (pick 2–4 that fit **this stem**): NSTEMI; STEMI (if stem excludes ST elevation); **unstable angina** (only if troponin **normal** on the stem); stable angina; pericarditis; pulmonary embolism; aortic dissection; demand ischaemia; non-cardiac chest pain; normal variant early repolarisation — each must be **wrong but plausible** on the facts given.',
        '- Before suggesting a distractor, check it does **not** contradict troponin/ECG/ST-segment facts in the stem.',
    ]);
}

/**
 * @param list<array<string, mixed>> $styleWarnings
 */
function sbaAiReviewerStyleWarningsLookSepsisRelated(array $styleWarnings): bool
{
    foreach ($styleWarnings as $w) {
        if (!is_array($w)) {
            continue;
        }
        $code = (string) ($w['code'] ?? '');
        if ($code !== '' && preg_match('/\bsepsis\./i', $code)) {
            return true;
        }
    }

    return false;
}

function sbaAiReviewerConditionLooksSepsis(string $conditionName): bool
{
    return (bool) preg_match('/\b(?:sepsis|septic\s+shock|severe\s+sepsis)\b/i', trim($conditionName));
}

/**
 * Short skill-specific addendum for the AI reviewer (optional).
 */
function buildSbaAiReviewerSkillStyleAddendum(string $skill): string
{
    $skillPath = __DIR__ . '/sba_skill_definitions.php';
    if (!is_readable($skillPath)) {
        return '';
    }
    require_once $skillPath;

    $def = function_exists('sbaGeneratorGetSkillDefinition')
        ? sbaGeneratorGetSkillDefinition($skill)
        : null;
    if ($def === null) {
        return '';
    }

    $lines = [
        '',
        '**Current skill addendum (' . $def['label'] . ')**',
    ];

    $key = sbaGeneratorNormalizeSkillKey($skill);
    switch ($key) {
        case 'emergency_management':
            $lines[] = '- All five options: **immediate emergency management / escalation actions** for the condition shown — **not** investigations, imaging, or “wait for results” unless the lead-in explicitly asks for assessment only.';
            $lines[] = '- Avoid **mirror-fragment** distractors (isolated halves of a combined correct strategy).';
            $lines[] = '- Avoid **overlapping** options that differ only by urgency when that collapses one-best-answer fairness.';
            break;
        case 'interpretation':
            $lines[] = '- Lead-in and options: **interpretation of supplied data only** — do **not** drift into management or “next step” actions.';
            $lines[] = '- Options must not start with action verbs (start, prescribe, arrange, monitor, etc.).';
            $lines[] = '- **Related interpretations are allowed** when distinct on the stem (e.g. NSTEMI vs STEMI) — do not penalise same-family labels unless two options could both be correct.';
            $lines[] = '- **Distractor suggestions:** must be clinically coherent on the stem — never “unstable angina with elevated troponin”; never synonymous duplicates of the key (e.g. STEMI + “AMI with ST elevation”).';
            break;
        case 'diagnosis':
            $lines[] = '- Options: **diagnoses / disease entities** only — do not mix heterogeneous diagnosis types in one set.';
            $lines[] = '- **Related diagnoses are allowed** when clinically distinct on the stem (e.g. NSTEMI vs STEMI) — flag similarity only if semantically overlapping or ambiguous, not merely because labels are in the same family.';
            break;
        case 'investigation':
            $lines[] = '- Options: **investigations/tests only**; stem must not already contain the **result** of the test being chosen for an **initial** investigation ask.';
            break;
        case 'monitoring':
            $lines[] = '- Options: **review / measure / monitor** actions — lead-in must be **narrow** enough to favour one target.';
            break;
        case 'management':
            $lines[] = '- Options: **management steps** — not standalone investigations as distractors when the lead-in asks for management.';
            break;
        default:
            foreach (array_slice($def['rules'], 0, 3) as $rule) {
                $lines[] = '- ' . $rule;
            }
    }

    if (preg_match('/prescrib/i', $skill)) {
        $lines[] = '- **Prescribing:** options stay in the prescribing family; check allergy and dose/route consistency with the stem.';
    }

    return implode("\n", $lines);
}

/**
 * @param list<array<string, mixed>> $styleWarnings
 */
function buildSbaAiReviewerMlaStyleReferenceBlock(
    string $currentSkill = '',
    string $conditionName = '',
    array $styleWarnings = [],
    string $presentation = ''
): string {
    $block = buildSbaAiReviewerMlaStyleReferenceCore();
    $block .= buildSbaAiReviewerCalibrationAddendum();
    $skill = trim($currentSkill);
    if ($skill !== '') {
        $block .= buildSbaAiReviewerSkillStyleAddendum($skill);
    }
    if (sbaAiReviewerConditionLooksSepsis($conditionName)
        || sbaAiReviewerStyleWarningsLookSepsisRelated($styleWarnings)) {
        $block .= buildSbaAiReviewerSepsisEmergencyAddendum();
    }
    if (sbaAiReviewerConditionLooksAcs($conditionName, $presentation)) {
        $block .= buildSbaAiReviewerAcsInterpretationAddendum();
    }
    if (sbaAiReviewerConditionLooksPe($conditionName)) {
        $block .= buildSbaAiReviewerPeEmergencyAddendum();
    }
    if (sbaAiReviewerConditionLooksCap($conditionName)) {
        $block .= buildSbaAiReviewerCapSkillAddendum();
    }

    return $block;
}
