<?php

declare(strict_types=1);

require DENTAL_ROOT . '/app/bootstrap.php';
require_login();
require_roles(['super_admin','clinic_admin']);
require DENTAL_ROOT . '/app/layout.php';

$pdo=db();
if(!schema_table_exists(table('appointment_reminders'))){
    render_header('Patient Reminders');
    echo '<div class="flash error">Apply database update 0.5.8.0 before using automatic reminders.</div>';
    render_footer();
    return;
}

if($_SERVER['REQUEST_METHOD']==='POST'){
    try{
        verify_csrf();
        $action=(string)($_POST['action']??'');
        if($action==='save'){
            $parts=preg_split('/\s*,\s*/',trim((string)($_POST['appointment_lead_hours']??'')),-1,PREG_SPLIT_NO_EMPTY)?:[];
            $leads=[];
            foreach($parts as $part){$hours=(int)$part;if($hours>=1&&$hours<=336)$leads[$hours]=$hours;}
            if(!$leads)throw new RuntimeException('Enter at least one reminder lead time between 1 and 336 hours.');
            rsort($leads,SORT_NUMERIC);
            setting_set('reminders','enabled',isset($_POST['enabled'])?'1':'0');
            setting_set('reminders','appointment_lead_hours',implode(',',$leads));
            setting_set('reminders','followups_enabled',isset($_POST['followups_enabled'])?'1':'0');
            setting_set('reminders','recalls_enabled',isset($_POST['recalls_enabled'])?'1':'0');
            setting_set('reminders','automatic_interval_minutes',(string)max(15,min(1440,(int)($_POST['automatic_interval_minutes']??30))));
            audit('reminder_settings_updated','reminder_settings',null,['appointment_lead_hours'=>$leads,'enabled'=>isset($_POST['enabled'])]);
            flash('success','Reminder settings saved.');
        }elseif($action==='run'){
            $result=run_due_patient_reminders($pdo,500);
            $delivery=run_email_queue($pdo,max(10,min(100,$result['queued']?:10)),'manual_reminders');
            setting_set('reminders','last_automatic_run_at',date('Y-m-d H:i:s'));
            audit('reminders_run','appointment_reminder',null,['reminders'=>$result,'delivery'=>$delivery]);
            $message=$result['queued'].' reminder'.($result['queued']===1?' was':'s were').' queued. ';
            if(!empty($delivery['busy']))$message.='Another email worker is active, so these messages remain queued for automatic delivery.';
            else $message.=$delivery['sent'].' accepted, '.$delivery['retry'].' retry scheduled, '.$delivery['failed'].' failed.';
            flash((!empty($delivery['busy'])||$delivery['retry']||$delivery['failed'])?'warning':'success',$message);
        }elseif($action==='retry_reminder'){
            $outboxId=(int)($_POST['outbox_id']??0);if($outboxId<1)throw new RuntimeException('Select a reminder message.');
            $retryStmt=$pdo->prepare('UPDATE `' . table('email_outbox') . '` SET status="pending",attempts=0,last_error=NULL,available_at=NOW(),updated_at=NOW() WHERE id=? AND status IN ("failed","retry","pending")');
            $retryStmt->execute([$outboxId]);
            if($retryStmt->rowCount()<1)throw new RuntimeException('This reminder is already accepted, cancelled, or currently being processed.');
            $delivery=(new Dental\Services\EmailService(dental_config(),$pdo))->processMessage($outboxId);
            $feedback=email_delivery_feedback($delivery,'Reminder email');
            audit('reminder_email_retried','appointment_reminder',$outboxId,['status'=>$delivery['status']??'unknown']);flash($feedback['type'],$feedback['message']);
        }else throw new RuntimeException('Unsupported reminder action.');
    }catch(Throwable $exception){flash('error',$exception->getMessage());}
    header('Location: reminders.php');exit;
}

$config=reminder_configuration();
$summary=['queued'=>0,'sent'=>0,'retry'=>0,'failed'=>0];
$stmt=$pdo->query('SELECT COALESCE(o.status,r.status) delivery_status,COUNT(*) total FROM `' . table('appointment_reminders') . '` r LEFT JOIN `' . table('email_outbox') . '` o ON o.id=r.outbox_id GROUP BY COALESCE(o.status,r.status)');
foreach($stmt as $row){$status=(string)$row['delivery_status'];if(isset($summary[$status]))$summary[$status]+=(int)$row['total'];elseif($status==='pending'||$status==='processing')$summary['queued']+=(int)$row['total'];}
$stmt=$pdo->query('SELECT r.*,COALESCE(o.status,r.status) delivery_status,o.last_error,CONCAT(p.first_name," ",p.last_name) patient,p.email FROM `' . table('appointment_reminders') . '` r JOIN `' . table('patients') . '` p ON p.id=r.patient_id LEFT JOIN `' . table('email_outbox') . '` o ON o.id=r.outbox_id ORDER BY r.created_at DESC LIMIT 100');
$rows=$stmt->fetchAll();
$lastRun=(string)setting_get('reminders','last_automatic_run_at','Never');

