<?php

declare(strict_types=1);

require DENTAL_ROOT . '/app/bootstrap.php';
require_login();
require_roles(['super_admin']);
require DENTAL_ROOT . '/app/layout.php';
require_once DENTAL_ROOT . '/app/production_readiness.php';
require_once DENTAL_ROOT . '/app/release_candidate.php';

$pdo = db();
$readOnlyPreview = function_exists('task_preview_mode') && task_preview_mode();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    try {
        verify_csrf();
        $action = (string) ($_POST['action'] ?? '');
        if ($readOnlyPreview) {
            throw new RuntimeException('Task View preview is read-only. Return to the signed-in Superuser workspace before recording production actions.');
        }
        if ($action === 'run_automated_validation') {
            $validation = dental_automated_validation_record($pdo);
            $blockedCount = (int)($validation['snapshot']['counts']['blocked'] ?? 0);
            audit_required('automated_production_validation_run', 'system', null, [
                'version'=>app_release_version(),
                'ready'=>!empty($validation['snapshot']['ready']),
                'blocked'=>$blockedCount,
                'fingerprint'=>(string)($validation['snapshot']['fingerprint'] ?? ''),
            ]);
            flash($blockedCount === 0 ? 'success' : 'error', $blockedCount === 0
                ? 'Automated production validation passed. Only the three clinic-specific live confirmations remain.'
                : $blockedCount . ' automated technical check(s) remain blocked. Review the exact results below.');
            header('Location: production_monitoring.php#automated-validation');
            exit;
        }
        if ($action === 'resume_automatic_release') {
            setting_set('production_acceptance', 'release_candidate_manual_hold', '0');
            flash('success', 'Automatic production unlock resumed. DentalCare will unlock installer generation when every current gate passes.');
            header('Location: production_monitoring.php#release-candidate');
            exit;
        }
        if ($action === 'cleanup_emergency_files') {
            if ((string)($_POST['confirmation'] ?? '') !== 'REMOVE EMERGENCY FILES') {
                throw new RuntimeException('Type REMOVE EMERGENCY FILES exactly to remove the known temporary diagnostic entry points.');
            }
            $result = dental_release_candidate_cleanup_emergency_files();
            if (!empty($result['failed'])) {
                throw new RuntimeException('Could not remove: ' . implode(', ', (array)$result['failed']) . '. Check root file permissions.');
            }
            audit_required('release_candidate_emergency_files_removed', 'system', null, ['files'=>(array)$result['removed']]);
            flash('success', empty($result['removed']) ? 'No emergency diagnostic files were present.' : 'Removed emergency diagnostic files: ' . implode(', ', (array)$result['removed']) . '.');
            header('Location: production_monitoring.php#release-candidate');
            exit;
        }
        if ($action === 'approve_release_candidate') {
            $approval = dental_release_candidate_record_approval($pdo, (string)($_POST['confirmation'] ?? ''), (string)($_POST['approval_note'] ?? ''));
            audit_required('release_candidate_approved', 'system', null, [
                'version'=>(string)($approval['version'] ?? ''),
                'evidence_sha256'=>(string)($approval['evidence_sha256'] ?? ''),
            ]);
            flash('success', 'DentalCare ' . (string)($approval['version'] ?? '') . ' is approved as the production release candidate. Production installer generation is now available while all gates remain clear.');
            header('Location: production_monitoring.php#release-candidate');
            exit;
        }
        if ($action === 'revoke_release_candidate') {
            if ((string)($_POST['confirmation'] ?? '') !== 'REVOKE') throw new RuntimeException('Type REVOKE exactly to remove the approval.');
            dental_release_candidate_revoke();
            audit_required('release_candidate_approval_revoked', 'system', null, ['version'=>app_release_version()]);
            flash('success', 'Release candidate approval was revoked. Production installer generation is locked again.');
            header('Location: production_monitoring.php#release-candidate');
            exit;
        }
        if ($action === 'record_role_acceptance') {
            $role = trim((string) ($_POST['role_code'] ?? ''));
            $status = trim((string) ($_POST['acceptance_status'] ?? 'not_tested'));
            $note = trim((string) ($_POST['acceptance_note'] ?? ''));
            if ($status === 'passed') {
                $prerequisites = dental_production_role_prerequisites($pdo);
                $rolePrerequisite = (array)($prerequisites[$role] ?? ['ready'=>false,'detail'=>'Role prerequisites could not be verified.']);
                if (empty($rolePrerequisite['ready'])) {
                    throw new RuntimeException('This role cannot be marked Passed while its prerequisites are blocked: ' . (string)($rolePrerequisite['detail'] ?? 'Review the role setup.'));
                }
            }
            dental_production_record_role_signoff($role, $status, $note, $pdo);
            audit_required('production_role_acceptance_recorded', 'system', null, [
                'role' => $role,
                'status' => $status,
                'note' => mb_substr($note, 0, 500),
            ]);
            flash('success', 'Production acceptance result saved for ' . (dental_production_role_codes()[$role] ?? $role) . '.');
            header('Location: production_monitoring.php#role-acceptance');
            exit;
        }
        if ($action === 'record_monitor_review') {
            $reviewRecord = dental_release_candidate_record_monitor_review($pdo);
            audit_required('production_monitor_reviewed', 'system', null, [
                'version' => app_release_version(),
                'fingerprint' => (string)($reviewRecord['fingerprint'] ?? ''),
            ]);
            flash('success', 'Production monitor review recorded for the current clear check state. It will expire automatically if a check becomes blocked or changes status.');
            header('Location: production_monitoring.php#monitor-review');
            exit;
        }
        if ($action === 'acknowledge_monitor_history') {
            $kind = (string) ($_POST['history_kind'] ?? '');
            $confirmation = trim((string) ($_POST['confirmation'] ?? ''));
            $allowed = [
                'runtime_errors' => ['ERRORS REVIEWED'],
                'slow_requests' => ['REQUESTS REVIEWED', 'SLOW REQUESTS REVIEWED'],
            ];
            if (!isset($allowed[$kind]) || !in_array($confirmation, $allowed[$kind], true)) {
                throw new RuntimeException('Enter the displayed confirmation exactly after reviewing and resolving the listed incidents.');
            }

            $now = date(DATE_ATOM);
            $cursor = dental_production_monitor_cursor_snapshot($kind);
            $encodedCursor = json_encode($cursor, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            if (!is_string($encodedCursor) || $encodedCursor === '') {
                throw new RuntimeException('DentalCare could not create the protected monitoring checkpoint. No incident was marked reviewed.');
            }
            setting_set('production_acceptance', $kind . '_review_cursor', $encodedCursor);
            // Keep the legacy timestamp for older pages while the byte-position
            // cursor remains authoritative for current monitoring.
            setting_set('production_acceptance', $kind . '_reviewed_through', $now);
            setting_set('production_acceptance', 'last_monitor_reviewed_at', '');
            setting_set('production_acceptance', 'last_monitor_review_fingerprint', '');
            setting_set('production_acceptance', 'last_monitor_review_version', '');
            audit_required('production_monitor_history_acknowledged', 'system', null, [
                'kind' => $kind,
                'reviewed_through' => $now,
                'cursor_files' => (array) ($cursor['files'] ?? []),
            ]);
            flash('success', $kind === 'runtime_errors'
                ? 'Resolved historical runtime incidents were checkpointed. Multiline stack traces are no longer counted as separate errors. Any newly appended incident will appear automatically.'
                : 'Resolved historical request telemetry was checkpointed. Any newly appended slow request or HTTP 500 response will appear automatically.');
            header('Location: production_monitoring.php#' . ($kind === 'runtime_errors' ? 'runtime-errors' : 'request-telemetry'));
            exit;
        }
        if ($action === 'save_storage_quota_snapshot') {
            $usedGb = (float)($_POST['account_used_gb'] ?? -1);
            $totalGb = (float)($_POST['account_total_gb'] ?? 0);
            $quota = dental_storage_record_quota_snapshot($usedGb, $totalGb);
            audit_required('storage_quota_snapshot_recorded', 'system', null, [
                'used_bytes'=>(int)($quota['used_bytes'] ?? 0),
                'total_bytes'=>(int)($quota['total_bytes'] ?? 0),
                'available_bytes'=>(int)($quota['available_bytes'] ?? 0),
            ]);
            flash('success', 'The cPanel quota snapshot was saved. DentalCare now reports account-level capacity separately from the shared server filesystem.');
            header('Location: production_monitoring.php#storage-health');
            exit;
        }
        if ($action === 'clear_storage_quota_snapshot') {
            if ((string)($_POST['confirmation'] ?? '') !== 'CLEAR STORAGE SNAPSHOT') {
                throw new RuntimeException('Type CLEAR STORAGE SNAPSHOT exactly.');
            }
            dental_storage_clear_quota_snapshot();
            audit_required('storage_quota_snapshot_cleared', 'system', null, []);
            flash('success', 'The saved cPanel quota snapshot was cleared. DentalCare will show the shared-filesystem measurement as informational only.');
            header('Location: production_monitoring.php#storage-health');
            exit;
        }
        if ($action === 'repair_safe_operational_state') {
            if ((string)($_POST['confirmation'] ?? '') !== 'REPAIR SAFE STALE STATE') {
                throw new RuntimeException('Type REPAIR SAFE STALE STATE exactly before applying the audited cleanup.');
            }
            $reason = trim((string)($_POST['repair_reason'] ?? ''));
            $repair = dental_repair_safe_operational_state($pdo, (int)(current_user()['id'] ?? 0), $reason);
            audit_required('production_safe_operational_state_repaired', 'system', null, $repair + ['reason'=>$reason]);
            $message = (int)$repair['chairs_released'] . ' finalized chair assignment(s) released and '
                . (int)$repair['empty_cashier_sessions_closed'] . ' empty stale cashier session(s) closed.';
            if ((int)$repair['cashier_sessions_requiring_reconciliation'] > 0) {
                $message .= ' ' . (int)$repair['cashier_sessions_requiring_reconciliation'] . ' cashier session(s) still contain financial activity and were left open for reconciliation.';
            }
            if ((int)($repair['skipped'] ?? 0) > 0) {
                $message .= ' ' . (int)$repair['skipped'] . ' record(s) were already corrected or changed and were skipped.';
            }
            $repairErrors = array_values(array_filter(array_map('strval', (array)($repair['errors'] ?? []))));
            if ($repairErrors) {
                flash('warning', $message . ' ' . count($repairErrors) . ' record(s) were left unchanged: ' . implode(' ', array_slice($repairErrors, 0, 3)));
            } else {
                flash('success', $message);
            }
            header('Location: production_monitoring.php#operational-state-repair');
            exit;
        }
        throw new RuntimeException('Unsupported production-monitoring action.');
    } catch (Throwable $exception) {
        flash('error', $exception->getMessage());
        header('Location: production_monitoring.php');
        exit;
    }
}

