<?php
/**
 * Included by patients.php after authentication, permission, and patient scope
 * checks have already been completed. It intentionally keeps the established
 * patients.php?action=view URL so existing bookmarks continue to work.
 */

$taskRole = active_role();
$actualRole = actual_role();
$patientId = (int) $id;
$patientAccess = dental_patient_access_capabilities();
$canViewPatientIdentity = !empty($patientAccess['identity']);
$canViewPatientContact = !empty($patientAccess['contact']);
$canViewSafetyAlertFlag = !empty($patientAccess['safety_alert']);
$canViewPatientMedical = !empty($patientAccess['medical']);
$canViewPatientFinancial = !empty($patientAccess['financial']);
$canManagePatientPortal = !empty($patientAccess['portal']);
$cashierView = $taskRole === 'cashier';
$canViewClinicalRecord = $canViewPatientMedical
    && navigation_can('clinical.view', ['super_admin','clinic_admin','dentist','dental_assistant']);
$canViewFinancialRecord = $canViewPatientFinancial
    && navigation_can('billing.manage', ['super_admin','clinic_admin','staff','cashier']);
$canViewDetailedAlerts = $canViewPatientMedical;

$profileTabsByRole = [
    'super_admin' => ['timeline'=>'Timeline','overview'=>'Overview','history'=>'History','clinical'=>'Clinical History','treatment'=>'Treatment History','appointments'=>'Appointments','billing'=>'Billing','documents'=>'Documents','communications'=>'Communications'],
    'clinic_admin' => ['timeline'=>'Timeline','overview'=>'Overview','history'=>'History','clinical'=>'Clinical History','treatment'=>'Treatment History','appointments'=>'Appointments','billing'=>'Billing','documents'=>'Documents','communications'=>'Communications'],
    'dentist' => ['timeline'=>'Timeline','clinical'=>'Clinical','overview'=>'Overview','history'=>'History','treatment'=>'Treatment','appointments'=>'Appointments','documents'=>'Documents','communications'=>'Communications'],
    'receptionist' => ['timeline'=>'Timeline','overview'=>'Overview','appointments'=>'Appointments','communications'=>'Communications'],
    'staff' => ['timeline'=>'Timeline','overview'=>'Overview','appointments'=>'Appointments','billing'=>'Billing','communications'=>'Communications'],
    'dental_assistant' => ['timeline'=>'Timeline','clinical'=>'Clinical','overview'=>'Overview','history'=>'History','treatment'=>'Treatment','appointments'=>'Appointments','documents'=>'Documents'],
    'cashier' => ['billing'=>'Billing'],
];
$profileTabs = $profileTabsByRole[$taskRole] ?? ['overview'=>'Overview'];
if (!$canViewClinicalRecord) {
    unset($profileTabs['history'], $profileTabs['clinical'], $profileTabs['treatment'], $profileTabs['documents']);
}
if (!$canViewFinancialRecord) unset($profileTabs['billing']);
if (!$canViewPatientContact || !navigation_can('communications.manage', ['super_admin','clinic_admin','receptionist','staff','dentist'])) {
    unset($profileTabs['communications']);
}
if (!$profileTabs) $profileTabs = ['overview'=>'Overview'];
$defaultTab = array_key_first($profileTabs) ?: 'overview';
$tab = (string) ($_GET['tab'] ?? $defaultTab);
if (!isset($profileTabs[$tab])) $tab = $defaultTab;

$secondaryTabs = [
    'history' => ['medical'=>'Dental Safety History','dental'=>'Dental History','allergies'=>'Allergies','medications'=>'Medicines','vitals'=>'Vitals','versions'=>'Change Timeline'],
    'clinical' => ['encounters'=>'Encounters','odontogram'=>'Dental Chart','periodontal'=>'Periodontal','notes'=>'Progress Notes','images'=>'Images','checkups'=>'In-house Checkups','vitals'=>'Vitals'],
    'treatment' => ['diagnoses'=>'Diagnoses','plans'=>'Treatment Plans','procedures'=>'Procedures','prescriptions'=>'Prescriptions','referrals'=>'Referrals','laboratory'=>'Laboratory Cases'],
    'appointments' => ['upcoming'=>'Upcoming','past'=>'Past','cancelled'=>'Cancelled','no_show'=>'No-Show','followups'=>'Follow-Ups','recalls'=>'Recalls'],
    'billing' => ['summary'=>'Account Summary','estimates'=>'Estimates','invoices'=>'Invoices','payments'=>'Payments','ledger'=>'Ledger','insurance'=>'Insurance & Claims'],
    'documents' => ['clinical_images'=>'Clinical Images','consents'=>'Consents','clearance'=>'Medical Clearance','forms'=>'Forms','letters'=>'Letters','exports'=>'Record Exports'],
    'communications' => ['all'=>'All','email'=>'Email','sms'=>'SMS','phone'=>'Calls','portal'=>'Portal Activity'],
];
if ($cashierView) $secondaryTabs['billing'] = ['summary'=>'Account Summary','invoices'=>'Invoices','payments'=>'Payments','ledger'=>'Ledger','insurance'=>'Insurance & Claims'];
$sectionDefaults = ['history'=>'medical','clinical'=>'encounters','treatment'=>'diagnoses','appointments'=>'upcoming','billing'=>'summary','documents'=>'clinical_images','communications'=>'all'];
$section = (string) ($_GET['section'] ?? ($sectionDefaults[$tab] ?? ''));
if (isset($secondaryTabs[$tab]) && !isset($secondaryTabs[$tab][$section])) $section = $sectionDefaults[$tab];

$safeFetchAll = static function (string $sql, array $args = []) use ($pdo): array {
    try { $stmt = $pdo->prepare($sql); $stmt->execute($args); return $stmt->fetchAll(); }
    catch (Throwable) { return []; }
};
$safeFetch = static function (string $sql, array $args = []) use ($pdo): ?array {
    try { $stmt = $pdo->prepare($sql); $stmt->execute($args); $row = $stmt->fetch(); return $row ?: null; }
    catch (Throwable) { return null; }
};
$safeValue = static function (string $sql, array $args = [], mixed $fallback = null) use ($pdo): mixed {
    try { $stmt = $pdo->prepare($sql); $stmt->execute($args); $value = $stmt->fetchColumn(); return $value === false ? $fallback : $value; }
    catch (Throwable) { return $fallback; }
};

$guardians = (($canViewClinicalRecord || $canManagePatientPortal) && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('patient_guardians') . '` WHERE patient_id=? ORDER BY id', [$patientId]) : [];
$alerts = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('medical_alerts') . '` WHERE patient_id=? AND is_active=1 ORDER BY FIELD(severity,"critical","caution","information"),created_at DESC', [$patientId]) : [];
$medicalVersions = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT m.*,u.name creator FROM `' . table('medical_histories') . '` m LEFT JOIN `' . table('users') . '` u ON u.id=m.created_by WHERE m.patient_id=? ORDER BY m.created_at DESC', [$patientId]) : [];
$latestMedical = null;
$pendingMedicalCount = 0;
foreach ($medicalVersions as $medicalVersion) {
    $verificationStatus=(string)($medicalVersion['verification_status'] ?? (!empty($medicalVersion['confirmed_at'])?'verified':'pending_review'));
    if ($verificationStatus === 'pending_review') $pendingMedicalCount++;
    if ($latestMedical === null && ($verificationStatus === 'verified' || !empty($medicalVersion['confirmed_at']))) $latestMedical=$medicalVersion;
}
$structuredSafetyContext=['allergies'=>[],'medications'=>[],'conditions'=>[],'history_verified'=>false];
if($canViewClinicalRecord&&function_exists('clinical_safety_schema_ready')&&clinical_safety_schema_ready()){
    try{$structuredSafetyContext=clinical_safety_patient_context($pdo,$patientId);}catch(Throwable $exception){error_log('Patient structured safety context unavailable: '.$exception->getMessage());}
}
$structuredAllergies=(array)($structuredSafetyContext['allergies']??[]);
$structuredMedications=(array)($structuredSafetyContext['medications']??[]);
$structuredConditions=(array)($structuredSafetyContext['conditions']??[]);

