<?php

declare(strict_types=1);

/**
 * Shared, non-diagnostic vital-sign capture and validation helpers.
 * Clinical classifications are screening cues only; the treating clinician
 * remains responsible for interpretation and treatment decisions.
 */

function clinical_vitals_schema_ready(): bool
{
    try {
        foreach (['oxygen_saturation','height_cm','bmi','bp_arm','bp_position','bp_cuff_size','bp_device_type','bp_measurement_confirmed','bp_repeat_systolic','bp_repeat_diastolic','bp_repeat_after_minutes','bp_symptoms_reviewed','bp_symptoms','measurement_notes'] as $column) {
            if (!schema_column_exists(table('vital_signs'), $column)) return false;
        }
        return true;
    } catch (Throwable) {
        return false;
    }
}

function require_clinical_vitals_schema(): void
{
    if (clinical_vitals_schema_ready()) return;
    if (has_role('super_admin')) {
        header('Location: system_setup.php?tab=updates');
        exit;
    }
    http_response_code(503);
    exit('The redesigned vital-sign capture update is pending. Ask the Superuser to apply Version 0.5.9.8.24.');
}

function clinical_vitals_nullable_number(string $key, float $min, float $max, bool $integer = false): int|float|null
{
    $raw = trim((string)($_POST[$key] ?? ''));
    if ($raw === '') return null;
    if (!is_numeric($raw)) throw new RuntimeException('Enter a valid numeric value for ' . str_replace('_', ' ', $key) . '.');
    $value = (float)$raw;
    if ($value < $min || $value > $max) {
        throw new RuntimeException(ucwords(str_replace('_', ' ', $key)) . ' is outside the supported entry range. Recheck the device and enter the reading again.');
    }
    return $integer ? (int)round($value) : $value;
}

function clinical_vitals_clean_choice(string $key, array $allowed, ?string $default = null): ?string
{
    $value = trim((string)($_POST[$key] ?? ''));
    if ($value === '') return $default;
    if (!in_array($value, $allowed, true)) throw new RuntimeException('Select a valid ' . str_replace('_', ' ', $key) . '.');
    return $value;
}