$snapshot = dental_production_health_snapshot($pdo);
$checks = (array) ($snapshot['checks'] ?? []);
$counts = (array) ($snapshot['counts'] ?? []);
$roles = (array) ($snapshot['roles'] ?? []);
$roleLabels = dental_production_role_codes();
$lastReviewed = (string) setting_get('production_acceptance', 'last_monitor_reviewed_at', '');
$blocked = (int) ($counts['blocked'] ?? 0);
$review = (int) ($counts['review'] ?? 0);
$notConfigured = (int) ($counts['not_configured'] ?? 0);
$readyForSignoff = $blocked === 0;
$readyForMonitorReview = $blocked === 0;
$releaseCandidateSnapshot = dental_release_candidate_snapshot($pdo);
$releaseCandidateApproved = dental_release_candidate_is_approved($pdo);
$releaseCandidateApproval = dental_release_candidate_approval();
$releaseCandidateBlockers = (array)($releaseCandidateSnapshot['blockers'] ?? []);
$releaseCandidateEmergencyFiles = (array)($releaseCandidateSnapshot['emergency_files'] ?? []);
$automatedValidation = (array)($releaseCandidateSnapshot['automated_validation'] ?? []);
$blockedChecks = (array)($automatedValidation['blocked'] ?? []);
$incompleteGates = array_values(array_filter((array)($releaseCandidateSnapshot['gates'] ?? []), static fn(array $gate): bool => empty($gate['ready'])));
$automaticReleaseHold = (string)setting_get('production_acceptance', 'release_candidate_manual_hold', '0') === '1';
$storageHealth = dental_storage_health_snapshot();
$storageQuota = (array)($storageHealth['quota'] ?? []);
$storageManaged = (array)($storageHealth['managed'] ?? []);
try {
    $operationalState = dental_operational_state_snapshot($pdo);
} catch (Throwable $operationalException) {
    $operationalReference = function_exists('dental_operational_log_failure')
        ? dental_operational_log_failure('Production Monitor operational-state snapshot failed', $operationalException)
        : dental_request_reference();
    $operationalState = [
        'chairs'=>[],
        'cashier_empty'=>[],
        'cashier_requires_reconciliation'=>[],
        'counts'=>['chairs'=>0,'cashier_empty'=>0,'cashier_requires_reconciliation'=>0],
        'errors'=>['Operational-state inspection could not complete. Reference: ' . $operationalReference . '.'],
    ];
}
$operationalCounts = (array)($operationalState['counts'] ?? []);
$operationalErrors = array_values(array_filter(array_map('strval', (array)($operationalState['errors'] ?? []))));