// Keep the complete source history for audit, but collapse consecutive identical
// confirmations in the normal view so a single allergy is not presented as
// multiple active records. The full source versions remain available on demand.
$showAllSafetyVersions = (string)($_GET['show_all_safety_versions'] ?? '') === '1';
$medicalTimelineVersions = [];
$collapsedMedicalVersionCount = 0;
foreach ($medicalVersions as $medicalVersion) {
    $versionStatus = (string)($medicalVersion['verification_status'] ?? (!empty($medicalVersion['confirmed_at']) ? 'verified' : 'pending_review'));
    $normalizeSnapshot = static function (mixed $value): string {
        $text = trim((string)$value);
        return function_exists('clinical_safety_normalize') ? clinical_safety_normalize($text) : strtolower((string)(preg_replace('/\s+/u', ' ', $text) ?: $text));
    };
    $fingerprint = hash('sha256', implode('|', [
        $versionStatus,
        $normalizeSnapshot($medicalVersion['allergies'] ?? ''),
        $normalizeSnapshot($medicalVersion['medications'] ?? ''),
        $normalizeSnapshot($medicalVersion['conditions'] ?? ''),
        $normalizeSnapshot($medicalVersion['dental_history'] ?? ''),
    ]));
    $lastIndex = count($medicalTimelineVersions) - 1;
    if (!$showAllSafetyVersions && $lastIndex >= 0 && ($medicalTimelineVersions[$lastIndex]['_snapshot_fingerprint'] ?? '') === $fingerprint) {
        $medicalTimelineVersions[$lastIndex]['_confirmation_count'] = (int)($medicalTimelineVersions[$lastIndex]['_confirmation_count'] ?? 1) + 1;
        $medicalTimelineVersions[$lastIndex]['_earliest_confirmation_at'] = (string)($medicalVersion['created_at'] ?? '');
        $collapsedMedicalVersionCount++;
        continue;
    }
    $medicalVersion['_snapshot_fingerprint'] = $fingerprint;
    $medicalVersion['_confirmation_count'] = 1;
    $medicalTimelineVersions[] = $medicalVersion;
}
$appointmentsAll = $cashierView ? [] : $safeFetchAll('SELECT * FROM `' . table('appointments') . '` WHERE patient_id=? ORDER BY start_at DESC LIMIT 100', [$patientId]);
$encounters = $canViewClinicalRecord ? $safeFetchAll('SELECT * FROM `' . table('clinical_encounters') . '` WHERE patient_id=? ORDER BY created_at DESC LIMIT 100', [$patientId]) : [];
$plans = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('treatment_plans') . '` WHERE patient_id=? ORDER BY created_at DESC', [$patientId]) : [];
$documents = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('documents') . '` WHERE patient_id=? ORDER BY created_at DESC', [$patientId]) : [];
if ($documents) {
    $documents=array_values(array_filter($documents,static function(array $document) use ($patient): bool {
        $document['patient_branch_id']=(int)($patient['branch_id']??0);
        return integrity_document_staff_decision($document)['allowed'];
    }));
}
$consents = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('consent_forms') . '` WHERE patient_id=? ORDER BY created_at DESC', [$patientId]) : [];
$communications = ($canViewPatientContact && navigation_can('communications.manage', ['super_admin','clinic_admin','receptionist','staff','dentist']) && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('communications') . '` WHERE patient_id=? ORDER BY communicated_at DESC LIMIT 100', [$patientId]) : [];
$invoices = $canViewFinancialRecord ? $safeFetchAll('SELECT * FROM `' . table('invoices') . '` WHERE patient_id=? ORDER BY created_at DESC LIMIT 100', [$patientId]) : [];
$payments = $canViewFinancialRecord ? $safeFetchAll('SELECT p.*,i.invoice_no FROM `' . table('payments') . '` p LEFT JOIN `' . table('invoices') . '` i ON i.id=p.invoice_id WHERE i.patient_id=? ORDER BY p.created_at DESC LIMIT 100', [$patientId]) : [];
$paymentAdjustments = $canViewFinancialRecord && schema_table_exists(table('payment_adjustments'))
    ? $safeFetchAll('SELECT pa.*,i.invoice_no,py.reference_no original_reference,rq.name requester,ap.name approver,pr.name processor FROM `' . table('payment_adjustments') . '` pa JOIN `' . table('invoices') . '` i ON i.id=pa.invoice_id JOIN `' . table('payments') . '` py ON py.id=pa.payment_id LEFT JOIN `' . table('users') . '` rq ON rq.id=pa.requested_by LEFT JOIN `' . table('users') . '` ap ON ap.id=pa.approved_by LEFT JOIN `' . table('users') . '` pr ON pr.id=pa.processed_by WHERE i.patient_id=? ORDER BY COALESCE(pa.processed_at,pa.approved_at,pa.requested_at) DESC LIMIT 100', [$patientId])
    : [];
$netPaymentsRetained = 0.0;
foreach ($payments as $paymentRow) {
    $netPaymentsRetained += max(0.0, (float)$paymentRow['amount'] - (float)($paymentRow['adjustment_total'] ?? 0));
}
$diagnoses = ($canViewClinicalRecord && clinical_sequence_schema_ready()) ? $safeFetchAll('SELECT d.*,e.created_at encounter_date,e.dentist_name FROM `' . table('diagnoses') . '` d LEFT JOIN `' . table('clinical_encounters') . '` e ON e.id=d.encounter_id WHERE d.patient_id=? ORDER BY d.diagnosed_at DESC', [$patientId]) : [];
$procedures = ($canViewClinicalRecord && $advanced) ? $safeFetchAll(encounter_assistant_schema_ready() ? 'SELECT pr.*,du.name dentist_name,au.name assistant_name,eu.name entered_by_name,vu.name verified_by_name FROM `' . table('procedures') . '` pr LEFT JOIN `' . table('users') . '` du ON du.id=pr.dentist_user_id LEFT JOIN `' . table('users') . '` au ON au.id=pr.assistant_user_id LEFT JOIN `' . table('users') . '` eu ON eu.id=pr.entered_by_user_id LEFT JOIN `' . table('users') . '` vu ON vu.id=pr.verified_by_user_id WHERE pr.patient_id=? ORDER BY pr.created_at DESC' : 'SELECT pr.*,u.name dentist_name FROM `' . table('procedures') . '` pr LEFT JOIN `' . table('users') . '` u ON u.id=pr.dentist_user_id WHERE pr.patient_id=? ORDER BY pr.created_at DESC', [$patientId]) : [];
$prescriptions = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT rx.*,u.name dentist_name,(SELECT GROUP_CONCAT(pi.medication_name ORDER BY pi.id SEPARATOR \', \') FROM `' . table('prescription_items') . '` pi WHERE pi.prescription_id=rx.id) medication_name FROM `' . table('prescriptions') . '` rx LEFT JOIN `' . table('users') . '` u ON u.id=rx.dentist_user_id WHERE rx.patient_id=? ORDER BY rx.issued_at DESC,rx.id DESC', [$patientId]) : [];
$latestPrescription = $prescriptions[0] ?? null;
$referrals = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('referrals') . '` WHERE patient_id=? ORDER BY created_at DESC', [$patientId]) : [];
$laboratoryCases = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('laboratory_cases') . '` WHERE patient_id=? ORDER BY created_at DESC', [$patientId]) : [];
$followUps = (!$cashierView && $advanced) ? $safeFetchAll('SELECT f.*,u.name dentist_name FROM `' . table('follow_ups') . '` f LEFT JOIN `' . table('users') . '` u ON u.id=f.dentist_user_id WHERE f.patient_id=? ORDER BY f.recommended_date DESC', [$patientId]) : [];
$recalls = (!$cashierView && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('recalls') . '` WHERE patient_id=? ORDER BY due_date DESC', [$patientId]) : [];
$vitals = ($canViewClinicalRecord && $advanced) ? $safeFetchAll('SELECT v.*,e.created_at encounter_date,e.dentist_name FROM `' . table('vital_signs') . '` v LEFT JOIN `' . table('clinical_encounters') . '` e ON e.id=v.encounter_id WHERE v.patient_id=? ORDER BY v.recorded_at DESC LIMIT 50', [$patientId]) : [];
$inhouseCheckups = ($canViewClinicalRecord && $advanced && schema_table_exists(table('inhouse_checkup_results'))) ? $safeFetchAll('SELECT c.*,u.name provider_name,rd.name referral_dentist_name FROM `' . table('inhouse_checkup_results') . '` c LEFT JOIN `' . table('users') . '` u ON u.id=c.provider_user_id LEFT JOIN `' . table('users') . '` rd ON rd.id=c.referral_dentist_user_id WHERE c.patient_id=? ORDER BY c.started_at DESC,c.id DESC LIMIT 100', [$patientId]) : [];
$insurance = ($canViewFinancialRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('patient_insurance') . '` WHERE patient_id=? ORDER BY is_active DESC,created_at DESC', [$patientId]) : [];
$claims = ($canViewFinancialRecord && $advanced) ? $safeFetchAll('SELECT * FROM `' . table('insurance_claims') . '` WHERE patient_id=? ORDER BY created_at DESC', [$patientId]) : [];
$portalAccesses = [];
if ($canManagePatientPortal && !$cashierView && $advanced) {
    if (patient_portal_account_patient_schema_ready()) {
        $portalAccesses = $safeFetchAll('SELECT m.*,a.email,a.status account_status,a.last_login_at,g.name guardian_name FROM `' . table('patient_portal_account_patients') . '` m JOIN `' . table('patient_portal_accounts') . '` a ON a.id=m.account_id LEFT JOIN `' . table('patient_guardians') . '` g ON g.id=m.guardian_id WHERE m.patient_id=? AND m.status="active" ORDER BY m.is_self DESC,m.id', [$patientId]);
    } else {
        $legacyPortal = $safeFetch('SELECT a.*,1 is_self,NULL guardian_id,a.status account_status FROM `' . table('patient_portal_accounts') . '` a WHERE a.patient_id=? LIMIT 1', [$patientId]);
        if ($legacyPortal) $portalAccesses[] = $legacyPortal;
    }
}
$portalAccount = $portalAccesses[0] ?? null;
$portalSelfAccess = null;
$portalGuardianAccessByGuardian = [];
foreach ($portalAccesses as $portalAccessRow) {
    if (!empty($portalAccessRow['is_self'])) $portalSelfAccess = $portalAccessRow;
    if (!empty($portalAccessRow['guardian_id'])) $portalGuardianAccessByGuardian[(int)$portalAccessRow['guardian_id']] = $portalAccessRow;
}
$portalInvite = ($canManagePatientPortal && !$cashierView && $advanced && schema_column_exists(table('patient_portal_invites'),'email_outbox_id')) ? $safeFetch('SELECT i.*,o.status email_status,o.last_error email_error,o.sent_at email_sent_at FROM `' . table('patient_portal_invites') . '` i LEFT JOIN `' . table('email_outbox') . '` o ON o.id=i.email_outbox_id WHERE i.patient_id=? ORDER BY i.id DESC LIMIT 1',[$patientId]) : null;
$currentQueue = $safeFetch('SELECT * FROM `' . table('queue_entries') . '` WHERE patient_id=? AND status NOT IN ("completed","cancelled","left_before_treatment") ORDER BY checked_in_at DESC LIMIT 1', [$patientId]);
$nextAppointment = $cashierView ? null : $safeFetch('SELECT * FROM `' . table('appointments') . '` WHERE patient_id=? AND start_at>=NOW() AND status NOT IN ("cancelled","no_show","completed") ORDER BY start_at LIMIT 1', [$patientId]);
$lastAppointment = $cashierView ? null : $safeFetch('SELECT * FROM `' . table('appointments') . '` WHERE patient_id=? AND start_at<NOW() ORDER BY start_at DESC LIMIT 1', [$patientId]);
$activePlan = ($canViewClinicalRecord && $advanced) ? $safeFetch('SELECT * FROM `' . table('treatment_plans') . '` WHERE patient_id=? AND status IN ("draft","presented","partially_accepted","accepted","scheduled","in_progress") ORDER BY created_at DESC LIMIT 1', [$patientId]) : null;
$primaryDentist = $cashierView ? null : $safeFetch('SELECT dentist_name,dentist_user_id FROM `' . table('appointments') . '` WHERE patient_id=? AND dentist_name<>"" ORDER BY start_at DESC LIMIT 1', [$patientId]);
if (!$cashierView && !$primaryDentist) $primaryDentist = $safeFetch('SELECT dentist_name,dentist_user_id FROM `' . table('clinical_encounters') . '` WHERE patient_id=? AND dentist_name<>"" ORDER BY created_at DESC LIMIT 1', [$patientId]);
$balance = $canViewFinancialRecord ? (float) $safeValue('SELECT COALESCE(SUM(GREATEST(amount-paid_amount,0)),0) FROM `' . table('invoices') . '` WHERE patient_id=? AND status NOT IN ("voided","refunded","written_off")', [$patientId], 0) : 0.0;