function clinical_vitals_payload_from_post(int $patientAge): array
{
    $systolic = clinical_vitals_nullable_number('bp_systolic', 40, 300, true);
    $diastolic = clinical_vitals_nullable_number('bp_diastolic', 20, 200, true);
    $repeatSystolic = clinical_vitals_nullable_number('bp_repeat_systolic', 40, 300, true);
    $repeatDiastolic = clinical_vitals_nullable_number('bp_repeat_diastolic', 20, 200, true);

    if (($systolic === null) !== ($diastolic === null)) throw new RuntimeException('Enter both systolic and diastolic values for the first blood-pressure reading.');
    if (($repeatSystolic === null) !== ($repeatDiastolic === null)) throw new RuntimeException('Enter both systolic and diastolic values for the repeat blood-pressure reading.');
    if ($repeatSystolic !== null && $systolic === null) throw new RuntimeException('Enter the first blood-pressure reading before adding a repeat reading.');
    if ($systolic !== null && $diastolic !== null && $systolic <= $diastolic) throw new RuntimeException('Systolic blood pressure must be higher than diastolic blood pressure. Recheck the reading.');
    if ($repeatSystolic !== null && $repeatDiastolic !== null && $repeatSystolic <= $repeatDiastolic) throw new RuntimeException('Repeat systolic blood pressure must be higher than repeat diastolic blood pressure.');

    $bpEntered = $systolic !== null || $repeatSystolic !== null;
    $measurementConfirmed = isset($_POST['bp_measurement_confirmed']) ? 1 : 0;
    if ($bpEntered && !$measurementConfirmed) {
        throw new RuntimeException('Confirm the blood-pressure measurement setup before saving the reading.');
    }

    $weight = clinical_vitals_nullable_number('weight_kg', 1, 500);
    $height = clinical_vitals_nullable_number('height_cm', 30, 250);
    $bmi = ($weight !== null && $height !== null && $height > 0)
        ? round($weight / (($height / 100) ** 2), 2)
        : null;

    $symptoms = [];
    foreach ((array)($_POST['bp_symptoms'] ?? []) as $symptom) {
        $symptom = trim((string)$symptom);
        if (in_array($symptom, ['chest_pain','shortness_of_breath','back_pain','numbness_or_weakness','vision_change','difficulty_speaking','other'], true)) $symptoms[] = $symptom;
    }
    $symptoms = array_values(array_unique($symptoms));
    $symptomsReviewed = isset($_POST['bp_symptoms_reviewed']) ? 1 : 0;

    $effectiveSystolic = $repeatSystolic ?? $systolic;
    $effectiveDiastolic = $repeatDiastolic ?? $diastolic;
    $initialExtreme = $systolic !== null && ($systolic >= 180 || $diastolic >= 120);
    $repeatExtreme = $repeatSystolic !== null && ($repeatSystolic >= 180 || $repeatDiastolic >= 120);
    $extreme = $initialExtreme || $repeatExtreme;
    if ($extreme && !$symptomsReviewed) {
        throw new RuntimeException('A very high blood-pressure reading requires documented symptom review before it can be saved.');
    }
    $repeatAfterMinutes = $repeatSystolic !== null
        ? (clinical_vitals_nullable_number('bp_repeat_after_minutes', 1, 60, true) ?? 1)
        : null;

    $payload = [
        'blood_pressure_systolic' => $systolic,
        'blood_pressure_diastolic' => $diastolic,
        'pulse_rate' => clinical_vitals_nullable_number('pulse_rate', 20, 250, true),
        'temperature_c' => clinical_vitals_nullable_number('temperature_c', 30, 45),
        'respiratory_rate' => clinical_vitals_nullable_number('respiratory_rate', 5, 80, true),
        'oxygen_saturation' => clinical_vitals_nullable_number('oxygen_saturation', 40, 100),
        'weight_kg' => $weight,
        'height_cm' => $height,
        'bmi' => $bmi,
        'pain_score' => clinical_vitals_nullable_number('pain_score', 0, 10, true),
        'blood_glucose' => clinical_vitals_nullable_number('blood_glucose', 20, 700),
        'pregnancy_status' => trim((string)($_POST['pregnancy_status'] ?? '')) ?: null,
        'bp_arm' => $bpEntered ? clinical_vitals_clean_choice('bp_arm', ['left','right','other'], 'left') : null,
        'bp_position' => $bpEntered ? clinical_vitals_clean_choice('bp_position', ['seated','standing','supine','other'], 'seated') : null,
        'bp_cuff_size' => $bpEntered ? clinical_vitals_clean_choice('bp_cuff_size', ['pediatric','small_adult','adult','large_adult','extra_large','other','not_documented'], 'adult') : null,
        'bp_device_type' => $bpEntered ? clinical_vitals_clean_choice('bp_device_type', ['automatic','manual','other'], 'automatic') : null,
        'bp_measurement_confirmed' => $bpEntered ? $measurementConfirmed : 0,
        'bp_repeat_systolic' => $repeatSystolic,
        'bp_repeat_diastolic' => $repeatDiastolic,
        'bp_repeat_after_minutes' => $repeatAfterMinutes,
        'bp_symptoms_reviewed' => $extreme ? $symptomsReviewed : 0,
        'bp_symptoms' => $extreme && $symptoms ? implode(',', $symptoms) : null,
        'measurement_notes' => trim((string)($_POST['measurement_notes'] ?? '')) ?: null,
        'patient_age' => $patientAge,
    ];

    return $payload;
}

function clinical_vitals_effective_bp(array $vitals): array
{
    $repeatSys = isset($vitals['bp_repeat_systolic']) && $vitals['bp_repeat_systolic'] !== null ? (int)$vitals['bp_repeat_systolic'] : null;
    $repeatDia = isset($vitals['bp_repeat_diastolic']) && $vitals['bp_repeat_diastolic'] !== null ? (int)$vitals['bp_repeat_diastolic'] : null;
    $sys = $repeatSys ?? (isset($vitals['blood_pressure_systolic']) && $vitals['blood_pressure_systolic'] !== null ? (int)$vitals['blood_pressure_systolic'] : null);
    $dia = $repeatDia ?? (isset($vitals['blood_pressure_diastolic']) && $vitals['blood_pressure_diastolic'] !== null ? (int)$vitals['blood_pressure_diastolic'] : null);
    return [$sys, $dia, $repeatSys !== null && $repeatDia !== null];
}

