<?php

declare(strict_types=1);

/**
 * Variant-only deterministic observation grammar helpers (stems).
 */

function variantStemHasClippedPossessivePulse(string $text): bool
{
    return (bool) preg_match('/\b(?:His|Her|Their|The)\s+pulse\s+(?!is\s)\d+/i', $text);
}

function variantStemHasClippedPossessiveBp(string $text): bool
{
    return (bool) preg_match('/\b(?:His|Her|Their)\s+BP\s+\d+\s*\/\s*\d+/i', $text);
}

function variantStemHasClippedPossessiveBloodPressure(string $text): bool
{
    return (bool) preg_match('/\b(?:His|Her|Their)\s+blood\s+pressure\s+(?!is\s)\d+/i', $text);
}

function variantStemHasBareBpInPossessiveContext(string $text): bool
{
    if (!preg_match('/\b(?:His|Her|Their)\s+/i', $text)) {
        return false;
    }
    if (preg_match('/\b(?:His|Her|Their)\s+BP\s+is\s+\d/i', $text)
        || preg_match('/\b(?:His|Her|Their)\s+blood\s+pressure\s+is\s+\d/i', $text)
        || preg_match('/\bblood\s+pressure\s+is\s+\d/i', $text)
        || preg_match('/\bBP\s+is\s+\d/i', $text)) {
        return false;
    }

    return (bool) preg_match('/,\s*(?:blood pressure|BP)\s+\d/i', $text)
        || (bool) preg_match('/\band\s+BP\s+\d/i', $text)
        || (bool) preg_match('/\band\s+blood\s+pressure\s+(?!is\s)\d/i', $text);
}

function variantStemHasBarePulseInPossessiveContext(string $text): bool
{
    if (!preg_match('/\b(?:His|Her|Their)\s+/i', $text)) {
        return false;
    }
    if (preg_match('/\b(?:His|Her|Their)\s+pulse\s+is\s+\d/i', $text) || preg_match('/,\s*pulse\s+is\s+\d/i', $text)) {
        return false;
    }

    return (bool) preg_match('/,\s*pulse\s+(?!is\s)\d+\s+bpm/i', $text)
        || (bool) preg_match('/\band\s+pulse\s+(?!is\s)\d+\s+bpm/i', $text);
}

function variantStemHasClippedPossessiveRespiratoryRate(string $text): bool
{
    if (!preg_match('/\b(?:His|Her|Their)\s+/i', $text)) {
        return false;
    }

    return (bool) preg_match('/,\s*respiratory\s+rate\s+(?!is\s)\d+\s+breaths/i', $text)
        || (bool) preg_match('/\band\s+respiratory\s+rate\s+(?!is\s)\d+\s+breaths/i', $text);
}

function variantStemHasClippedObservationGrammar(string $text): bool
{
    if (trim($text) === '') {
        return false;
    }
    if (variantStemHasClippedPossessivePulse($text)) {
        return true;
    }
    if (variantStemHasClippedPossessiveBp($text)) {
        return true;
    }
    if (variantStemHasClippedPossessiveBloodPressure($text)) {
        return true;
    }
    if (variantStemHasBareBpInPossessiveContext($text)) {
        return true;
    }
    if (variantStemHasBarePulseInPossessiveContext($text)) {
        return true;
    }
    if (variantStemHasClippedPossessiveRespiratoryRate($text)) {
        return true;
    }

    $other = [
        '/\b(?:His|Her|Their)\s+(?:heart\s+rate|HR)\s+(?!is\s)\d+/i',
        '/\b(?:His|Her|Their)\s+(?:temperature|temp)\s+(?!is\s)\d+/i',
        '/\b(?:His|Her|Their)\s+(?:respiratory\s+rate|RR)\s+(?!is\s)\d+/i',
        '/\b(?:His|Her|Their)\s+oxygen\s+saturation\s+(?!is\s)\d+/i',
    ];
    foreach ($other as $pattern) {
        if (preg_match($pattern, $text)) {
            return true;
        }
    }

    return false;
}