$age = '—';
if (!empty($patient['birth_date'])) {
    try { $age = (string) (new DateTimeImmutable((string) $patient['birth_date']))->diff(new DateTimeImmutable('today'))->y; }
    catch (Throwable) { $age = '—'; }
}
$canSeeBalance = $canViewFinancialRecord;
$canBook = in_array($taskRole, ['super_admin','clinic_admin','receptionist','staff'], true) && task_context_page_allowed('appointments');
$canStartEncounter = active_role_is('dentist');
$canCheckIn = in_array($taskRole, ['super_admin','clinic_admin','receptionist','staff'], true) && task_context_page_allowed('queue');

$activeEncounter = null;
$lastFinalizedEncounter = null;
foreach ($encounters as $encounterRow) {
    if ($activeEncounter === null && in_array((string)($encounterRow['status'] ?? ''), ['draft','pending_review','addendum'], true)) $activeEncounter = $encounterRow;
    if ($lastFinalizedEncounter === null && (string)($encounterRow['status'] ?? '') === 'finalized') $lastFinalizedEncounter = $encounterRow;
}
$latestProcedure = $procedures[0] ?? null;
$pendingFollowUp = null;
foreach ($followUps as $followUpRow) {
    if (in_array((string)($followUpRow['status'] ?? ''), ['pending','scheduled'], true)) { $pendingFollowUp = $followUpRow; break; }
}
$timelineCategoryMap = patient_timeline_category_map($taskRole);
$timelineFilters = [
    'category' => trim((string)($_GET['timeline_category'] ?? '')),
    'encounter_id' => max(0, (int)($_GET['timeline_encounter_id'] ?? 0)),
    'from' => trim((string)($_GET['timeline_from'] ?? '')),
    'to' => trim((string)($_GET['timeline_to'] ?? '')),
];
$timelineEvents = ($tab === 'timeline' && $timelineCategoryMap)
    ? patient_timeline_fetch($pdo, $patientId, $taskRole, $timelineFilters)
    : [];
$vitalTrends = $canViewClinicalRecord ? patient_vital_trends($vitals) : [];

function patient_workspace_url(int $patientId, string $tab, string $section = ''): string
{
    $url = 'patients.php?action=view&id=' . $patientId . '&tab=' . rawurlencode($tab);
    if ($section !== '') $url .= '&section=' . rawurlencode($section);
    return $url;
}

function patient_workspace_render_vital_trends(array $trends): void
{
    $units = ['blood_pressure'=>'mmHg','pulse_rate'=>'bpm','oxygen_saturation'=>'%','temperature_c'=>'°C','weight_kg'=>'kg','bmi'=>'','pain_score'=>'','blood_glucose'=>'mg/dL'];
    ?><section class="vital-trend-grid" aria-label="Vital-sign trends"><?php foreach ($trends as $key => $trend): ?><article class="vital-trend-card<?=empty($trend['has_current'])?' no-reading':''?>"><span><?=e((string)$trend['label'])?></span><strong><?=e((string)$trend['current'])?></strong><small><?php if(!empty($trend['current_at'])):?>Latest <?=e(date('M j, Y g:i A',strtotime((string)$trend['current_at'])))?><?php else:?>No reading recorded<?php endif;?></small><div class="vital-trend-comparison"><span>Previous: <?=e((string)$trend['previous'])?></span><span><?=e(patient_vital_delta_label($trend['delta']??null,$units[$key]??''))?></span></div></article><?php endforeach; ?></section><?php
}

function patient_workspace_render_vital_table(array $vitals, int $patientAge): void
{
    ?><div class="table-wrap"><table><thead><tr><th>Date / Encounter</th><th>Blood pressure review</th><th>Pulse / SpO₂</th><th>Temperature / respiration</th><th>Weight / height / BMI</th><th>Pain / glucose</th><th>Measurement context</th></tr></thead><tbody><?php foreach ($vitals as $row): [$bpSys,$bpDia,$bpRepeat]=clinical_vitals_effective_bp($row); $bpScreen=clinical_vitals_bp_screening($row,$patientAge); ?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$row['recorded_at'])))?><?php if(!empty($row['encounter_id'])):?><br><small>Encounter #<?=(int)$row['encounter_id']?></small><?php endif;?></td><td><?=$bpSys!==null?e((string)$bpSys).'/'.e((string)$bpDia).' mmHg':'—'?><?=$bpRepeat?'<br><small>Repeat value used</small>':''?><br><span class="badge vital-<?=e((string)($bpScreen['class']??'neutral'))?>"><?=e((string)($bpScreen['label']??'Clinical review'))?></span><?php if(!empty($bpScreen['message'])):?><br><small><?=e((string)$bpScreen['message'])?></small><?php endif;?></td><td><?=e((string)($row['pulse_rate'] ?? '—'))?> bpm<br><small><?=e((string)($row['oxygen_saturation'] ?? '—'))?>% SpO₂</small></td><td><?=e((string)($row['temperature_c'] ?? '—'))?> °C<br><small><?=e((string)($row['respiratory_rate'] ?? '—'))?>/min</small></td><td><?=e((string)($row['weight_kg'] ?? '—'))?> kg · <?=e((string)($row['height_cm'] ?? '—'))?> cm<br><small>BMI <?=e((string)($row['bmi'] ?? '—'))?></small></td><td><?=isset($row['pain_score'])&&$row['pain_score']!==null?e((string)$row['pain_score']).'/10':'—'?><br><small><?=e((string)($row['blood_glucose'] ?? '—'))?> mg/dL</small></td><td><?=e(module_status((string)($row['bp_position']??'not recorded')))?><?=!empty($row['bp_arm'])?' · '.e(ucfirst((string)$row['bp_arm'])).' arm':''?><?=!empty($row['bp_cuff_size'])?'<br><small>Cuff: '.e(module_status((string)$row['bp_cuff_size'])).'</small>':''?><?=!empty($row['bp_device_type'])?' · <small>'.e(module_status((string)$row['bp_device_type'])).' device</small>':''?><?php if(!empty($row['measurement_notes'])):?><br><small><?=e((string)$row['measurement_notes'])?></small><?php endif;?></td></tr><?php endforeach; ?></tbody></table></div><?php if(!$vitals):?><p class="muted">No vital signs recorded.</p><?php endif;?><?php
}

render_header('Patient Record');
?>
<section class="patient-workspace-header card">
    <div class="patient-identity">
        <?php if (!empty($patient['profile_photo'])): ?><span class="patient-photo"><img src="<?=e((string)$patient['profile_photo'])?>" alt=""></span><?php else: ?><span class="avatar"><?=e(strtoupper(substr((string)$patient['first_name'],0,1).substr((string)$patient['last_name'],0,1)))?></span><?php endif; ?>
        <div><span class="eyebrow">Patient record</span><h2><?=e(patient_full_name($patient))?></h2><p><?=e((string)$patient['patient_no'])?> · <?=e((string)$patient['sex'])?> · Age <?=e($age)?> · <?=e(module_status((string)$patient['status']))?></p></div>
    </div>
    <div class="patient-workspace-actions">
        <?php if ($canViewClinicalRecord && $activeEncounter && in_array((string)($activeEncounter['status']??''),['draft','pending_review','addendum'],true)): ?><a class="btn primary" href="clinical_workspace.php?encounter_id=<?=(int)$activeEncounter['id']?>">Open today’s visit</a><?php elseif ($canBook): ?><a class="btn primary" href="appointments.php?action=new&patient_id=<?=$patientId?>">New appointment</a><?php endif; ?>
        <?php if ($canViewClinicalRecord && $activeEncounter && $canBook): ?><a class="btn ghost" href="appointments.php?action=new&patient_id=<?=$patientId?>">New appointment</a><?php endif; ?>
        <?php if ($canCheckIn && $nextAppointment && date('Y-m-d', strtotime((string)$nextAppointment['start_at'])) === date('Y-m-d') && (string)($nextAppointment['status'] ?? '') === 'confirmed'): ?><a class="btn ghost" href="queue.php?appointment_id=<?=(int)$nextAppointment['id']?>">Check in appointment</a><?php endif; ?>
        <?php if ($canCheckIn && !$currentQueue): ?><a class="btn ghost" href="queue.php?walkin=1&amp;patient_id=<?=$patientId?>">Check in as walk-in</a><?php endif; ?>
        <?php if ($canStartEncounter): ?><a class="btn ghost" href="clinical.php?patient_id=<?=$patientId?>">Start encounter</a><?php endif; ?>
        <?php if (navigation_can('records.print',['super_admin','clinic_admin','dentist','receptionist','staff','dental_assistant','cashier'])): ?><?php $printDocument=in_array($taskRole,['super_admin','clinic_admin','dentist','dental_assistant'],true)?'complete':($taskRole==='cashier'?'ledger':'summary'); ?><a class="btn ghost" target="_blank" href="print_record.php?type=patient_summary&amp;document=<?=e($printDocument)?>&amp;id=<?=$patientId?>"><?= $printDocument==='complete'?'Print complete record':($printDocument==='ledger'?'Print ledger':'Print patient summary') ?></a><?php endif; ?>
        <?php if ($canManagePatient): ?><a class="btn ghost" href="patients.php?action=edit&id=<?=$patientId?>">Edit</a><?php endif; ?>
    </div>
    <?php if ($canViewClinicalRecord && navigation_can('records.print',['super_admin','clinic_admin','dentist','dental_assistant'])): ?>
    <details class="patient-print-options wide">
        <summary>Complete record print options</summary>
        <form method="get" action="print_record.php" target="_blank" class="timeline-filter-form">
            <input type="hidden" name="type" value="patient_summary">
            <input type="hidden" name="document" value="complete">
            <input type="hidden" name="id" value="<?=$patientId?>">
            <label>From date<input type="date" name="date_from"></label>
            <label>To date<input type="date" name="date_to"></label>
            <label>Encounter<select name="encounter_id"><option value="0">All encounters</option><?php foreach ($encounters as $encounterOption): ?><option value="<?=(int)$encounterOption['id']?>"><?=e(date('M j, Y',strtotime((string)$encounterOption['created_at'])))?> · <?=e((string)($encounterOption['dentist_name'] ?: 'Dentist'))?> · <?=e(module_status((string)$encounterOption['status']))?></option><?php endforeach; ?></select></label>
            <button class="btn ghost" type="submit">Print selected record</button>
        </form>
    </details>
    <?php endif; ?>
    <?php if (!$cashierView): ?>
    <div class="patient-alert-strip wide">
        <?php if ($canViewDetailedAlerts): ?>
            <?php if ($patient['medical_alerts'] || $alerts): ?><strong>Clinical alerts</strong><span><?=e(trim((string)$patient['medical_alerts']) ?: 'Structured dental safety alert present')?></span><?php else: ?><strong>No active dental safety alert</strong><span>Review verified health information relevant to dental care before treatment.</span><?php endif; ?>
        <?php elseif ($canViewSafetyAlertFlag && !empty($patient['medical_alerts'])): ?>
            <strong>Dental safety alert on file</strong><span>Clinical details are restricted. Coordinate with the treating clinical team before chairside care.</span>
        <?php else: ?>
            <strong>No scheduling alert shown</strong><span>Clinical details are available only to the authorized care team.</span>
        <?php endif; ?>
    </div>
    <?php endif; ?>
    <div class="patient-snapshot wide">
        <?php if (!$cashierView): ?><div><span>Primary dentist</span><strong><?=e((string)($primaryDentist['dentist_name'] ?? 'Not assigned'))?></strong></div><div><span>Next appointment</span><strong><?= $nextAppointment ? e(date('M j, Y g:i A', strtotime((string)$nextAppointment['start_at']))) : 'None scheduled' ?></strong></div><?php endif; ?>
        <div><span><?= $cashierView ? 'Cashier queue' : 'Current queue' ?></span><strong><?= $currentQueue ? e((string)$currentQueue['queue_no'] . ' · ' . module_status((string)$currentQueue['status'])) : 'Not in queue' ?></strong></div>
        <?php if ($canViewClinicalRecord): ?><div><span>Active treatment</span><strong><?=e((string)($activePlan['title'] ?? 'No active plan'))?></strong></div><div><span>Current assistant</span><strong><?=e((string)($activeEncounter['assistant_name'] ?? 'Not assigned'))?></strong></div><?php endif; ?>
        <?php if ($canSeeBalance): ?><div><span>Outstanding balance</span><strong>₱<?=number_format($balance,2)?></strong></div><div><span>Invoices</span><strong><?=count($invoices)?> account item<?=count($invoices)===1?'':'s'?></strong></div><?php endif; ?>
    </div>