render_header('Patient Reminders');
?>
<section class="role-welcome card"><div><span class="eyebrow">Administration control</span><h2>Automatic patient reminders</h2><p>Queue appointment, follow-up, and recall reminders without requiring a permanent background worker. The system checks automatically while staff use the dashboard, and administration can run it manually at any time.</p></div><span class="role-pill"><?= $config['enabled']?'Enabled':'Disabled' ?></span></section>
<div class="stats">
<?php stat_card('Queued',$summary['queued'],'Waiting in the email outbox'); ?>
<?php stat_card('Accepted',$summary['sent'],'Accepted by the configured mail server'); ?>
<?php stat_card('Retry',$summary['retry'],'Temporary delivery failures'); ?>
<?php stat_card('Failed',$summary['failed'],'Requires email configuration review'); ?>
</div>
<section class="grid-2">
<article class="card"><div class="card-head"><div><h2>Reminder rules</h2><p>Appointment lead times are entered in hours. The default sends approximately 3 days, 1 day, and 3 hours before the visit.</p></div></div><form method="post" class="form-grid"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="save"><label class="wide check-label"><input type="checkbox" name="enabled" value="1" <?=$config['enabled']?'checked':''?>><span>Enable automatic email reminders</span></label><label class="wide">Appointment lead hours<input name="appointment_lead_hours" value="<?=e(implode(',',$config['appointment_lead_hours']))?>" required><small>Examples: 72,24,3. Each appointment is protected from duplicate sends.</small></label><label>Automatic check interval<select name="automatic_interval_minutes"><?php foreach([15,30,60,120,240,720,1440] as $minutes):?><option value="<?=$minutes?>" <?=$config['automatic_interval_minutes']===$minutes?'selected':''?>><?=$minutes<60?$minutes.' minutes':($minutes/60).' hours'?></option><?php endforeach;?></select></label><label class="check-label"><input type="checkbox" name="followups_enabled" value="1" <?=$config['followups']?'checked':''?>><span>Remind pending follow-ups when due</span></label><label class="check-label"><input type="checkbox" name="recalls_enabled" value="1" <?=$config['recalls']?'checked':''?>><span>Remind due recalls</span></label><button class="btn primary wide">Save reminder rules</button></form></article>
<article class="card"><div class="card-head"><div><h2>Run and delivery</h2><p>Last automatic check: <?=e($lastRun)?></p></div><a href="email_settings.php">Email settings</a></div><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="run"><button class="btn primary">Generate and Send Due Reminders</button></form><div class="alert"><strong>Delivery model</strong><br>Automatic checks create deduplicated messages in the normal email outbox. Failed messages continue to use the configured retry rules. SMS is not sent unless a separate SMS provider is configured in a future integration.</div></article>
</section>
<section class="card table-wrap"><div class="card-head"><div><h2>Recent reminder activity</h2><p>Patient names are shown only to authorized administrators.</p></div></div><table><thead><tr><th>Created</th><th>Patient</th><th>Reminder</th><th>Scheduled for</th><th>Delivery</th><th>Error</th><th></th></tr></thead><tbody><?php foreach($rows as $row):?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$row['created_at'])))?></td><td><strong><?=e((string)$row['patient'])?></strong><small><?=e((string)$row['email'])?></small></td><td><?=e(ucwords(str_replace('_',' ',(string)$row['entity_type'])))?><small><?=e((string)$row['reminder_key'])?></small></td><td><?=e(date('M j, Y g:i A',strtotime((string)$row['scheduled_for'])))?></td><td><span class="badge"><?=e(ucwords(str_replace('_',' ',(string)$row['delivery_status'])))?></span></td><td><?=e((string)($row['last_error']?:'—'))?></td><td><?php if(!empty($row['outbox_id'])&&in_array((string)$row['delivery_status'],['failed','retry','pending'],true)):?><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="retry_reminder"><input type="hidden" name="outbox_id" value="<?=(int)$row['outbox_id']?>"><button class="btn ghost">Retry now</button></form><?php endif;?></td></tr><?php endforeach;if(!$rows):?><tr><td colspan="7" class="muted">No reminders have been queued yet.</td></tr><?php endif;?></tbody></table></section>
<?php render_footer();
