<?php

declare(strict_types=1);

require DENTAL_ROOT . '/app/bootstrap.php';
require_login();
require DENTAL_ROOT . '/app/layout.php';

$patientAccess = dental_patient_access_capabilities();
$canSearchPatients = !empty($patientAccess['identity'])
    && navigation_can('patients.view', ['super_admin','clinic_admin','receptionist','staff','dentist','dental_assistant'])
    && task_link_allowed('patients.php');
$canViewPatientContact = !empty($patientAccess['contact']);
$canSearchAppointments = navigation_can('appointments.manage', ['super_admin','clinic_admin','receptionist','staff','dentist','dental_assistant'])
    && task_link_allowed('appointments.php');
$canSearchQueue = navigation_can('queue.manage', ['super_admin','clinic_admin','receptionist','staff','dentist','dental_assistant'])
    && task_link_allowed('queue.php');
$canSearchInvoices = navigation_can('billing.manage', ['super_admin','clinic_admin','staff','cashier'])
    && task_link_allowed('billing.php');

if (!$canSearchPatients && !$canSearchAppointments && !$canSearchQueue && !$canSearchInvoices) {
    access_denied('Global patient search is not part of the active task workspace.');
}

$q = trim((string)($_GET['q'] ?? ''));
$patients = $appointments = $queues = $invoices = [];
$error = '';

if ($q !== '' && mb_strlen($q) >= 2) {
    try {
        $pdo = db();
        $like = '%' . $q . '%';
        [$scopeSql, $scopeParams] = task_patient_scope_condition('p.id');
        $patientTable = table('patients');
        $patientDeleted = schema_column_exists($patientTable, 'deleted_at') ? ' AND p.deleted_at IS NULL' : '';
        $patientStatus = schema_column_exists($patientTable, 'status') ? 'p.status' : '"active" AS status';

        if ($canSearchPatients) {
            $contactSelect = $canViewPatientContact ? 'p.mobile,p.email' : 'NULL AS mobile,NULL AS email';
            $patientSearch = ['p.patient_no LIKE ?', 'p.first_name LIKE ?', 'p.last_name LIKE ?', 'CONCAT(p.first_name," ",p.last_name) LIKE ?'];
            $patientArgs = [$like, $like, $like, $like];
            if ($canViewPatientContact) {
                $patientSearch[] = 'p.mobile LIKE ?';
                $patientSearch[] = 'p.email LIKE ?';
                $patientArgs[] = $like;
                $patientArgs[] = $like;
            }
            $patientSql = 'SELECT p.id,p.patient_no,p.first_name,p.last_name,' . $contactSelect . ',' . $patientStatus
                . ' FROM `' . $patientTable . '` p WHERE 1=1' . $scopeSql . $patientDeleted
                . ' AND (' . implode(' OR ', $patientSearch) . ') ORDER BY p.last_name,p.first_name LIMIT 15';
            $stmt = $pdo->prepare($patientSql);
            $stmt->execute(array_merge($scopeParams, $patientArgs));
            $patients = $stmt->fetchAll();
        }

        if ($canSearchAppointments && schema_table_exists(table('appointments'))) {
            $sql = 'SELECT a.id,a.patient_id,a.service_name,a.start_at,a.status,a.dentist_name,'
                . 'CONCAT(p.first_name," ",p.last_name) patient,p.patient_no '
                . 'FROM `' . table('appointments') . '` a JOIN `' . $patientTable . '` p ON p.id=a.patient_id '
                . 'WHERE 1=1' . $scopeSql . $patientDeleted
                . ' AND (p.patient_no LIKE ? OR p.first_name LIKE ? OR p.last_name LIKE ? OR a.service_name LIKE ? OR a.dentist_name LIKE ? OR a.status LIKE ?) '
                . 'ORDER BY a.start_at DESC LIMIT 10';
            $stmt = $pdo->prepare($sql);
            $stmt->execute(array_merge($scopeParams, [$like,$like,$like,$like,$like,$like]));
            $appointments = $stmt->fetchAll();
        }

        if ($canSearchQueue && schema_table_exists(table('queue_entries'))) {
            $sql = 'SELECT q.id,q.patient_id,q.queue_no,q.service_name,q.status,q.checked_in_at,'
                . 'CONCAT(p.first_name," ",p.last_name) patient '
                . 'FROM `' . table('queue_entries') . '` q JOIN `' . $patientTable . '` p ON p.id=q.patient_id '
                . 'WHERE 1=1' . $scopeSql . $patientDeleted
                . ' AND (q.queue_no LIKE ? OR p.patient_no LIKE ? OR p.first_name LIKE ? OR p.last_name LIKE ? OR q.service_name LIKE ?) '
                . 'ORDER BY q.checked_in_at DESC LIMIT 10';
            $stmt = $pdo->prepare($sql);
            $stmt->execute(array_merge($scopeParams, [$like,$like,$like,$like,$like]));
            $queues = $stmt->fetchAll();
        }

        if ($canSearchInvoices && schema_table_exists(table('invoices'))) {
            $sql = 'SELECT i.id,i.patient_id,i.invoice_no,i.description,i.amount,i.paid_amount,i.status,i.created_at,'
                . 'CONCAT(p.first_name," ",p.last_name) patient '
                . 'FROM `' . table('invoices') . '` i JOIN `' . $patientTable . '` p ON p.id=i.patient_id '
                . 'WHERE 1=1' . $scopeSql . $patientDeleted
                . ' AND (i.invoice_no LIKE ? OR p.patient_no LIKE ? OR p.first_name LIKE ? OR p.last_name LIKE ? OR i.description LIKE ? OR i.status LIKE ?) '
                . 'ORDER BY i.created_at DESC LIMIT 10';
            $stmt = $pdo->prepare($sql);
            $stmt->execute(array_merge($scopeParams, [$like,$like,$like,$like,$like,$like]));
            $invoices = $stmt->fetchAll();
        }
    } catch (Throwable $exception) {
        error_log('DentalCare minimum-necessary global search failed: ' . $exception);
        $error = 'Some authorized records could not be searched. Apply all pending updates and try again.';
    }
}