</section>

<nav class="patient-primary-tabs" aria-label="Patient record sections">
<?php foreach ($profileTabs as $key => $label): ?><a class="<?=$tab===$key?'active':''?>" href="<?=e(patient_workspace_url($patientId,$key))?>"><?=e($label)?></a><?php endforeach; ?>
</nav>

<?php if (isset($secondaryTabs[$tab])): ?>
<nav class="patient-secondary-tabs" aria-label="<?=e($profileTabs[$tab])?> sections">
<?php foreach ($secondaryTabs[$tab] as $key => $label): ?><a class="<?=$section===$key?'active':''?>" href="<?=e(patient_workspace_url($patientId,$tab,$key))?>"><?=e($label)?></a><?php endforeach; ?>
</nav>
<?php endif; ?>
<?php if ($tab === 'history'): ?><div class="alert info dental-scope-notice"><strong>Dental-care scope:</strong> This section stores only health information needed for safe dental treatment, dental prescribing, anesthesia or sedation review, bleeding-risk assessment, radiography precautions, and referral decisions. It is not a general medical record.</div><?php endif; ?>

<?php if ($tab === 'timeline'): ?>
<section class="card patient-timeline-toolbar">
    <div class="card-head"><div><span class="eyebrow">Unified patient record</span><h2>Clinical and care timeline</h2><p>Events are read from their authoritative appointment, clinical, document, follow-up, and authorized financial records. Entries are never copied into a separate editable summary.</p></div><span class="version-pill"><?=count($timelineEvents)?> event<?=count($timelineEvents)===1?'':'s'?></span></div>
    <form method="get" class="timeline-filter-form">
        <input type="hidden" name="action" value="view"><input type="hidden" name="id" value="<?=$patientId?>"><input type="hidden" name="tab" value="timeline">
        <label>Category<select name="timeline_category"><option value="">All permitted categories</option><?php foreach ($timelineCategoryMap as $timelineCategory => $timelineLabel): ?><option value="<?=e($timelineCategory)?>" <?=$timelineFilters['category']===$timelineCategory?'selected':''?>><?=e($timelineLabel)?></option><?php endforeach; ?></select></label>
        <?php if ($canViewClinicalRecord): ?><label>Encounter<select name="timeline_encounter_id"><option value="0">All encounters</option><?php foreach ($encounters as $encounterOption): ?><option value="<?=(int)$encounterOption['id']?>" <?=$timelineFilters['encounter_id']===(int)$encounterOption['id']?'selected':''?>><?=e(date('M j, Y',strtotime((string)$encounterOption['created_at'])))?> · <?=e((string)($encounterOption['dentist_name'] ?: 'Dentist'))?> · <?=e(module_status((string)$encounterOption['status']))?></option><?php endforeach; ?></select></label><?php endif; ?>
        <label>From<input type="date" name="timeline_from" value="<?=e($timelineFilters['from'])?>"></label>
        <label>To<input type="date" name="timeline_to" value="<?=e($timelineFilters['to'])?>"></label>
        <div class="timeline-filter-actions"><button class="btn primary" type="submit">Apply filters</button><a class="btn ghost" href="<?=e(patient_workspace_url($patientId,'timeline'))?>">Clear</a></div>
    </form>
</section>
<?php if ($timelineEvents): ?>
<section class="patient-unified-timeline" aria-label="Patient timeline">
<?php $timelineDay=''; foreach ($timelineEvents as $event): $eventDay=date('F j, Y',strtotime((string)$event['at'])); if($eventDay!==$timelineDay): $timelineDay=$eventDay; ?><h3 class="timeline-day-heading"><?=e($timelineDay)?></h3><?php endif; ?>
<article class="unified-timeline-item<?=!empty($event['flag'])?' flag-'.e((string)$event['flag']):''?>">
    <div class="timeline-rail"><span class="timeline-dot"></span><time><?=e(date('g:i A',strtotime((string)$event['at'])))?></time></div>
    <div class="timeline-event-card">
        <div class="record-head"><div><span class="badge timeline-category"><?=e($timelineCategoryMap[$event['category']] ?? module_status((string)$event['category']))?></span><h3><?=e((string)$event['title'])?></h3></div><?php if(!empty($event['status'])):?><span class="badge"><?=e(module_status((string)$event['status']))?></span><?php endif;?></div>
        <?php if(!empty($event['summary'])):?><p><?=e((string)$event['summary'])?></p><?php endif;?>
        <div class="timeline-attribution">
            <?php if(!empty($event['dentist'])):?><span><strong>Dentist:</strong> <?=e((string)$event['dentist'])?></span><?php endif;?>
            <?php if(!empty($event['assistant'])):?><span><strong>Assistant:</strong> <?=e((string)$event['assistant'])?></span><?php endif;?>
            <?php if(!empty($event['actor'])):?><span><strong>Recorded by:</strong> <?=e((string)$event['actor'])?></span><?php endif;?>
            <?php if((int)$event['encounter_id']>0):?><span><strong>Encounter:</strong> #<?=(int)$event['encounter_id']?></span><?php endif;?>
        </div>
        <?php if(!empty($event['url'])):?><a class="timeline-source-link" href="<?=e((string)$event['url'])?>"<?=str_starts_with((string)$event['url'],'print_record.php')?' target="_blank"':''?>>Open source record</a><?php endif;?>
    </div>
</article>
<?php endforeach; ?>
</section>
<?php else: ?><section class="card queue-empty"><h3>No matching timeline entries</h3><p>Clear or widen the filters, or create the first authorized record for this patient.</p></section><?php endif; ?>

