<?php

declare(strict_types=1);

/**
 * Clinical record completion support.
 *
 * This layer does not replace the existing encounter closeout checks. It gives
 * the clinic a permanent, queryable review record showing what was present in
 * the signed chart, what was missing, and who finalized the record.
 */

function clinical_record_completion_schema_ready(PDO $pdo): bool
{
    return schema_table_exists(table('clinical_record_completion_reviews'))
        && schema_table_exists(table('procedure_note_templates'))
        && schema_table_exists(table('treatment_plan_signatures'))
        && schema_column_exists(table('clinical_encounters'), 'record_completion_status')
        && schema_column_exists(table('clinical_encounters'), 'record_completion_missing_json')
        && schema_column_exists(table('documents'), 'clinical_significance')
        && schema_column_exists(table('documents'), 'captured_at');
}

function clinical_record_completion_categories(): array
{
    return [
        'identity' => 'Patient identity and visit context',
        'intake' => 'Chief complaint, history, allergies, medications',
        'vitals' => 'Vital signs / medical risk review',
        'assessment' => 'Clinical examination and assessment',
        'diagnosis' => 'Diagnosis or no-pathology decision',
        'treatment' => 'Treatment/procedure notes or no-treatment outcome',
        'consent' => 'Procedure consent or exception',
        'imaging' => 'Imaging/photo note where relevant',
        'prescription' => 'Dental prescription decision and safety review',
        'follow_up' => 'Follow-up, recall, or no-follow-up decision',
        'billing' => 'Billing/no-payment handoff decision',
        'signature' => 'Dentist signature and license snapshot',
    ];
}

function clinical_record_completion_fetch_one(PDO $pdo, string $sql, array $args): ?array
{
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    $row = $stmt->fetch();
    return $row ?: null;
}

function clinical_record_completion_fetch_count(PDO $pdo, string $sql, array $args): int
{
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return (int) $stmt->fetchColumn();
}