$searchKinds = [];
if ($canSearchPatients) $searchKinds[] = 'patient name or number' . ($canViewPatientContact ? ', mobile, or email' : '');
if ($canSearchAppointments) $searchKinds[] = 'appointment';
if ($canSearchInvoices) $searchKinds[] = 'invoice';
if ($canSearchQueue) $searchKinds[] = 'queue ticket';
$placeholder = 'Search ' . implode(', ', $searchKinds);

render_header('Search');
?>
<section class="search-page-head card">
    <div><span class="eyebrow">Minimum-necessary clinic search</span><h2>Find only records authorized for this Task View.</h2><p>Results are filtered by permission, branch, patient assignment, and the selected workspace. Restricted contact, medical, and financial data are not queried.</p></div>
    <form action="search.php" method="get" class="search-page-form" data-auto-submit><?=dental_icon('search')?><input type="search" name="q" value="<?=e($q)?>" autofocus placeholder="<?=e($placeholder)?>" autocomplete="off" data-auto-search data-min-length="2"><span class="auto-filter-note">Results update automatically</span></form>
</section>
<?php if ($error): ?><div class="flash error"><?=e($error)?></div><?php endif; ?>
<?php if ($q === '' || mb_strlen($q) < 2): ?>
<section class="empty-state card"><?=dental_icon('search','empty-state-icon')?><h2>Enter at least two characters.</h2><p><?=e(ucfirst($placeholder))?>.</p></section>
<?php else: $total = count($patients) + count($appointments) + count($queues) + count($invoices); ?>
<div class="search-summary"><strong><?=$total?></strong> authorized result<?=$total===1?'':'s'?> for “<?=e($q)?>”</div>
<div class="search-result-grid">
<?php if ($canSearchPatients): ?>
<section class="card search-result-section"><div class="card-head"><div><h2>Patients</h2><p><?=count($patients)?> matching record<?=count($patients)===1?'':'s'?></p></div><?=dental_icon('patients','section-icon')?></div>
<?php if (!$patients): ?><p class="muted">No matching patients in your authorized scope.</p><?php else: ?><div class="search-result-list">
<?php foreach ($patients as $row): $contact = $canViewPatientContact ? trim((string)($row['mobile'] ?: $row['email'])) : ''; ?>
<a href="patients.php?action=view&amp;id=<?=(int)$row['id']?>"><span class="result-icon"><?=dental_icon('patient')?></span><span><strong><?=e($row['last_name'].', '.$row['first_name'])?></strong><small><?=e((string)$row['patient_no'])?><?=$contact!==''?' · '.e($contact):''?></small></span><em><?=e((string)$row['status'])?></em></a>
<?php endforeach; ?></div><?php endif; ?></section>
<?php endif; ?>

<?php if ($canSearchAppointments): ?><section class="card search-result-section"><div class="card-head"><div><h2>Appointments</h2><p><?=count($appointments)?> matching record<?=count($appointments)===1?'':'s'?></p></div><?=dental_icon('calendar','section-icon')?></div><?php if(!$appointments):?><p class="muted">No matching appointments.</p><?php else:?><div class="search-result-list"><?php foreach($appointments as $row):?><a href="appointments.php"><span class="result-icon"><?=dental_icon('calendar')?></span><span><strong><?=e((string)$row['patient'])?> · <?=e((string)$row['service_name'])?></strong><small><?=e(date('M j, Y g:i A',strtotime((string)$row['start_at'])))?> · <?=e((string)$row['dentist_name'])?></small></span><em><?=e((string)$row['status'])?></em></a><?php endforeach;?></div><?php endif;?></section><?php endif; ?>

<?php if ($canSearchQueue): ?><section class="card search-result-section"><div class="card-head"><div><h2>Queue</h2><p><?=count($queues)?> matching record<?=count($queues)===1?'':'s'?></p></div><?=dental_icon('queue','section-icon')?></div><?php if(!$queues):?><p class="muted">No matching queue tickets.</p><?php else:?><div class="search-result-list"><?php foreach($queues as $row):?><a href="queue.php"><span class="result-icon"><?=dental_icon('queue')?></span><span><strong><?=e((string)$row['queue_no'])?> · <?=e((string)$row['patient'])?></strong><small><?=e((string)$row['service_name'])?> · <?=e(date('M j, g:i A',strtotime((string)$row['checked_in_at'])))?></small></span><em><?=e((string)$row['status'])?></em></a><?php endforeach;?></div><?php endif;?></section><?php endif; ?>

<?php if ($canSearchInvoices): ?><section class="card search-result-section"><div class="card-head"><div><h2>Invoices</h2><p><?=count($invoices)?> matching record<?=count($invoices)===1?'':'s'?></p></div><?=dental_icon('receipt','section-icon')?></div><?php if(!$invoices):?><p class="muted">No matching invoices.</p><?php else:?><div class="search-result-list"><?php foreach($invoices as $row):?><a href="billing.php"><span class="result-icon"><?=dental_icon('receipt')?></span><span><strong><?=e((string)$row['invoice_no'])?> · <?=e((string)$row['patient'])?></strong><small><?=e((string)$row['description'])?> · ₱<?=number_format((float)$row['amount'],2)?></small></span><em><?=e((string)$row['status'])?></em></a><?php endforeach;?></div><?php endif;?></section><?php endif; ?>
</div>
<?php endif; ?>
<?php render_footer();