<?php elseif ($tab === 'overview'): ?>
<section class="patient-overview-grid">
    <article class="card"><div class="card-head"><h3>Patient information</h3><?php if ($canManagePatient): ?><a href="patients.php?action=edit&id=<?=$patientId?>">Edit</a><?php endif; ?></div><dl><dt>Birth date</dt><dd><?=e((string)$patient['birth_date'])?></dd><dt>Sex</dt><dd><?=e((string)$patient['sex'])?></dd><?php if($canViewPatientContact):?><dt>Mobile</dt><dd><?=e((string)$patient['mobile'])?></dd><dt>Email</dt><dd><?=e((string)$patient['email'])?></dd><dt>Address</dt><dd><?=nl2br(e((string)$patient['address']))?></dd><dt>Emergency contact</dt><dd><?=e((string)$patient['emergency_contact'])?></dd><?php else:?><dt>Contact details</dt><dd>Restricted to authorized patient-coordination staff.</dd><?php endif;?></dl></article>
    <?php if ($canViewClinicalRecord): ?>
    <article class="card"><div class="card-head"><h3>Active alerts</h3><?php if ($canVerifyMedical): ?><button class="link-btn" data-open="alert-form">Add verified alert</button><?php endif; ?></div><?php foreach ($alerts as $alert): ?><div class="patient-alert-card severity-<?=e((string)$alert['severity'])?>"><strong><?=e((string)$alert['alert_type'])?></strong><span><?=e((string)$alert['description'])?></span></div><?php endforeach; ?><?php if (!$alerts): ?><p class="muted"><?=nl2br(e((string)($patient['medical_alerts'] ?: 'No active structured alerts.')))?></p><?php endif; ?></article>
    <article class="card"><h3>Current clinical summary</h3><dl><dt>Responsible Dentist</dt><dd><?=e((string)($activeEncounter['dentist_name'] ?? $lastFinalizedEncounter['dentist_name'] ?? $primaryDentist['dentist_name'] ?? 'Not assigned'))?></dd><dt>Dental Assistant</dt><dd><?=e((string)($activeEncounter['assistant_name'] ?? $lastFinalizedEncounter['assistant_name'] ?? 'Not assigned'))?></dd><dt>Latest completed treatment</dt><dd><?php if($latestProcedure):?><?=e((string)$latestProcedure['procedure_name'])?> · <?=e(date('M j, Y',strtotime((string)$latestProcedure['created_at'])))?><?php else:?>None recorded<?php endif;?></dd><dt>Active treatment plan</dt><dd><?=e((string)($activePlan['title'] ?? 'None'))?></dd><dt>Latest prescription</dt><dd><?php if($latestPrescription):?><a target="_blank" href="print_record.php?type=prescription&amp;id=<?=(int)$latestPrescription['id']?>"><?=e((string)($latestPrescription['medication_name']?:$latestPrescription['prescription_no']))?></a><br><small><?=e(date('M j, Y',strtotime((string)($latestPrescription['issued_at']??$latestPrescription['created_at']))))?> · <?=e((string)($latestPrescription['dentist_name']?:'Dentist'))?></small><?php else:?>None issued<?php endif;?></dd><dt>Outstanding follow-up</dt><dd><?= $pendingFollowUp ? e((string)$pendingFollowUp['purpose'] . ' · ' . $pendingFollowUp['recommended_date']) : 'None pending' ?></dd></dl></article>
    <?php else: ?>
    <article class="card"><h3>Care coordination</h3><dl><dt>Primary Dentist</dt><dd><?=e((string)($primaryDentist['dentist_name'] ?? 'Not assigned'))?></dd><dt>Next appointment</dt><dd><?= $nextAppointment ? e(date('M j, Y g:i A',strtotime((string)$nextAppointment['start_at']))) : 'None scheduled' ?></dd><dt>Current queue</dt><dd><?= $currentQueue ? e((string)$currentQueue['queue_no'].' · '.module_status((string)$currentQueue['status'])) : 'Not in queue' ?></dd><dt>Follow-up</dt><dd><?= $pendingFollowUp ? e((string)$pendingFollowUp['purpose'].' · '.$pendingFollowUp['recommended_date']) : 'None pending' ?></dd></dl></article>
    <article class="card"><h3>Privacy-limited view</h3><p>Clinical diagnoses, treatment details, prescriptions, and vital signs are restricted to the authorized care team. This workspace contains only the information required for scheduling and patient coordination.</p><a href="<?=e(patient_workspace_url($patientId,'timeline'))?>">Open coordination timeline</a></article>
    <?php endif; ?>
    <?php if ($canViewClinicalRecord || $canManagePatientPortal): ?>
    <article class="card">
        <div class="card-head"><h3>Guardian and portal</h3><?php if ($canManagePatient): ?><button class="link-btn" data-open="guardian-form">Add guardian</button><?php endif; ?></div>
        <?php foreach ($guardians as $guardian): $guardianStatus=(string)($guardian['verification_status']??'pending'); ?>
        <div class="timeline-item">
            <h4><?=e((string)$guardian['name'])?> <span class="badge"><?=e(module_status($guardianStatus))?></span></h4>
            <p><?=e((string)$guardian['relationship'])?> · <?=e(($canViewPatientContact || $canManagePatientPortal) ? (string)$guardian['mobile'] : dental_mask_contact((string)$guardian['mobile'],'phone'))?></p>
            <small>Consent authority: <?=!empty($guardian['authorized_to_consent'])?'Granted':'Not granted'?> · Record-release authority: <?=!empty($guardian['authorized_to_receive_records'])?'Granted':'Not granted'?></small>
            <?php if($canVerifyGuardian):?><details><summary><?=$guardianStatus==='verified'?'Review or change authority':'Verify identity and authority'?></summary><form method="post" class="compact-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="verify_guardian"><input type="hidden" name="patient_id" value="<?=$patientId?>"><input type="hidden" name="guardian_id" value="<?=(int)$guardian['id']?>"><label>Verification method<input name="verification_method" required value="<?=e((string)($guardian['verification_method']??''))?>" placeholder="Government ID, birth certificate, court order"></label><label>Supporting note<textarea name="verification_note" required placeholder="Record the document checked, identifier, relationship, scope, and reviewer conclusion."><?=e((string)($guardian['verification_note']??''))?></textarea></label><label class="check-option"><input type="checkbox" name="authorized_to_consent" <?=!empty($guardian['authorized_to_consent'])?'checked':''?>><span>Grant consent authority</span></label><label class="check-option"><input type="checkbox" name="authorized_to_receive_records" <?=!empty($guardian['authorized_to_receive_records'])?'checked':''?>><span>Grant record-release authority</span></label><button class="btn primary">Save guardian authority</button></form><?php if($guardianStatus==='verified'):?><form method="post" class="compact-form danger-zone" onsubmit="return confirm('Revoke this guardian’s authority and dependent portal access?')"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="revoke_guardian"><input type="hidden" name="patient_id" value="<?=$patientId?>"><input type="hidden" name="guardian_id" value="<?=(int)$guardian['id']?>"><label>Revocation reason<textarea name="revocation_reason" required placeholder="State why authority or record access is being withdrawn."></textarea></label><button class="btn danger">Revoke authority and portal access</button></form><?php endif;?></details><?php endif;?>
        </div>
        <?php endforeach; ?>
        <?php if (!$guardians): ?><p class="muted">No guardian linked.</p><?php endif; ?>
        <?php if($canManagePatientPortal):?><hr><p><strong>Portal access:</strong> <?=count($portalAccesses)?> active account<?=count($portalAccesses)===1?'':'s'?></p>
        <?php if($portalInvite):?><p><strong>Latest invitation:</strong> <span class="badge email-<?=e((string)($portalInvite['email_status']??'pending'))?>"><?=e(email_delivery_label((string)($portalInvite['email_status']??'pending')))?></span><br><small><?=e((string)$portalInvite['email'])?> · expires <?=e(date('M j, Y g:i A',strtotime((string)$portalInvite['expires_at'])))?></small></p><?php if(!empty($portalInvite['email_error'])):?><p class="warning-text"><?=e((string)$portalInvite['email_error'])?></p><?php endif;?><?php endif;?>
        <?php if ($canPortalInvite): ?>
        <div class="portal-access-list">
            <p><strong>Patient account:</strong> <?=e($portalSelfAccess ? module_status((string)($portalSelfAccess['account_status']??'active')) : 'Not activated')?></p>
            <?php if(!$portalSelfAccess):?>
                <?php if(filter_var((string)$patient['email'],FILTER_VALIDATE_EMAIL)):?><form method="post" class="inline-portal-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="invite_portal"><input type="hidden" name="patient_id" value="<?=$patientId?>"><input type="email" name="email" value="<?=e((string)$patient['email'])?>" readonly required><button class="btn ghost">Invite patient</button></form><?php else:?><p class="muted">Save a valid patient email before inviting the patient.</p><?php endif;?>
            <?php endif;?>
            <?php foreach($guardians as $guardian):$guardianId=(int)$guardian['id'];$guardianCanPortal=(string)($guardian['verification_status']??'pending')==='verified'&&!empty($guardian['authorized_to_receive_records'])&&filter_var((string)($guardian['email']??''),FILTER_VALIDATE_EMAIL);$guardianPortal=$portalGuardianAccessByGuardian[$guardianId]??null;?>
                <?php if($guardianCanPortal):?><div class="timeline-item"><strong><?=e((string)$guardian['name'])?> portal</strong><small><?=e((string)$guardian['email'])?> · <?=e($guardianPortal?module_status((string)($guardianPortal['account_status']??'active')):'Not activated')?><?php if(empty($guardian['authorized_to_consent'])):?> · View-only records access<?php endif;?></small><?php if(!$guardianPortal):?><form method="post" class="inline-portal-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="invite_portal"><input type="hidden" name="patient_id" value="<?=$patientId?>"><input type="hidden" name="guardian_id" value="<?=$guardianId?>"><input type="email" value="<?=e((string)$guardian['email'])?>" readonly><button class="btn ghost">Invite guardian</button></form><?php endif;?></div><?php endif;?>
            <?php endforeach;?>
        </div>
        <?php endif; ?>
        <?php endif; ?>
    </article>
    <?php endif; ?>
    <article class="card wide"><h3>Quick actions</h3><div class="patient-quick-actions"><a href="<?=e(patient_workspace_url($patientId,'timeline'))?>">Open unified timeline</a><?php if ($canBook): ?><a href="appointments.php?action=new&patient_id=<?=$patientId?>">Book appointment</a><?php endif; ?><?php if ($canClinicalWrite): ?><a href="treatment.php?patient_id=<?=$patientId?>">Create treatment plan</a><?php endif; ?><?php if($canViewClinicalRecord):?><a href="<?=e(patient_workspace_url($patientId,'history','medical'))?>">Review history</a><a href="<?=e(patient_workspace_url($patientId,'clinical','encounters'))?>">Open clinical record</a><?php endif;?><?php if ($canSeeBalance): ?><a href="<?=e(patient_workspace_url($patientId,'billing','summary'))?>">Review account</a><?php endif; ?><a href="visit_workflow.php?patient_id=<?=$patientId?>">Patient journey</a></div></article>
</section>