function production_monitor_status_label(string $status): string
{
    return match ($status) {
        'pass' => 'PASS',
        'blocked' => 'BLOCKED',
        'not_configured' => 'NOT CONFIGURED',
        default => 'REVIEW',
    };
}

function production_monitor_badge_class(string $status): string
{
    return match ($status) {
        'pass' => 'success',
        'blocked' => 'danger',
        'not_configured' => 'warning',
        default => 'warning',
    };
}

/**
 * Production Monitor is loaded without app/module_helpers.php. Keep the
 * operational-state table self-contained so a historical queue row cannot
 * crash the page merely while its status label is being rendered.
 */
function production_monitor_stage_label(?string $status): string
{
    $status = trim((string) $status);
    if ($status === '') return 'Unknown stage';
    return ucwords(str_replace(['_', '-'], ' ', $status));
}

render_header('Production Monitor');
?>
<section class="admin-hero card">
    <div>
        <span class="eyebrow">Production validation</span>
        <h2>Automated Production Readiness</h2>
        <p>DentalCare validates technical safeguards automatically. You only confirm what requires the clinic's actual server and staff: live email delivery, one real workflow, and one restore drill.</p>
        <div class="status-actions">
            <a class="btn ghost" href="backup_restore.php">Backup &amp; Restore</a>
            <a class="btn ghost" href="email_settings.php">Email Test</a>
            <a class="btn ghost" href="visit_exceptions.php">Reconciliation Center</a>
            <a class="btn primary" href="system_setup.php?tab=updates">Updates &amp; Database</a>
        </div>
    </div>
    <div class="admin-hero-icon"><?= dental_icon('chart') ?></div>