function clinical_record_completion_evaluate(PDO $pdo, int $encounterId): array
{
    $encounter = clinical_record_completion_fetch_one(
        $pdo,
        'SELECT * FROM `' . table('clinical_encounters') . '` WHERE id=? LIMIT 1',
        [$encounterId]
    );
    if (!$encounter) {
        throw new RuntimeException('Clinical encounter not found for completion review.');
    }

    $patientId = (int) ($encounter['patient_id'] ?? 0);
    $queueId = (int) ($encounter['queue_entry_id'] ?? 0);
    $appointmentId = (int) ($encounter['appointment_id'] ?? 0);

    $intake = clinical_record_completion_fetch_one(
        $pdo,
        'SELECT * FROM `' . table('patient_intakes') . '` WHERE patient_id=? AND (queue_entry_id=? OR appointment_id=? OR (queue_entry_id IS NULL AND appointment_id IS NULL)) ORDER BY CASE WHEN queue_entry_id=? THEN 0 WHEN appointment_id=? THEN 1 ELSE 2 END,id DESC LIMIT 1',
        [$patientId, $queueId, $appointmentId, $queueId, $appointmentId]
    );
    $vitalsCount = clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('vital_signs') . '` WHERE encounter_id=?', [$encounterId]);
    $assessment = clinical_record_completion_fetch_one($pdo, 'SELECT * FROM `' . table('clinical_assessments') . '` WHERE encounter_id=? LIMIT 1', [$encounterId]);
    $diagnosisCount = clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('diagnoses') . '` WHERE encounter_id=?', [$encounterId]);
    $procedureCount = clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('procedures') . '` WHERE encounter_id=? AND status NOT IN ("cancelled")', [$encounterId]);
    $performedProcedureCount = clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('procedures') . '` WHERE encounter_id=? AND status IN ("completed","performed")', [$encounterId]);
    $consentCount = schema_table_exists(table('consent_forms')) ? clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('consent_forms') . '` WHERE patient_id=? AND (encounter_id=? OR id=?) AND status IN ("signed","active")', [$patientId, $encounterId, (int)($encounter['consent_form_id'] ?? 0)]) : 0;
    $imagingCount = schema_table_exists(table('documents')) ? clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('documents') . '` WHERE patient_id=? AND (encounter_id=? OR encounter_id IS NULL) AND category LIKE "%X-ray%"', [$patientId, $encounterId]) : 0;
    $prescriptionCount = clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('prescriptions') . '` WHERE encounter_id=? AND status<>"cancelled"', [$encounterId]);
    $followupCount = schema_table_exists(table('follow_ups')) ? clinical_record_completion_fetch_count($pdo, 'SELECT COUNT(*) FROM `' . table('follow_ups') . '` WHERE encounter_id=?', [$encounterId]) : 0;

    $completion = json_decode((string)($encounter['completion_check_json'] ?? ''), true);
    if (!is_array($completion)) $completion = [];

    $items = [];
    $add = static function(string $key, string $label, bool $passed, string $message = '', bool $required = true) use (&$items): void {
        $items[] = [
            'key' => $key,
            'label' => $label,
            'passed' => $passed,
            'required' => $required,
            'message' => $message,
        ];
    };

    $add('identity', 'Patient identity and encounter context', $patientId > 0 && ((int)$encounterId > 0), 'Patient and encounter must be linked.');
    $add('chief_complaint', 'Chief complaint', trim((string)($encounter['chief_complaint'] ?? '')) !== '' || trim((string)($intake['chief_complaint'] ?? '')) !== '', 'Record why the patient came in.');
    $add('history_present_condition', 'History of present condition', trim((string)($encounter['history_present_condition'] ?? '')) !== '' || trim((string)($intake['history_present_condition'] ?? '')) !== '', 'Record current history or relevant negatives.');
    $add('allergy_medication_review', 'Dental allergy and medicine review', !empty($completion['intake']) || ((int)($intake['allergies_confirmed'] ?? 0) === 1 && (int)($intake['medications_confirmed'] ?? 0) === 1), 'Confirm allergies and medicines that may affect dental treatment or dental prescribing.');
    $add('vitals_review', 'Vital-sign / medical-risk review', !empty($completion['vitals_review']) || $vitalsCount > 0, 'Record vitals or explicitly acknowledge review.');
    $add('assessment', 'Clinical examination / assessment', trim((string)($encounter['examination'] ?? '')) !== '' || (bool)$assessment, 'Record examination findings.');
    $add('diagnosis', 'Diagnosis or no-pathology decision', $diagnosisCount > 0 || trim((string)($encounter['diagnosis'] ?? '')) !== '' || in_array((string)($encounter['clinical_disposition'] ?? ''), ['no_treatment_required','observation','examination_only'], true), 'Record diagnosis, observation, or no-treatment outcome.');
    $add('treatment_record', 'Treatment/procedure record or valid no-treatment outcome', $procedureCount > 0 || in_array((string)($encounter['clinical_disposition'] ?? ''), ['no_treatment_required','observation','examination_only','referral','treatment_advised_declined','treatment_deferred'], true), 'Record performed treatment or a valid no-treatment/deferred/referral outcome.');
    $requiresConsent = $performedProcedureCount > 0 || !empty($completion['consent_required']);
    $add('consent', 'Consent or documented exception', !$requiresConsent || $consentCount > 0 || !empty($encounter['consent_exception_reason']), 'Signed consent or emergency exception is required for treatment.', $requiresConsent);
    $requiresImaging = str_contains(strtolower((string)($encounter['clinical_disposition'] ?? '')), 'imaging') || str_contains(strtolower((string)($encounter['procedure_done'] ?? '')), 'x-ray');
    $add('imaging', 'Imaging/photo note when used', !$requiresImaging || $imagingCount > 0 || trim((string)($encounter['examination'] ?? '')) !== '', 'Attach or describe the imaging used for diagnosis/treatment.', $requiresImaging);
    $prescriptionDecision = (string)($completion['prescription_decision'] ?? '');
    $add('prescription', 'Prescription decision', $prescriptionDecision !== '' || $prescriptionCount > 0 || trim((string)($encounter['prescription'] ?? '')) !== '', 'Record issued prescription or mark not required.');
    $add('follow_up', 'Follow-up / recall decision', !empty($completion['follow_up']) || $followupCount > 0 || in_array((string)($encounter['disposition'] ?? ''), ['no_follow_up','follow_up_planned'], true), 'Record follow-up plan or no-follow-up decision.');
    $add('billing', 'Billing/no-payment handoff', !empty($completion['billing_review']) || in_array((string)($encounter['completion_destination'] ?? ''), ['cashier','no_payment'], true), 'Confirm cashier handoff or authorized no-payment discharge.');
    $add('signature', 'Signed dentist snapshot', trim((string)($encounter['signed_by_name'] ?? '')) !== '' && trim((string)($encounter['signed_license_number'] ?? '')) !== '' && trim((string)($encounter['finalized_hash'] ?? '')) !== '', 'Finalized records must include signer name, license, and record hash.');

    $missing = array_values(array_filter($items, static fn(array $item): bool => !empty($item['required']) && empty($item['passed'])));
    return [
        'encounter_id' => $encounterId,
        'patient_id' => $patientId,
        'status' => $missing ? 'needs_review' : 'complete',
        'missing_count' => count($missing),
        'items' => $items,
        'missing' => $missing,
        'counts' => [
            'vitals' => $vitalsCount,
            'diagnoses' => $diagnosisCount,
            'procedures' => $procedureCount,
            'performed_procedures' => $performedProcedureCount,
            'consents' => $consentCount,
            'imaging' => $imagingCount,
            'prescriptions' => $prescriptionCount,
            'followups' => $followupCount,
        ],
        'checked_at' => date('c'),
    ];
}