<?php elseif ($tab === 'history'): ?>
<?php if ($section === 'medical'): ?><section class="card"><div class="card-head"><div><h2>Dental treatment safety history</h2><p>Record only health information needed for safe dental treatment, dental prescribing, anesthesia/sedation, bleeding-risk assessment, radiography precautions, and referral decisions.</p></div><?php if ($canMedicalHistory): ?><button class="btn primary" data-open="medical-form"><?=$canVerifyMedical?'Verify updated history':'Record patient update'?></button><?php endif; ?></div><?php if($pendingMedicalCount>0):?><div class="alert warning"><strong><?=$pendingMedicalCount?> update<?=$pendingMedicalCount===1?'':'s'?> pending dentist review.</strong> Pending entries are retained in the Change Timeline but are not activated as clinical alerts.</div><?php endif;?><dl class="history-summary"><dt>Conditions</dt><dd><?=nl2br(e((string)($latestMedical['conditions'] ?? 'No verified conditions recorded')))?></dd><dt>Allergies</dt><dd><?=nl2br(e((string)($latestMedical['allergies'] ?? 'No verified allergies recorded')))?></dd><dt>Current medicines relevant to dental care</dt><dd><?=nl2br(e((string)($latestMedical['medications'] ?? 'No verified medications recorded')))?></dd><dt>Structured active entries</dt><dd><?=count($structuredConditions)?> condition<?=count($structuredConditions)===1?'':'s'?> · <?=count($structuredAllergies)?> allerg<?=count($structuredAllergies)===1?'y':'ies'?> · <?=count($structuredMedications)?> medication<?=count($structuredMedications)===1?'':'s'?></dd><dt>Verified</dt><dd><?=isset($latestMedical['verified_at'])&&$latestMedical['verified_at'] ? e(date('M j, Y g:i A',strtotime((string)$latestMedical['verified_at']))) : (isset($latestMedical['confirmed_at'])&&$latestMedical['confirmed_at'] ? e(date('M j, Y g:i A',strtotime((string)$latestMedical['confirmed_at']))) : 'Not yet verified')?></dd></dl></section>
<?php elseif ($section === 'dental'): ?><section class="card"><h2>Dental history</h2><p><?=nl2br(e((string)($latestMedical['dental_history'] ?? 'No dental history recorded.')))?></p><div class="timeline-list"><?php foreach ($encounters as $row): ?><article class="timeline-item"><h4><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?> · <?=e((string)$row['dentist_name'])?><?php if(!empty($row['assistant_name'])):?> · Assistant <?=e((string)$row['assistant_name'])?><?php endif;?></h4><p><?=e((string)($row['procedure_done'] ?: $row['diagnosis'] ?: 'Dental visit'))?></p></article><?php endforeach; ?></div></section>
<?php elseif ($section === 'allergies'): ?><section class="card"><div class="card-head"><div><h2>Current allergies and dental treatment alerts</h2><p>One canonical current record is shown for each dentist-verified allergy. Earlier reports and confirmations remain in the Change Timeline.</p></div><?php if ($canVerifyMedical): ?><button class="btn primary" data-open="alert-form">Add verified alert</button><?php endif; ?></div>
<?php if($structuredAllergies):?><h3>Current verified allergies</h3><div class="module-card-grid"><?php foreach($structuredAllergies as $allergy):?><article class="module-card"><span class="badge"><?=e(module_status((string)($allergy['verification_status']??'verified')))?></span><h3><?=e((string)($allergy['substance_name']??'Allergy'))?></h3><p><?=e((string)($allergy['reaction']??'Reaction not separately recorded'))?></p><small>Severity: <?=e(module_status((string)($allergy['severity']??'unknown')))?><?php if(!empty($allergy['verified_at'])):?> · Confirmed <?=e(date('M j, Y',strtotime((string)$allergy['verified_at'])))?><?php endif;?></small></article><?php endforeach;?></div><?php else:?><p class="muted"><?=nl2br(e((string)($latestMedical['allergies'] ?? 'No verified allergies reported.')))?></p><?php endif;?>
<?php if($alerts):?><h3>Active clinical alerts</h3><?php foreach ($alerts as $alert): ?><article class="patient-alert-card severity-<?=e((string)$alert['severity'])?>"><strong><?=e((string)$alert['alert_type'])?> · <?=e(module_status((string)$alert['severity']))?></strong><span><?=nl2br(e((string)$alert['description']))?></span></article><?php endforeach; ?><?php endif;?></section>
<?php elseif ($section === 'medications'): ?><section class="card"><h2>Current and reported medications</h2><div class="alert warning"><strong>Clinical limitation:</strong> the structured list is used by clinic-curated safety rules, but DentalCare does not claim a complete external drug-interaction database. Unknown medicines are shown as data gaps, not as safe.</div>
<?php if($structuredMedications):?><div class="module-card-grid"><?php foreach($structuredMedications as $medication):?><article class="module-card"><span class="badge"><?=e(module_status((string)($medication['verification_status']??'verified')))?></span><h3><?=e((string)($medication['medication_name']??'Medication'))?></h3><p><?=e((string)($medication['dose_text']??'Dose not separately recorded'))?></p><small><?=e((string)($medication['frequency']??'Frequency not separately recorded'))?></small></article><?php endforeach;?></div><?php else:?><p><?=nl2br(e((string)($latestMedical['medications'] ?? 'No verified medications reported.')))?></p><?php endif;?>
<h3>Clinic-issued prescriptions</h3><div class="table-wrap"><table><thead><tr><th>Date</th><th>Medication</th><th>Dentist</th><th>Prescription</th><th>Safety review</th></tr></thead><tbody><?php foreach ($prescriptions as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><?=e((string)($row['medication_name'] ?? 'Prescription'))?></td><td><?=e((string)($row['dentist_name'] ?? ''))?></td><td><?=e(module_status((string)$row['status']))?></td><td><?=e(clinical_safety_status_label((string)($row['safety_status']??'pending')))?></td></tr><?php endforeach; ?></tbody></table></div></section>
<?php elseif ($section === 'vitals'): ?><section class="card"><div class="card-head"><div><h2>Vital-sign trends</h2><p>Latest values are compared with the previous recorded value. These are documentation and screening cues, not an automatic diagnosis.</p></div><a href="<?=e(patient_workspace_url($patientId,'timeline'))?>&amp;timeline_category=vitals">Open vital timeline</a></div><?php patient_workspace_render_vital_trends($vitalTrends); ?><h3>Complete measurement history</h3><?php patient_workspace_render_vital_table($vitals,(int)$age); ?></section>
<?php else: ?><section class="card"><div class="card-head"><div><h2>Dental safety change timeline</h2><p>The current summary shows one active record per allergy, medicine, or condition. This timeline preserves when information was reported, confirmed, or changed and who handled it.</p></div><div class="inline-actions"><?php if($showAllSafetyVersions):?><a class="btn ghost" href="<?=e(patient_workspace_url($patientId,'history','versions'))?>">Collapse repeated confirmations</a><?php else:?><a class="btn ghost" href="<?=e(patient_workspace_url($patientId,'history','versions').'&show_all_safety_versions=1')?>">Show every source version</a><?php endif;?></div></div><?php if(!$showAllSafetyVersions&&$collapsedMedicalVersionCount>0):?><div class="alert information"><strong><?=$collapsedMedicalVersionCount?> repeated confirmation<?=$collapsedMedicalVersionCount===1?'':'s'?> collapsed.</strong> No source record was deleted; use “Show every source version” for the complete audit trail.</div><?php endif;?></section><section class="timeline-list"><?php foreach ($medicalTimelineVersions as $row): $versionStatus=(string)($row['verification_status']??(!empty($row['confirmed_at'])?'verified':'pending_review'));?><article class="card"><div class="card-head"><h3><?=e(date('F j, Y g:i A',strtotime((string)$row['created_at'])))?></h3><span><span class="badge"><?=e(module_status($versionStatus))?></span> <?=e((string)($row['creator'] ?: 'Patient/clinic'))?></span></div><?php if((int)($row['_confirmation_count']??1)>1):?><p class="muted"><strong><?=(int)$row['_confirmation_count']?> identical confirmations</strong> are represented by this unchanged snapshot.</p><?php endif;?><p class="muted">Source: <?=e(module_status((string)($row['source_type']??'legacy_record')))?><?php if(!empty($row['verification_note'])):?> · <?=e((string)$row['verification_note'])?><?php endif;?></p><dl><dt>Allergies</dt><dd><?=nl2br(e((string)($row['allergies'] ?: 'None reported')))?></dd><dt>Medications</dt><dd><?=nl2br(e((string)($row['medications'] ?: 'None reported')))?></dd><dt>Conditions</dt><dd><?=nl2br(e((string)($row['conditions'] ?: 'None reported')))?></dd><dt>Dental history</dt><dd><?=nl2br(e((string)($row['dental_history'] ?: 'None reported')))?></dd></dl></article><?php endforeach; ?><?php if (!$medicalTimelineVersions): ?><div class="card queue-empty">No dental-safety history version saved.</div><?php endif; ?></section><?php endif; ?>

<?php elseif ($tab === 'clinical'): ?>
<?php if ($section === 'encounters' || $section === 'notes'): ?><section class="card table-wrap"><div class="card-head"><div><h2><?= $section==='notes'?'Progress notes':'Clinical encounters' ?></h2><p>Chronological clinical history.</p></div><?php if ($canClinicalWrite): ?><a class="btn primary" href="clinical.php?patient_id=<?=$patientId?>">New encounter</a><?php endif; ?></div><table><thead><tr><th>Date</th><th>Care team</th><th>Complaint</th><th>Diagnosis</th><th>Procedure</th><th>Status</th><th></th></tr></thead><tbody><?php foreach ($encounters as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><strong><?=e((string)$row['dentist_name'])?></strong><?php if(!empty($row['assistant_name'])):?><br><small>Assistant: <?=e((string)$row['assistant_name'])?></small><?php endif;?></td><td><?=e((string)$row['chief_complaint'])?></td><td><?=e((string)$row['diagnosis'])?></td><td><?=e((string)$row['procedure_done'])?></td><td><?=e(module_status((string)$row['status']))?></td><td><a href="clinical_workspace.php?encounter_id=<?=(int)$row['id']?>">Open</a></td></tr><?php endforeach; ?></tbody></table></section>
<?php elseif ($section === 'odontogram'): ?><section class="card patient-context-launch"><h2>Dental Chart</h2><p>Open the graphical current and historical tooth chart for this patient.</p><a class="btn primary" href="odontogram.php?patient_id=<?=$patientId?>">Open dental chart</a></section>
<?php elseif ($section === 'periodontal'): ?><section class="card patient-context-launch"><h2>Periodontal chart</h2><p>Review probing depths, recession, bleeding, mobility, furcation, and prior comparisons.</p><a class="btn primary" href="periodontal.php?patient_id=<?=$patientId?>">Open periodontal chart</a></section>
<?php elseif ($section === 'checkups'): ?><section class="card table-wrap"><div class="card-head"><div><h2>Dental support services</h2><p>Approved dental-support work and documented Dentist handoffs performed by the assigned clinic team.</p></div><?php if(task_link_allowed('inhouse_checkups.php')):?><a class="btn ghost" href="inhouse_checkups.php">Open dental-support workspace</a><?php endif;?></div><table><thead><tr><th>Date</th><th>Checkup</th><th>Provider</th><th>Measurements</th><th>Findings</th><th>Outcome</th></tr></thead><tbody><?php foreach($inhouseCheckups as $row):$measurements=array_filter([($row['blood_pressure_systolic']!==null&&$row['blood_pressure_diastolic']!==null)?$row['blood_pressure_systolic'].'/'.$row['blood_pressure_diastolic'].' mmHg':null,$row['pulse_rate']!==null?$row['pulse_rate'].' bpm':null,$row['temperature_c']!==null?$row['temperature_c'].' °C':null,$row['oxygen_saturation']!==null?$row['oxygen_saturation'].'% SpO₂':null,$row['weight_kg']!==null?$row['weight_kg'].' kg':null,$row['bmi']!==null?'BMI '.$row['bmi']:null,$row['blood_glucose_mg_dl']!==null?$row['blood_glucose_mg_dl'].' mg/dL':null]);?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$row['started_at'])))?></td><td><strong><?=e((string)$row['service_name'])?></strong><?php if(!empty($row['abnormal_flag'])):?><br><span class="urgency urgent">Flagged</span><?php endif;?></td><td><?=e((string)($row['provider_name']?:'Clinic staff'))?></td><td><?=e($measurements?implode(' · ',$measurements):'—')?></td><td><?=nl2br(e((string)($row['findings']?:$row['notes']?:'—')))?></td><td><?=e(module_status((string)$row['status']))?><?php if(!empty($row['referral_dentist_name'])):?><br><small>Referred to <?=e((string)$row['referral_dentist_name'])?></small><?php endif;?></td></tr><?php endforeach;?></tbody></table><?php if(!$inhouseCheckups):?><p class="muted">No dental-support service result is recorded.</p><?php endif;?></section>
<?php elseif ($section === 'images'): ?><section class="module-card-grid"><?php foreach ($documents as $row): if (!in_array(strtolower((string)$row['category']),['x-ray','xray','clinical image','intraoral photograph','extraoral photograph','panoramic'],true)) continue; ?><article class="module-card"><h3><?=e((string)$row['category'])?></h3><p><?=e((string)$row['file_name'])?></p><a href="download_document.php?id=<?=(int)$row['id']?>">Open</a></article><?php endforeach; ?><article class="module-card"><h3>Manage images</h3><p>Upload, categorize, and review protected clinical files.</p><a href="documents.php?patient_id=<?=$patientId?>">Open image center</a></article></section>
<?php else: ?><section class="card"><div class="card-head"><div><h2>Vitals linked to encounters</h2><p>Review current values, previous values, and the original encounter context.</p></div><a href="<?=e(patient_workspace_url($patientId,'history','vitals'))?>">Open full vital history</a></div><?php patient_workspace_render_vital_trends($vitalTrends); ?><?php patient_workspace_render_vital_table($vitals,(int)$age); ?></section><?php endif; ?>