</section>

<?php if ($readOnlyPreview): ?><div class="alert warning"><strong>Read-only Task View.</strong> Production validation results are visible, but system actions are hidden. Return to the signed-in Superuser workspace to run or confirm checks.</div><?php endif; ?>
<section class="card" id="release-candidate">
    <div class="card-head">
        <div><span class="eyebrow">Version <?= e(app_release_version()) ?></span><h2>Production readiness status</h2><p>Installer generation unlocks automatically only while all automated checks and the three clinic-specific confirmations remain current.</p></div>
        <span class="badge <?= $releaseCandidateApproved ? 'success' : (!empty($releaseCandidateSnapshot['ready']) ? 'warning' : 'danger') ?>"><?= $releaseCandidateApproved ? 'PRODUCTION VALIDATED' : (!empty($releaseCandidateSnapshot['ready']) ? 'ON HOLD' : 'BLOCKED') ?></span>
    </div>
    <?php if ($releaseCandidateApproved): ?>
        <div class="alert success"><strong>Production validation is complete.</strong> DentalCare automatically bound installer generation to the current evidence at <?= !empty($releaseCandidateApproval['approved_at']) ? e(date('M j, Y g:i A', strtotime((string)$releaseCandidateApproval['approved_at']))) : 'the current check time' ?>. Any new blocker automatically locks production packaging again.</div>
    <?php elseif (!empty($releaseCandidateSnapshot['ready']) && $automaticReleaseHold): ?>
        <div class="alert warning"><strong>Every gate passes, but automatic release is paused.</strong> Resume automatic unlock to allow production installer generation.</div>
        <?php if (!$readOnlyPreview): ?><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="resume_automatic_release"><button class="btn primary" type="submit">Resume automatic production unlock</button></form><?php endif; ?>
    <?php else: ?>
        <div class="alert error"><strong><?= count($releaseCandidateBlockers) ?> gate<?= count($releaseCandidateBlockers)===1?'':'s' ?> blocked.</strong> Technical checks are automatic. Complete only the failed rows shown below.</div>
    <?php endif; ?>
    <div class="table-wrap"><table><thead><tr><th>Gate</th><th>Status</th><th>Metric</th><th>Requirement</th><th></th></tr></thead><tbody>
    <?php foreach ((array)$releaseCandidateSnapshot['gates'] as $gate): ?>
        <tr><td><strong><?= e((string)$gate['title']) ?></strong></td><td><span class="badge <?= !empty($gate['ready']) ? 'success' : 'danger' ?>"><?= !empty($gate['ready']) ? 'PASS' : 'BLOCKED' ?></span></td><td><?= e((string)($gate['metric'] ?? '')) ?></td><td><?= e((string)$gate['detail']) ?></td><td><?php if (!empty($gate['href'])): ?><a class="btn compact ghost" href="<?= e((string)$gate['href']) ?>"><?= e((string)($gate['actionLabel'] ?? 'Complete')) ?></a><?php endif; ?></td></tr>
    <?php endforeach; ?>
    </tbody></table></div>
    <?php if (!$readOnlyPreview && $releaseCandidateEmergencyFiles): ?>
        <details class="compact-details"><summary>Remove temporary emergency files</summary><div class="compact-details-body"><p>Detected: <code><?= e(implode(', ', $releaseCandidateEmergencyFiles)) ?></code></p><form method="post" class="form-grid"><input type="hidden" name="csrf" value="<?= e(csrf_token()) ?>"><input type="hidden" name="action" value="cleanup_emergency_files"><label class="wide">Confirmation<input name="confirmation" placeholder="REMOVE EMERGENCY FILES" required></label><div class="wide"><button class="btn danger" type="submit">Remove known emergency files</button></div></form></div></details>
    <?php endif; ?>
    <?php if (!$readOnlyPreview && $releaseCandidateApproved): ?>
        <details class="compact-details"><summary>Temporarily pause production packaging</summary><div class="compact-details-body"><form method="post" class="form-grid"><input type="hidden" name="csrf" value="<?= e(csrf_token()) ?>"><input type="hidden" name="action" value="revoke_release_candidate"><label>Confirmation<input name="confirmation" placeholder="REVOKE" required></label><div><button class="btn danger" type="submit">Pause automatic production unlock</button></div></form></div></details>
    <?php endif; ?>