function variantStemIsListStyleObservationPhrase(string $text): bool
{
    $t = trim($text);
    if ($t === '' || preg_match('/^(?:On examination[,:]?\s+)?(?:His|Her|Their)\s+/i', $t)) {
        return false;
    }
    if (variantStemHasClippedObservationGrammar($t)) {
        return false;
    }

    $segments = preg_split('/[.;]\s+/', $t) ?: [];
    foreach ($segments as $seg) {
        $seg = trim((string) $seg);
        if ($seg === '') {
            continue;
        }
        if (preg_match_all(
            '/(?:^|,\s*)(?:temperature|temp|pulse|heart rate|HR|BP|blood pressure|respiratory rate|RR|oxygen saturation)\s+[\d.\/%°]+/i',
            $seg,
            $matches
        ) && count($matches[0]) >= 2) {
            return true;
        }
    }

    return false;
}

/**
 * @return array{stem: string, changed: bool, needs_review: bool}
 */
function variantNormalizeStemObservationGrammar(string $stem): array
{
    $original = $stem;
    $s = $stem;

    if (trim($s) === '' || (variantStemIsListStyleObservationPhrase($s) && !variantStemHasClippedObservationGrammar($s))) {
        return [
            'stem' => $s,
            'changed' => false,
            'needs_review' => variantStemHasClippedObservationGrammar($s),
        ];
    }

    $hasPossessiveContext = (bool) preg_match('/\b(?:His|Her|Their|The)\s+pulse\s/i', $s)
        || (bool) preg_match('/\b(?:His|Her|Their)\s+/i', $s)
        || variantStemHasClippedObservationGrammar($s);

    if (!$hasPossessiveContext) {
        return [
            'stem' => $s,
            'changed' => false,
            'needs_review' => variantStemHasClippedObservationGrammar($s),
        ];
    }

    $s = (string) preg_replace(
        '/\b(His|Her|Their|The)\s+pulse\s+(\d+)/i',
        '$1 pulse is $2',
        $s
    );
    $s = (string) preg_replace(
        '/,\s*pulse\s+(?!is\s)(\d+)\s+bpm/i',
        ', pulse is $1 bpm',
        $s
    );
    $s = (string) preg_replace(
        '/\band\s+pulse\s+(?!is\s)(\d+)\s+bpm/i',
        'and pulse is $1 bpm',
        $s
    );
    $s = (string) preg_replace(
        '/\b(His|Her|Their)\s+BP\s+(\d+\s*\/\s*\d+)/i',
        '$1 blood pressure is $2',
        $s
    );
    $s = (string) preg_replace(
        '/\b(His|Her|Their)\s+blood\s+pressure\s+(\d+\s*\/\s*\d+)/i',
        '$1 blood pressure is $2',
        $s
    );
    $s = (string) preg_replace(
        '/,\s*BP\s+(\d+\s*\/\s*\d+)/i',
        ', blood pressure is $1',
        $s
    );
    $s = (string) preg_replace(
        '/,\s*blood\s+pressure\s+(?!is\s)(\d+\s*\/\s*\d+)/i',
        ', blood pressure is $1',
        $s
    );
    $s = (string) preg_replace(
        '/\band\s+BP\s+(\d+\s*\/\s*\d+)/i',
        'and blood pressure is $1',
        $s
    );
    $s = (string) preg_replace(
        '/\band\s+blood\s+pressure\s+(?!is\s)(\d+\s*\/\s*\d+)/i',
        'and blood pressure is $1',
        $s
    );
    $s = (string) preg_replace(
        '/,\s*respiratory\s+rate\s+(?!is\s)(\d+)\s+breaths/i',
        ', respiratory rate is $1 breaths',
        $s
    );
    $s = (string) preg_replace(
        '/\band\s+respiratory\s+rate\s+(?!is\s)(\d+)\s+breaths/i',
        'and respiratory rate is $1 breaths',
        $s
    );
    $s = (string) preg_replace(
        '/\b(His|Her|Their)\s+(heart\s+rate|HR)\s+(?!is\s)(\d+)/i',
        '$1 $2 is $3',
        $s
    );
    $s = (string) preg_replace(
        '/\b(His|Her|Their)\s+(temperature|temp)\s+(?!is\s)(\d+)/i',
        '$1 $2 is $3',
        $s
    );
    $s = (string) preg_replace(
        '/\b(His|Her|Their)\s+(respiratory\s+rate|RR)\s+(?!is\s)(\d+)/i',
        '$1 $2 is $3',
        $s
    );
    $s = (string) preg_replace(
        '/\b(His|Her|Their)\s+oxygen\s+saturation\s+(?!is\s)(\d+)/i',
        '$1 oxygen saturation is $2',
        $s
    );

    return [
        'stem' => $s,
        'changed' => $s !== $original,
        'needs_review' => variantStemHasClippedObservationGrammar($s),
    ];
}