<?php elseif ($tab === 'treatment'): ?>
<?php if ($section === 'diagnoses'): ?><section class="card table-wrap"><h2>Diagnoses</h2><table><thead><tr><th>Date</th><th>Tooth / region</th><th>Diagnosis</th><th>Severity</th><th>Status</th><th>Dentist</th></tr></thead><tbody><?php foreach ($diagnoses as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['diagnosed_at'])))?></td><td><?=e((string)$row['tooth_region'])?></td><td><?=e((string)$row['diagnosis_name'])?></td><td><?=e(module_status((string)$row['severity']))?></td><td><?=e(module_status((string)$row['diagnosis_status']))?></td><td><?=e((string)$row['dentist_name'])?></td></tr><?php endforeach; ?></tbody></table></section>
<?php elseif ($section === 'plans'): ?><section><div class="toolbar"><strong>Treatment plans</strong><a class="btn primary" href="treatment.php?patient_id=<?=$patientId?>"><?= $canClinicalWrite ? 'Manage plans' : 'View plans' ?></a></div><div class="module-card-grid"><?php foreach ($plans as $row): ?><article class="module-card"><span class="badge"><?=e(module_status((string)$row['status']))?></span><h3><?=e((string)$row['title'])?></h3><p><?=e((string)$row['phase'])?></p><strong>₱<?=number_format((float)$row['estimate_total'],2)?></strong></article><?php endforeach; ?></div></section>
<?php elseif ($section === 'procedures'): ?><section class="card table-wrap"><h2>Procedures</h2><table><thead><tr><th>Date</th><th>Procedure</th><th>Tooth / region</th><th>Responsible Dentist</th><th>Entered / verified</th><th>Status</th></tr></thead><tbody><?php foreach ($procedures as $row): $entryName=(string)(($row['entered_by_name']??'') ?: ($row['assistant_name']??$row['dentist_name']??'—')); ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><?=e((string)$row['procedure_name'])?></td><td><?=e((string)$row['tooth_region'])?></td><td><?=e((string)$row['dentist_name'])?></td><td><?=e($entryName)?><?php if(!empty($row['entered_by_role'])): ?><br><small><?=e(module_status((string)$row['entered_by_role']))?></small><?php endif; ?><?php if(!empty($row['verified_by_name'])): ?><br><small>Verified by <?=e((string)$row['verified_by_name'])?><?=!empty($row['verified_at'])?' · '.e(date('M j, Y g:i A',strtotime((string)$row['verified_at']))):''?></small><?php elseif (($row['entered_by_role']??'') === 'dental_assistant'): ?><br><span class="badge warning">Awaiting Dentist verification</span><?php endif; ?></td><td><?=e(module_status((string)$row['status']))?></td></tr><?php endforeach; ?></tbody></table></section>
<?php elseif ($section === 'prescriptions'): ?><section class="card table-wrap"><div class="card-head"><h2>Prescriptions</h2><a href="prescriptions.php?patient_id=<?=$patientId?>">Open prescription module</a></div><table><thead><tr><th>Date</th><th>Medication</th><th>Dentist</th><th>Status</th><th>Safety review</th></tr></thead><tbody><?php foreach ($prescriptions as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><?=e((string)($row['medication_name'] ?? 'Prescription'))?></td><td><?=e((string)$row['dentist_name'])?></td><td><?=e(module_status((string)$row['status']))?></td><td><?=e(clinical_safety_status_label((string)($row['safety_status']??'pending')))?></td></tr><?php endforeach; ?></tbody></table></section>
<?php elseif ($section === 'referrals'): ?><section class="card table-wrap"><div class="card-head"><h2>Referrals</h2><a href="referrals.php?patient_id=<?=$patientId?>">Manage</a></div><table><thead><tr><th>Date</th><th>Provider</th><th>Reason</th><th>Urgency</th><th>Status</th></tr></thead><tbody><?php foreach ($referrals as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><?=e((string)$row['provider_name'])?></td><td><?=e((string)$row['reason'])?></td><td><?=e(module_status((string)$row['urgency']))?></td><td><?=e(module_status((string)$row['status']))?></td></tr><?php endforeach; ?></tbody></table></section>
<?php else: ?><section class="card table-wrap"><div class="card-head"><h2>Laboratory cases</h2><a href="laboratory.php?patient_id=<?=$patientId?>">Manage</a></div><table><thead><tr><th>Date</th><th>Case</th><th>Laboratory</th><th>Due</th><th>Status</th></tr></thead><tbody><?php foreach ($laboratoryCases as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><?=e((string)$row['case_type'])?></td><td><?=e((string)$row['laboratory_name'])?></td><td><?=e((string)$row['due_date'])?></td><td><?=e(module_status((string)$row['status']))?></td></tr><?php endforeach; ?></tbody></table></section><?php endif; ?>

<?php elseif ($tab === 'appointments'): ?>
<?php
$filteredAppointments = array_values(array_filter($appointmentsAll, static function(array $row) use ($section): bool {
    $status = strtolower((string)$row['status']); $time = strtotime((string)$row['start_at']); $now = time();
    return match($section) { 'upcoming' => $time >= $now && !in_array($status,['cancelled','no_show','completed'],true), 'past' => $time < $now && !in_array($status,['cancelled','no_show'],true), 'cancelled' => $status==='cancelled', 'no_show' => $status==='no_show', default => true };
}));
?>
<?php if (in_array($section,['upcoming','past','cancelled','no_show'],true)): ?><section class="card table-wrap"><div class="card-head"><h2><?=e($secondaryTabs['appointments'][$section])?></h2><?php if ($canBook): ?><a class="btn primary" href="appointments.php?action=new&patient_id=<?=$patientId?>">Book appointment</a><?php endif; ?></div><table><thead><tr><th>Date</th><th>Service</th><th>Dentist</th><th>Chair</th><th>Source</th><th>Status</th></tr></thead><tbody><?php foreach ($filteredAppointments as $row): ?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$row['start_at'])))?></td><td><?=e((string)$row['service_name'])?></td><td><?=e((string)$row['dentist_name'])?></td><td><?=e((string)$row['chair_name'])?></td><td><?=e(module_status((string)($row['appointment_origin'] ?? 'manual')))?></td><td><?=e(module_status((string)$row['status']))?></td></tr><?php endforeach; ?></tbody></table></section>
<?php elseif ($section === 'followups'): ?><section class="card table-wrap"><div class="card-head"><h2>Follow-ups</h2><a href="followups.php?patient_id=<?=$patientId?>">Open scheduler</a></div><table><thead><tr><th>Recommended</th><th>Purpose</th><th>Dentist</th><th>Urgency</th><th>Status</th></tr></thead><tbody><?php foreach ($followUps as $row): ?><tr><td><?=e((string)$row['recommended_date'])?></td><td><?=e((string)$row['purpose'])?></td><td><?=e((string)$row['dentist_name'])?></td><td><?=e(module_status((string)$row['urgency']))?></td><td><?=e(module_status((string)$row['status']))?></td></tr><?php endforeach; ?></tbody></table></section>
<?php else: ?><section class="card table-wrap"><div class="card-head"><h2>Recalls</h2><a href="followups.php?patient_id=<?=$patientId?>">Open recall center</a></div><table><thead><tr><th>Due</th><th>Recall type</th><th>Status</th><th>Notes</th></tr></thead><tbody><?php foreach ($recalls as $row): ?><tr><td><?=e((string)$row['due_date'])?></td><td><?=e((string)$row['recall_type'])?></td><td><?=e(module_status((string)$row['status']))?></td><td><?=e((string)$row['notes'])?></td></tr><?php endforeach; ?></tbody></table></section><?php endif; ?>