</section>
<section class="card production-completion-center" id="completion-path">
    <div class="card-head"><div><span class="eyebrow">Ordered completion path</span><h2>Finish only what is still required</h2><p>Passed gates are automatically skipped. Complete the remaining steps in order; no production approval is granted until the evidence is real and current.</p></div><span class="badge <?= empty($incompleteGates)?'success':'warning' ?>"><?= count($incompleteGates) ?> remaining</span></div>
    <ol class="production-completion-steps">
    <?php foreach ((array)($releaseCandidateSnapshot['gates'] ?? []) as $gate): $gateReady=!empty($gate['ready']); ?>
        <li class="<?= $gateReady?'complete':'pending' ?>"><span><?= $gateReady?'✓':'!' ?></span><div><strong><?= e((string)$gate['title']) ?></strong><small><?= $gateReady?'Already complete — skipped automatically.':e((string)$gate['detail']) ?></small></div><?php if(!$gateReady&&!empty($gate['href'])):?><a class="btn compact <?= $gate['key']==='production_health'?'primary':'ghost' ?>" href="<?=e((string)$gate['href'])?>"><?=e((string)($gate['actionLabel']??'Complete'))?></a><?php endif;?></li>
    <?php endforeach; ?>
    </ol>
</section>

<section class="card" id="operational-state-repair">
    <div class="card-head">
        <div><span class="eyebrow">Historical operational state</span><h2>Stale chair and cashier cleanup</h2><p>These rows can remain after the visible transaction is finished or removed. DentalCare separates records that are safe to repair from cashier sessions that contain financial activity.</p></div>
        <span class="badge <?= ((int)($operationalCounts['chairs']??0)+(int)($operationalCounts['cashier_empty']??0)+(int)($operationalCounts['cashier_requires_reconciliation']??0))===0?'success':'warning' ?>"><?= (int)($operationalCounts['chairs']??0)+(int)($operationalCounts['cashier_empty']??0)+(int)($operationalCounts['cashier_requires_reconciliation']??0) ?> found</span>
    </div>
    <?php if ($operationalErrors): ?>
        <div class="alert error"><strong>Operational-state inspection needs attention.</strong> <?= e(implode(' ', $operationalErrors)) ?> No chair or cashier record was changed by the inspection.</div>
    <?php endif; ?>
    <div class="stats mini-stats">
        <article><strong><?= (int)($operationalCounts['chairs']??0) ?></strong><span>Finalized visits retaining chairs</span></article>
        <article><strong><?= (int)($operationalCounts['cashier_empty']??0) ?></strong><span>Empty stale cashier sessions</span></article>
        <article><strong><?= (int)($operationalCounts['cashier_requires_reconciliation']??0) ?></strong><span>Cashier sessions requiring reconciliation</span></article>
    </div>
    <?php if ((int)($operationalCounts['chairs']??0)>0): ?>
        <div class="alert warning"><strong>Finalized visits still retain chair fields.</strong> The repair clears the queue and linked appointment chair, records chair release, preserves completed/cancelled visits, and otherwise restores the visit to waiting for billing or completed no-payment checkout.</div>
        <div class="table-wrap operational-state-table"><table><thead><tr><th>Queue</th><th>Patient</th><th>Current stage</th><th>Chair</th></tr></thead><tbody><?php foreach(array_slice((array)($operationalState['chairs']??[]),0,25) as $row): ?><tr><td><?=e((string)($row['queue_no']??('#'.(int)($row['queue_entry_id']??0))))?></td><td><?=e(trim((string)($row['patient_name']??''))?:'Patient record')?></td><td><?=e(production_monitor_stage_label((string)($row['queue_status']??'')))?></td><td><?=e((string)($row['chair_name']??('Chair #'.(int)($row['chair_id']??0))))?></td></tr><?php endforeach; ?></tbody></table></div>
    <?php endif; ?>
    <?php if ((int)($operationalCounts['cashier_empty']??0)>0): ?>
        <div class="alert info"><strong>Empty stale cashier sessions are not payment transactions.</strong> They are drawer-session rows left open for more than 18 hours with no payment, no checkout, and no locked patient. They can be closed safely with zero variance.</div>
    <?php endif; ?>
    <?php if ((int)($operationalCounts['cashier_requires_reconciliation']??0)>0): ?>
        <div class="alert warning"><strong>Some stale cashier sessions contain financial evidence.</strong> DentalCare will not auto-close them. Open Billing and reconcile the drawer/session normally.</div>
    <?php endif; ?>
    <?php if (!$readOnlyPreview && ((int)($operationalCounts['chairs']??0)>0 || (int)($operationalCounts['cashier_empty']??0)>0)): ?>
        <details class="compact-details" open><summary>Repair safe stale state</summary><div class="compact-details-body">
            <form method="post" class="form-grid">
                <input type="hidden" name="csrf" value="<?=e(csrf_token())?>">
                <input type="hidden" name="action" value="repair_safe_operational_state">
                <label class="wide">Audited reason<textarea name="repair_reason" minlength="10" required>Clear historical chair assignments and abandoned empty cashier sessions after production reconciliation.</textarea></label>
                <label class="wide">Confirmation<input name="confirmation" required placeholder="REPAIR SAFE STALE STATE"></label>
                <div class="wide"><button class="btn primary" type="submit">Repair safe stale records</button></div>
            </form>
        </div></details>
    <?php elseif (((int)($operationalCounts['chairs']??0)+(int)($operationalCounts['cashier_empty']??0)+(int)($operationalCounts['cashier_requires_reconciliation']??0))===0): ?>
        <div class="alert success">No stale chair assignment or cashier session is currently detected.</div>
    <?php endif; ?>