function clinical_record_completion_store(PDO $pdo, int $encounterId, int $reviewerUserId = 0): array
{
    if (!clinical_record_completion_schema_ready($pdo)) {
        return ['status' => 'schema_missing', 'missing' => [], 'items' => []];
    }
    $review = clinical_record_completion_evaluate($pdo, $encounterId);
    $missingJson = json_encode($review['missing'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $itemsJson = json_encode($review['items'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $status = (string)$review['status'];

    $pdo->prepare('UPDATE `' . table('clinical_encounters') . '` SET record_completion_status=?,record_completion_checked_at=NOW(),record_completion_missing_json=?,updated_at=NOW() WHERE id=?')
        ->execute([$status, $missingJson ?: '[]', $encounterId]);

    $hash = hash('sha256', (string)json_encode($review, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
    $stmt = $pdo->prepare('INSERT INTO `' . table('clinical_record_completion_reviews') . '` (encounter_id,patient_id,review_status,missing_count,missing_json,checklist_json,review_hash,reviewed_by,reviewed_at,created_at) VALUES (?,?,?,?,?,?,?,?,NOW(),NOW())');
    $stmt->execute([
        $encounterId,
        (int)$review['patient_id'],
        $status,
        (int)$review['missing_count'],
        $missingJson ?: '[]',
        $itemsJson ?: '[]',
        $hash,
        $reviewerUserId ?: ((int)(current_user()['id'] ?? 0) ?: null),
    ]);
    audit('clinical_record_completion_reviewed', 'clinical_encounter', $encounterId, [
        'status' => $status,
        'missing_count' => (int)$review['missing_count'],
        'review_hash' => $hash,
    ]);
    return $review;
}

function clinical_record_completion_latest(PDO $pdo, int $encounterId): ?array
{
    if (!schema_table_exists(table('clinical_record_completion_reviews'))) return null;
    $row = clinical_record_completion_fetch_one($pdo, 'SELECT * FROM `' . table('clinical_record_completion_reviews') . '` WHERE encounter_id=? ORDER BY id DESC LIMIT 1', [$encounterId]);
    if (!$row) return null;
    $row['missing'] = json_decode((string)($row['missing_json'] ?? '[]'), true) ?: [];
    $row['checklist'] = json_decode((string)($row['checklist_json'] ?? '[]'), true) ?: [];
    return $row;
}

function procedure_note_template_seed_rows(): array
{
    return [
        ['Oral prophylaxis', 'Pre-op: dental treatment safety history reviewed and consent/indication confirmed. Procedure: scaling and polishing completed; deposits removed; oral hygiene instruction given. Post-op: patient advised on brushing/flossing and recall interval.'],
        ['Restoration', 'Pre-op: tooth, surface, diagnosis, and shade/material confirmed. Procedure: caries removed, cavity prepared, restored, finished, and occlusion checked. Post-op: patient advised about sensitivity, diet, and when to return.'],
        ['Extraction', 'Pre-op: health information relevant to dental care, BP when indicated, consent, tooth, radiographic findings, and anesthesia reviewed. Procedure: extraction completed with hemostasis achieved. Post-op: bleeding control, medication instructions, emergency warnings, and follow-up advice given.'],
        ['Consultation / examination', 'Chief concern reviewed. Extraoral/intraoral assessment completed. Findings and diagnosis explained. Treatment options, risks, benefits, alternatives, and next steps discussed.'],
        ['X-ray / imaging', 'Imaging indication recorded. Image captured/reviewed. Radiographic findings explained and linked to diagnosis or treatment plan.'],
    ];
}