<?php elseif ($tab === 'billing'): ?>
<?php if ($section === 'summary'): ?><section class="patient-overview-grid"><article class="stat-card"><span>Outstanding balance</span><strong>₱<?=number_format($balance,2)?></strong><small>Across open invoices</small></article><article class="stat-card"><span>Invoices</span><strong><?=count($invoices)?></strong><small>Recorded account items</small></article><article class="stat-card"><span>Payments</span><strong><?=count($payments)?></strong><small>Net retained ₱<?=number_format($netPaymentsRetained,2)?></small></article><article class="stat-card"><span>Insurance</span><strong><?=count($insurance)?></strong><small>Coverage records</small></article></section>
<?php elseif ($section === 'estimates'): ?><section><h2>Treatment estimates</h2><div class="module-card-grid"><?php foreach ($plans as $row): ?><article class="module-card"><span class="badge"><?=e(module_status((string)$row['status']))?></span><h3><?=e((string)$row['title'])?></h3><strong>₱<?=number_format((float)$row['estimate_total'],2)?></strong></article><?php endforeach; ?></div></section>
<?php elseif ($section === 'payments'): ?><section class="card table-wrap"><h2>Payment ledger</h2><table><thead><tr><th>Date</th><th>Invoice</th><th>Source / Method</th><th>Reference</th><th>Gross</th><th>Returned</th><th>Net</th><th>Status</th></tr></thead><tbody><?php foreach ($payments as $row): $returned=(float)($row['adjustment_total']??0);$net=max(0,(float)$row['amount']-$returned);?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$row['created_at'])))?></td><td><?=e((string)$row['invoice_no'])?></td><td><?=e(module_status((string)($row['source_type']??'patient')))?> · <?=e(module_status((string)$row['method']))?></td><td><?=e((string)($row['reference_no']?:'—'))?></td><td>₱<?=number_format((float)$row['amount'],2)?></td><td>₱<?=number_format($returned,2)?></td><td><strong>₱<?=number_format($net,2)?></strong></td><td><?=e(module_status((string)($row['status']??'posted')))?></td></tr><?php endforeach;if(!$payments):?><tr><td colspan="8" class="muted">No payments recorded.</td></tr><?php endif;?></tbody></table></section><?php if($paymentAdjustments):?><section class="card table-wrap"><h2>Refund and reversal history</h2><table><thead><tr><th>Date</th><th>Invoice</th><th>Type</th><th>Method</th><th>Reference</th><th>Amount</th><th>Status</th><th>Control trail</th><th>Reason</th></tr></thead><tbody><?php foreach($paymentAdjustments as $row):?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)($row['processed_at']??$row['approved_at']??$row['requested_at']))))?></td><td><?=e((string)$row['invoice_no'])?></td><td><?=e(module_status((string)$row['adjustment_type']))?></td><td><?=e(module_status((string)$row['method']))?></td><td><?=e((string)($row['reference_no']?:'—'))?></td><td>₱<?=number_format((float)$row['amount'],2)?></td><td><?=e(module_status((string)$row['status']))?></td><td><small>Requested: <?=e($row['requester']?:'—')?><?php if(!empty($row['approver'])):?><br>Approved: <?=e($row['approver'])?><?php endif;?><?php if(!empty($row['processor'])):?><br>Processed: <?=e($row['processor'])?><?php endif;?></small></td><td><?=e((string)$row['reason'])?></td></tr><?php endforeach;?></tbody></table></section><?php endif;?>
<?php elseif ($section === 'insurance'): ?><section class="grid-2"><div class="card"><h2>Insurance and HMO</h2><?php foreach ($insurance as $row): ?><article class="timeline-item"><h4><?=e((string)$row['provider'])?></h4><p><?=e((string)$row['plan_name'])?> · Member <?=e((string)$row['member_no'])?> · <?=!empty($row['is_active'])?'Active':'Inactive'?></p></article><?php endforeach; ?></div><div class="card"><h2>Claims</h2><?php foreach ($claims as $row): ?><article class="timeline-item"><h4><?=e((string)($row['claim_no'] ?: 'Draft claim'))?></h4><p><?=e(module_status((string)$row['status']))?> · ₱<?=number_format((float)$row['claimed_amount'],2)?></p></article><?php endforeach; ?></div></section>
<?php else: ?><section class="card table-wrap"><h2><?= $section==='ledger'?'Patient ledger':'Invoices' ?></h2><table><thead><tr><th>Date</th><th>Invoice</th><th>Description</th><th>Amount</th><th>Paid</th><th>Balance</th><th>Status</th></tr></thead><tbody><?php foreach ($invoices as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><?=e((string)$row['invoice_no'])?></td><td><?=e((string)$row['description'])?></td><td>₱<?=number_format((float)$row['amount'],2)?></td><td>₱<?=number_format((float)$row['paid_amount'],2)?></td><td>₱<?=number_format(max(0,(float)$row['amount']-(float)$row['paid_amount']),2)?></td><td><?=e(module_status((string)$row['status']))?></td></tr><?php endforeach; ?></tbody></table></section><?php endif; ?>

<?php elseif ($tab === 'documents'): ?>
<?php if ($section === 'consents'): ?><section class="card table-wrap"><div class="card-head"><h2>Consent records</h2><a href="consents.php?patient_id=<?=$patientId?>">Manage consents</a></div><table><thead><tr><th>Date</th><th>Consent</th><th>Version</th><th>Signer</th><th>Status</th></tr></thead><tbody><?php foreach ($consents as $row): ?><tr><td><?=e(date('M j, Y',strtotime((string)$row['created_at'])))?></td><td><?=e((string)$row['consent_type'])?></td><td><?=e((string)$row['version_no'])?></td><td><?=e((string)$row['signer_name'])?></td><td><?=e(module_status((string)$row['status']))?></td></tr><?php endforeach; ?></tbody></table></section>
<?php else: ?><section><div class="toolbar"><div><strong><?=e($secondaryTabs['documents'][$section])?></strong><span class="muted">Protected patient files.</span></div><a class="btn primary" href="documents.php?patient_id=<?=$patientId?>"><?= task_context_action_allowed('documents.upload') ? 'Manage files' : 'View files' ?></a></div><div class="module-card-grid"><?php foreach ($documents as $row): $category = strtolower((string)$row['category']); $show = match($section) { 'clinical_images' => str_contains($category,'image') || str_contains($category,'x-ray') || str_contains($category,'xray') || str_contains($category,'photo') || str_contains($category,'panoramic'), 'clearance' => str_contains($category,'clearance') || str_contains($category,'medical'), 'forms' => str_contains($category,'form'), 'letters' => str_contains($category,'letter') || str_contains($category,'referral'), 'exports' => str_contains($category,'export') || str_contains($category,'record'), default => true }; if (!$show) continue; ?><article class="module-card"><h3><?=e((string)$row['category'])?></h3><p><?=e((string)$row['file_name'])?></p><a href="download_document.php?id=<?=(int)$row['id']?>">Open file</a></article><?php endforeach; ?></div></section><?php endif; ?>

<?php elseif ($tab === 'communications'): ?>
<?php $channelFilter = $section === 'all' ? null : $section; ?><section class="card"><div class="card-head"><div><h2>Communication history</h2><p>Emails, calls, messages, and portal activity.</p></div><a class="btn primary" href="communications.php?patient_id=<?=$patientId?>">Log communication</a></div><div class="timeline-list"><?php foreach ($communications as $row): if ($channelFilter && (string)$row['channel'] !== $channelFilter) continue; ?><article class="timeline-item"><h4><?=e(module_status((string)$row['channel']))?> · <?=e((string)$row['subject'])?></h4><p><?=nl2br(e((string)$row['summary']))?></p><small><?=e(date('M j, Y g:i A',strtotime((string)$row['communicated_at'])))?> · <?=e(module_status((string)($row['delivery_status'] ?? 'recorded')))?></small></article><?php endforeach; ?></div></section>
<?php endif; ?>

<?php if ($advanced && $canManagePatient): ?><dialog id="guardian-form" class="wide-dialog"><form method="post" class="form-grid"><button type="button" class="dialog-close" data-close>×</button><h2 class="wide">Add guardian for verification</h2><div class="alert warning wide">Adding a guardian does not grant consent or record-release authority. An Administrator must verify identity, relationship, and authority before either permission is activated.</div><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="add_guardian"><input type="hidden" name="patient_id" value="<?=$patientId?>"><label>Name<input name="name" required></label><label>Relationship<input name="relationship"></label><label>Mobile<input name="mobile"></label><label>Email<input type="email" name="email"></label><label class="wide">Address<textarea name="address"></textarea></label><button class="btn primary">Save pending guardian</button></form></dialog><?php endif; ?>
<?php if ($advanced && $canVerifyMedical): ?><dialog id="alert-form" class="wide-dialog"><form method="post" class="form-grid"><button type="button" class="dialog-close" data-close>×</button><h2 class="wide">Add verified dental treatment alert</h2><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="add_alert"><input type="hidden" name="patient_id" value="<?=$patientId?>"><label>Alert type<input name="alert_type" required placeholder="Severe allergy, anticoagulant use"></label><label>Severity<select name="severity"><option value="information">Information</option><option value="caution">Caution</option><option value="critical">Critical</option></select></label><label class="wide">Description<textarea name="description" required></textarea></label><button class="btn primary">Activate verified alert</button></form></dialog><?php endif; ?>
<?php if ($advanced && $canMedicalHistory): ?><dialog id="medical-form" class="wide-dialog"><form method="post" class="form-grid"><button type="button" class="dialog-close" data-close>×</button><h2 class="wide"><?=$canVerifyMedical?'Verify dental treatment safety and dental history':'Record patient-reported update'?></h2><?php if(!$canVerifyMedical):?><div class="alert warning wide">This entry will remain pending and will not change the active clinical alert until a dentist verifies it.</div><?php endif;?><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="save_medical"><input type="hidden" name="patient_id" value="<?=$patientId?>"><label class="wide">Allergies<textarea name="allergies"><?=e((string)($latestMedical['allergies'] ?? ''))?></textarea></label><label class="wide">Current medicines relevant to dental care<textarea name="medications"><?=e((string)($latestMedical['medications'] ?? ''))?></textarea></label><label class="wide">Health conditions, surgeries, and clearances relevant to dental care<textarea name="conditions"><?=e((string)($latestMedical['conditions'] ?? ''))?></textarea></label><label class="wide">Dental history and concerns<textarea name="dental_history"><?=e((string)($latestMedical['dental_history'] ?? ''))?></textarea></label><?php if($canVerifyMedical):?><label class="wide">Verification note<textarea name="verification_note" required placeholder="Record how the dental-safety history was reviewed with the patient and any clarification made."></textarea></label><?php endif;?><button class="btn primary"><?=$canVerifyMedical?'Verify and activate':'Save for dentist review'?></button></form></dialog><?php endif; ?>
<?php render_footer(); ?>