</section>

<section class="card" id="automated-validation">
    <div class="card-head"><div><span class="eyebrow">Technical validation</span><h2>Automated production checks</h2><p>These checks cover role routes, permissions, database transactions, patient-ledger privacy, adaptive encounter safety, backup verification, update recovery, runtime health, and clean packaging.</p></div><span class="badge <?=empty($blockedChecks)?'success':'danger'?>"><?=count($blockedChecks)?> blocked</span></div>
    <?php if(!$readOnlyPreview): ?><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="run_automated_validation"><button class="btn primary" type="submit">Run production validation</button></form><?php endif; ?>
    <div class="table-wrap"><table><thead><tr><th>Check</th><th>Status</th><th>Metric</th><th>Assessment</th></tr></thead><tbody><?php foreach((array)($automatedValidation['checks']??[]) as $check): ?><tr><td><strong><?=e((string)$check['title'])?></strong></td><td><span class="badge <?=!empty($check['ready'])?'success':'danger'?>"><?=!empty($check['ready'])?'PASS':'BLOCKED'?></span></td><td><?=e((string)($check['metric']??''))?></td><td><?=e((string)$check['detail'])?></td></tr><?php endforeach; ?></tbody></table></div>
</section>
<div class="alert <?= empty($blockedChecks) ? 'success' : 'error' ?>">
    <strong><?= empty($blockedChecks) ? 'All automated technical checks pass.' : count($blockedChecks) . ' automated technical check' . (count($blockedChecks)===1?'':'s') . ' blocked.' ?></strong>
    <?= empty($blockedChecks)
        ? ' No manual role-by-role signoff or separate monitor-review form is required. Complete only email delivery, one clinic workflow, and one restore confirmation.'
        : ' Resolve the exact blocked rows before accepting real clinic transactions or generating a production installer.' ?>
</div>

<section class="stats mini-stats">
    <?php stat_card('Passed', (int)($counts['pass'] ?? 0), 'Automated checks clear'); ?>
    <?php stat_card('Review', $review, 'Requires operational review'); ?>
    <?php stat_card('Blocked', $blocked, 'Must be corrected'); ?>
    <?php stat_card('Not configured', $notConfigured, 'Optional or incomplete services'); ?>
</section>

<section class="card" id="storage-health">
    <div class="card-head"><div><span class="eyebrow">Quota-aware storage</span><h2>Storage health</h2><p>DentalCare separates your cPanel account quota from PHP's shared-server filesystem measurement. Only a failed write probe or genuinely critical capacity can block production.</p></div><span class="badge <?=production_monitor_badge_class((string)($storageHealth['status']??'review'))?>"><?=production_monitor_status_label((string)($storageHealth['status']??'review'))?></span></div>
    <div class="alert <?=((string)($storageHealth['status']??'review'))==='blocked'?'error':(((string)($storageHealth['status']??'review'))==='pass'?'success':'warning')?>"><strong><?=e((string)($storageHealth['metric']??'Unknown'))?></strong> <?=e((string)($storageHealth['detail']??''))?></div>
    <div class="health-list">
        <div><span>Checked application path</span><strong><code><?=e((string)($storageHealth['checked_path']??DENTAL_ROOT))?></code></strong></div>
        <div><span>Protected write probe</span><strong class="<?=!empty($storageHealth['write_probe']['ready'])?'ok':'warn'?>"><?=!empty($storageHealth['write_probe']['ready'])?'Passed':'Failed'?></strong></div>
        <div><span>Shared filesystem available</span><strong><?=e(dental_storage_format_bytes((int)($storageHealth['filesystem']['free_bytes']??0)))?></strong></div>
        <div><span>Capacity source used for status</span><strong><?=((string)($storageHealth['source']??''))==='hosting_quota'?'Current cPanel quota snapshot':'Shared filesystem emergency threshold'?></strong></div>
    </div>
    <div class="table-wrap"><table><thead><tr><th>DentalCare-managed area</th><th>Measured size</th><th>Files</th><th>Path</th></tr></thead><tbody><?php foreach((array)($storageManaged['rows']??[]) as $row):?><tr><td><strong><?=e((string)$row['label'])?></strong><?=!empty($row['partial'])?' <span class="badge warning">PARTIAL SCAN</span>':''?></td><td><?=e(dental_storage_format_bytes((int)$row['bytes']))?></td><td><?=number_format((int)$row['files'])?></td><td><code><?=e((string)$row['path'])?></code></td></tr><?php endforeach;?></tbody></table></div>
    <?php if(!empty($storageManaged['partial'])):?><p class="muted">The directory scan stopped at its safety time or file limit. The displayed managed total is a lower bound and does not affect the quota result.</p><?php endif;?>
    <?php if(!$readOnlyPreview):?>
    <details class="compact-details" <?=empty($storageQuota['fresh'])?'open':''?>><summary>Record the current cPanel disk snapshot</summary><div class="compact-details-body"><p>Use the values shown in <strong>cPanel → Statistics</strong>. This optional snapshot expires after seven days so stale numbers cannot be treated as current capacity.</p><form method="post" class="inline-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="save_storage_quota_snapshot"><label>Used disk (GB)<input type="number" name="account_used_gb" step="0.01" min="0" value="<?=!empty($storageQuota['configured'])?e(number_format(((int)$storageQuota['used_bytes'])/1073741824,2,'.','')):''?>" required></label><label>Total quota (GB)<input type="number" name="account_total_gb" step="0.01" min="0.01" value="<?=!empty($storageQuota['configured'])?e(number_format(((int)$storageQuota['total_bytes'])/1073741824,2,'.','')):''?>" required></label><button class="btn primary" type="submit">Save current cPanel snapshot</button></form><?php if(!empty($storageQuota['configured'])):?><p class="muted">Recorded <?=e((string)($storageQuota['recorded_at']??''))?> by <?=e((string)($storageQuota['recorded_by']??''))?>.</p><form method="post" class="inline-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="clear_storage_quota_snapshot"><label>Confirmation<input name="confirmation" placeholder="CLEAR STORAGE SNAPSHOT" required></label><button class="btn danger" type="submit">Clear saved snapshot</button></form><?php endif;?></div></details>
    <?php endif;?>
