<?php

/**
 * Unit tests for CAP skill validators and allergy-contradiction refinement.
 * Usage: php tools/test_cap_skill_rules.php
 */

require dirname(__DIR__) . '/validators/style_validator.php';

$passed = 0;
$failed = 0;

function capTest(bool $ok, string $label): void
{
    global $passed, $failed;
    if ($ok) {
        echo 'PASS: ' . $label . PHP_EOL;
        ++$passed;
    } else {
        echo 'FAIL: ' . $label . PHP_EOL;
        ++$failed;
    }
}

function capWarnCodes(array $question): array
{
    $warnings = validateSbaStyle(array_merge([
        '_current_skill' => '',
        '_condition_name' => 'Community-acquired pneumonia',
        '_tutor_comments' => '',
        '_batch_prior_questions' => [],
    ], $question));
    $codes = [];
    foreach ($warnings as $w) {
        if (is_array($w) && !empty($w['code'])) {
            $codes[] = (string) $w['code'];
        }
    }

    return $codes;
}

// 1. Allergy — no false positive for negated allergy phrasing
$negatedJust = 'Amoxicillin is first-line for uncomplicated CAP without penicillin allergy.';
capTest(
    !sbaStyleBlobClaimsDrugAllergyForPrescribing($negatedJust),
    'allergy negation: without penicillin allergy'
);
capTest(
    !sbaStyleBlobClaimsDrugAllergyForPrescribing('There is no penicillin allergy so amoxicillin is appropriate.'),
    'allergy negation: no penicillin allergy'
);

// 2. Allergy — true positive for affirmative contradiction
$affirmJust = 'Amoxicillin is contraindicated due to penicillin allergy.';
capTest(
    sbaStyleBlobClaimsDrugAllergyForPrescribing($affirmJust),
    'allergy affirmation: contraindicated due to penicillin allergy'
);

$allergyQ = [
    '_current_skill' => 'Prescribing',
    'stem' => 'A 70 year old man has community-acquired pneumonia. He has no known drug allergies.',
    'lead_in' => 'What is the most appropriate antibiotic?',
    'option_a' => 'Amoxicillin',
    'option_b' => 'Doxycycline',
    'option_c' => 'Clarithromycin',
    'option_d' => 'Co-amoxiclav',
    'option_e' => 'Ciprofloxacin',
    'correct_answer_letter' => 'A',
    'correct_answer' => 'Amoxicillin',
    'justification' => $negatedJust,
];
capTest(
    !in_array('prescribing_allergy_contradiction', capWarnCodes($allergyQ), true),
    'prescribing_allergy_contradiction not flagged for without penicillin allergy'
);

$allergyQBad = $allergyQ;
$allergyQBad['justification'] = $affirmJust;
capTest(
    in_array('prescribing_allergy_contradiction', capWarnCodes($allergyQBad), true),
    'prescribing_allergy_contradiction flagged for active allergy claim'
);

// 3. CAP Emergency hypoxic oxygen omission
$emergQ = [
    '_current_skill' => 'Emergency Management',
    'stem' => 'A 72 year old woman has fever, confusion and breathlessness. Temperature 39.1°C, pulse 118/min, blood pressure 86/52 mmHg, respiratory rate 28/min and oxygen saturation 88% on breathing air. No treatment has been given.',
    'lead_in' => 'What is the most appropriate immediate management?',
    'option_a' => 'Start IV fluids and broad-spectrum IV antibiotics',
    'option_b' => 'Give oxygen therapy',
    'option_c' => 'Give oral antibiotics and observe',
    'option_d' => 'Monitor observations on the ward',
    'option_e' => 'Repeat chest X-ray before treatment',
    'correct_answer_letter' => 'A',
    'correct_answer' => 'Start IV fluids and broad-spectrum IV antibiotics',
    'justification' => 'Septic shock from pneumonia requires immediate resuscitation.',
];
capTest(
    in_array('cap.emergency_hypoxic_oxygen_unfair', capWarnCodes($emergQ), true),
    'cap.emergency_hypoxic_oxygen_unfair for hypoxic key omitting oxygen'
);

// 4. CAP Interpretation severity overclaim
$interpQ = [
    '_current_skill' => 'Interpretation',
    'stem' => 'A 65 year old man has cough and fever. CRP is 145 mg/L, WBC 15 × 10⁹/L and chest X-ray shows bilateral infiltrates. Observations are otherwise not documented.',
    'lead_in' => 'What is the best interpretation of these findings?',
    'option_a' => 'Severe infection likely due to pneumonia',
    'option_b' => 'Viral upper respiratory tract infection',
    'option_c' => 'Pulmonary embolism',
    'option_d' => 'Heart failure',
    'option_e' => 'Normal variant',
    'correct_answer_letter' => 'A',
    'correct_answer' => 'Severe infection likely due to pneumonia',
    'justification' => 'Raised inflammatory markers and infiltrates support severe pneumonia.',
];
capTest(
    in_array('cap.interpretation_severity_overclaim', capWarnCodes($interpQ), true),
    'cap.interpretation_severity_overclaim when only CRP/WBC/CXR'
);

// 5. CAP Management antibiotic-only drift
$mgmtQ = [
    '_current_skill' => 'Management',
    'stem' => 'A 58 year old woman has mild community-acquired pneumonia suitable for outpatient care. She has no penicillin allergy.',
    'lead_in' => 'What is the most appropriate management?',
    'option_a' => 'Amoxicillin',
    'option_b' => 'Doxycycline',
    'option_c' => 'Clarithromycin',
    'option_d' => 'Co-amoxiclav',
    'option_e' => 'Levofloxacin',
    'correct_answer_letter' => 'A',
    'correct_answer' => 'Amoxicillin',
    'justification' => 'Oral amoxicillin for mild CAP.',
];
capTest(
    in_array('cap.management_antibiotic_selection_drift', capWarnCodes($mgmtQ), true),
    'cap.management_antibiotic_selection_drift for antibiotic-only Management set'
);

// 6. CAP Monitoring diagnostic drift
$monQ = [
    '_current_skill' => 'Monitoring',
    'stem' => 'A 60 year old man is recovering from community-acquired pneumonia on oral amoxicillin at home.',
    'lead_in' => 'What is the most appropriate monitoring at follow-up?',
    'option_a' => 'Oxygen saturation and symptoms',
    'option_b' => 'CT chest scan',
    'option_c' => 'Blood cultures',
    'option_d' => 'Bronchoscopy',
    'option_e' => 'Temperature and respiratory rate',
    'correct_answer_letter' => 'A',
    'correct_answer' => 'Oxygen saturation and symptoms',
    'justification' => 'Monitor clinical recovery.',
];
capTest(
    in_array('cap.monitoring_diagnostic_investigation_drift', capWarnCodes($monQ), true),
    'cap.monitoring_diagnostic_investigation_drift for CT/cultures in monitoring set'
);

echo PHP_EOL . '========== SUMMARY ==========' . PHP_EOL;
echo "Passed: {$passed} Failed: {$failed}" . PHP_EOL;
exit($failed > 0 ? 1 : 0);