function clinical_vitals_bp_screening(array $vitals, int $patientAge): array
{
    [$sys, $dia, $usedRepeat] = clinical_vitals_effective_bp($vitals);
    if ($sys === null || $dia === null) {
        return ['code'=>'missing','label'=>'Not recorded','message'=>'Record both systolic and diastolic values.','class'=>'neutral','used_repeat'=>false];
    }
    if ($sys >= 180 || $dia >= 120) {
        $hasSymptoms = trim((string)($vitals['bp_symptoms'] ?? '')) !== '';
        return [
            'code'=>$hasSymptoms?'emergency_symptoms':'urgent_review',
            'label'=>$hasSymptoms?'Emergency symptoms recorded':'Urgent review',
            'message'=>$hasSymptoms
                ? 'Stop routine workflow and follow the clinic emergency-response protocol.'
                : 'Repeat the reading after at least one minute and obtain immediate clinician review.',
            'class'=>'danger','used_repeat'=>$usedRepeat,
        ];
    }
    $initialSys = isset($vitals['blood_pressure_systolic']) && $vitals['blood_pressure_systolic'] !== null ? (int)$vitals['blood_pressure_systolic'] : null;
    $initialDia = isset($vitals['blood_pressure_diastolic']) && $vitals['blood_pressure_diastolic'] !== null ? (int)$vitals['blood_pressure_diastolic'] : null;
    if ($usedRepeat && $initialSys !== null && ($initialSys >= 180 || $initialDia >= 120)) {
        $hasSymptoms = trim((string)($vitals['bp_symptoms'] ?? '')) !== '';
        return [
            'code'=>$hasSymptoms?'emergency_symptoms':'severe_initial_repeated_lower',
            'label'=>$hasSymptoms?'Emergency symptoms recorded':'Very high initial reading — repeat lower',
            'message'=>$hasSymptoms
                ? 'Stop routine workflow and follow the clinic emergency-response protocol.'
                : 'Keep both readings documented and obtain immediate clinician review.',
            'class'=>'danger','used_repeat'=>true,
        ];
    }
    if ($patientAge <= 0) {
        return ['code'=>'age_unavailable','label'=>'Clinical review','message'=>'Patient age is unavailable; interpret the screening reading clinically.','class'=>'info','used_repeat'=>$usedRepeat];
    }
    if ($patientAge < 18) {
        return ['code'=>'pediatric_review','label'=>'Pediatric review','message'=>'Interpret this reading using age-, sex-, and height-appropriate clinical references.','class'=>'info','used_repeat'=>$usedRepeat];
    }
    if ($sys >= 140 || $dia >= 90) return ['code'=>'stage_2','label'=>'High reading — stage 2 range','message'=>'Repeat and have the treating clinician review before proceeding.','class'=>'warning','used_repeat'=>$usedRepeat];
    if ($sys >= 130 || $dia >= 80) return ['code'=>'stage_1','label'=>'High reading — stage 1 range','message'=>'Document and have the treating clinician review the screening result.','class'=>'warning','used_repeat'=>$usedRepeat];
    if ($sys >= 120 && $dia < 80) return ['code'=>'elevated','label'=>'Elevated reading','message'=>'Document the result and continue clinical review.','class'=>'info','used_repeat'=>$usedRepeat];
    return ['code'=>'routine','label'=>'Routine adult range','message'=>'Screening reading is below 120/80 mmHg.','class'=>'success','used_repeat'=>$usedRepeat];
}

function clinical_vitals_symptom_labels(?string $csv): array
{
    $map = [
        'chest_pain'=>'Chest pain',
        'shortness_of_breath'=>'Shortness of breath',
        'back_pain'=>'Back pain',
        'numbness_or_weakness'=>'Numbness or weakness',
        'vision_change'=>'Vision change',
        'difficulty_speaking'=>'Difficulty speaking',
        'other'=>'Other concerning symptom',
    ];
    $out = [];
    foreach (array_filter(array_map('trim', explode(',', (string)$csv))) as $code) if (isset($map[$code])) $out[] = $map[$code];
    return $out;
}