</section>

<section class="card table-wrap" id="monitor-review">
    <div class="card-head"><div><h2>Runtime and operational health</h2><p>These live checks remain visible for diagnosis. The formal technical gate above evaluates blocking conditions automatically.</p></div></div>
    <table>
        <thead><tr><th>Category</th><th>Check</th><th>Status</th><th>Metric</th><th>Assessment</th><th></th></tr></thead>
        <tbody>
        <?php foreach ($checks as $check): ?>
            <tr>
                <td><?= e((string)$check['category']) ?></td>
                <td><strong><?= e((string)$check['title']) ?></strong></td>
                <td><span class="badge <?= e(production_monitor_badge_class((string)$check['status'])) ?>"><?= e(production_monitor_status_label((string)$check['status'])) ?></span></td>
                <td><?= e((string)($check['metric'] ?? '')) ?></td>
                <td><?= e((string)$check['detail']) ?></td>
                <td><?php if (!empty($check['href'])): ?><a class="btn compact ghost" href="<?= e((string)$check['href']) ?>"><?= e((string)($check['actionLabel'] ?? 'Review')) ?></a><?php endif; ?></td>
            </tr>
        <?php endforeach; ?>
        </tbody>
    </table>
</section>

<section class="card" id="role-acceptance">
    <div class="card-head"><div><h2>Automatic role capability matrix</h2><p>DentalCare verifies each role's required routes, tables, indexes, and permission boundaries automatically. Staff orientation may still be performed, but nine separate technical signoffs are no longer required.</p></div></div>
    <div class="admin-category-grid production-role-grid">
    <?php foreach ($roleLabels as $roleCode => $roleLabel): $prerequisite=(array)($roles[$roleCode]??['ready'=>false,'detail'=>'Prerequisite check unavailable.']); ?>
        <article class="admin-category card"><div class="admin-category-head"><span class="admin-category-icon"><?=dental_icon($roleCode==='patient'?'patient':($roleCode==='cashier'?'receipt':'shield'))?></span><div><h3><?=e($roleLabel)?></h3><p><?=e((string)$prerequisite['detail'])?></p></div></div><span class="badge <?=!empty($prerequisite['ready'])?'success':'danger'?>"><?=!empty($prerequisite['ready'])?'TECHNICAL PASS':'BLOCKED'?></span></article>
    <?php endforeach; ?>
    </div>
</section>

<div class="setup-grid">
<section class="card" id="runtime-errors">
    <div class="card-head"><div><h2>Recent protected runtime errors</h2><p>Only Superusers can access this summary. Full details remain in protected runtime logs.</p></div><span class="badge <?= empty($snapshot['errors']['count']) ? 'success' : 'warning' ?>"><?= (int)($snapshot['errors']['count'] ?? 0) ?></span></div>
    <?php if (!empty($snapshot['errors']['entries'])): ?><div class="production-log-list">
        <?php foreach ((array)$snapshot['errors']['entries'] as $entry): ?><article><strong><?= e((string)($entry['reference'] ?: 'No reference')) ?></strong><small><?= e((string)($entry['recorded_at'] ?? '')) ?><?=!empty($entry['recorded_at'])?' · ':''?><?= e((string)$entry['file']) ?></small><code><?= e((string)$entry['summary']) ?></code></article><?php endforeach; ?>
    </div><?php else: ?><p class="muted">No unreviewed fatal or uncaught request error was found.</p><?php endif; ?>
    <?php if(!$readOnlyPreview&&!empty($snapshot['errors']['count'])):?><details class="compact-details"><summary>Mark resolved historical errors reviewed</summary><div class="compact-details-body"><p>Use this only after the underlying defects are fixed. New errors after this checkpoint will appear again automatically.</p><form method="post" class="inline-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="acknowledge_monitor_history"><input type="hidden" name="history_kind" value="runtime_errors"><label>Confirmation<input name="confirmation" placeholder="ERRORS REVIEWED" required></label><button class="btn warning" type="submit">Start clean error-monitoring window</button></form></div></details><?php endif;?>
</section>
<section class="card" id="request-telemetry">
    <div class="card-head"><div><h2>Recent request telemetry</h2><p>Routes exceeding 2.5 seconds and HTTP 500 responses are recorded without request payloads or patient names.</p></div><span class="badge <?= empty($snapshot['performance']['count']) ? 'success' : 'warning' ?>"><?= (int)($snapshot['performance']['slow_count'] ?? 0) ?> slow · <?= (int)($snapshot['performance']['error_count'] ?? 0) ?> errors</span></div>
    <?php if (!empty($snapshot['performance']['entries'])): ?><div class="production-log-list">
        <?php foreach ((array)$snapshot['performance']['entries'] as $entry): ?><article><strong><?= e((string)($entry['route'] ?? 'unknown')) ?></strong><small><?= e((string)($entry['recorded_at'] ?? '')) ?> · HTTP <?= (int)($entry['status_code'] ?? 0) ?></small><code><?= e(number_format((float)($entry['elapsed_ms'] ?? 0),1)) ?> ms · <?= e(number_format(((int)($entry['peak_memory_bytes'] ?? 0))/1048576,2)) ?> MB</code></article><?php endforeach; ?>
    </div><?php else: ?><p class="muted">No unreviewed slow or failed request has been recorded.</p><?php endif; ?>
    <?php if(!$readOnlyPreview&&!empty($snapshot['performance']['count'])):?><details class="compact-details"><summary>Mark resolved historical request telemetry reviewed</summary><div class="compact-details-body"><p>Use this after profiling or fixing the listed slow routes and HTTP 500 responses. New telemetry appended after this checkpoint will appear again.</p><form method="post" class="inline-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="acknowledge_monitor_history"><input type="hidden" name="history_kind" value="slow_requests"><label>Confirmation<input name="confirmation" placeholder="REQUESTS REVIEWED" required></label><button class="btn warning" type="submit">Start clean request-monitoring window</button></form></div></details><?php endif;?>
</section>
</div>

<style>
.production-role-grid{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}.production-completion-steps{display:grid;gap:.65rem;margin:0;padding:0;list-style:none}.production-completion-steps li{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:.8rem;padding:.8rem;border:1px solid var(--border);border-radius:.75rem}.production-completion-steps li>span{display:grid;place-items:center;width:28px;height:28px;border-radius:999px;font-weight:900}.production-completion-steps li.complete>span{background:#dcfce7;color:#166534}.production-completion-steps li.pending>span{background:#fee2e2;color:#991b1b}.production-completion-steps small{display:block;color:var(--muted);margin-top:.2rem}.production-blocker-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:.8rem}.production-blocker-grid article{display:flex;flex-direction:column;gap:.5rem;padding:1rem;border:1px solid #fecaca;border-radius:.8rem;background:#fff7f7}.production-blocker-grid h3,.production-blocker-grid p{margin:0}.production-blocker-grid .btn{margin-top:auto}.production-log-list{display:grid;gap:.75rem}.production-log-list article{display:grid;gap:.25rem;padding:.75rem;border:1px solid var(--border,#dfe6ea);border-radius:.65rem}.production-log-list code{white-space:normal;word-break:break-word;font-size:.78rem;max-height:7rem;overflow:auto}.production-log-list small{color:var(--muted,#6b7280)}.operational-state-table table{min-width:680px;table-layout:auto}.operational-state-table th:nth-child(1),.operational-state-table td:nth-child(1){width:110px;white-space:nowrap}.operational-state-table th:nth-child(3),.operational-state-table td:nth-child(3){width:170px;white-space:normal}.operational-state-table th:nth-child(4),.operational-state-table td:nth-child(4){width:150px;white-space:normal;word-break:normal;overflow-wrap:anywhere}@media(max-width:700px){.production-completion-steps li{grid-template-columns:auto 1fr}.production-completion-steps li .btn{grid-column:1/-1;width:100%}}
</style>
<?php render_footer();
