<?php

declare(strict_types=1);

use Dental\Services\EmailService;
use Dental\Services\GmailApiMailer;
use Dental\Services\SmtpMailer;

require DENTAL_ROOT . '/app/bootstrap.php';
require_login();
require_doctor_workflow_schema();
require_permission('smtp.manage',['super_admin','clinic_admin']);
require DENTAL_ROOT . '/app/layout.php';
require_once DENTAL_ROOT . '/app/module_helpers.php';

$pdo=db();$user=current_user()??[];

function email_record_diagnostic(PDO $pdo,string $type,string $status,array $mail,string $message,string $transcript=''): void
{
    $driver=(string)($mail['driver']??'smtp');
    $smtp=(array)($mail['smtp']??[]);
    $host=(string)($smtp['host']??'');
    $port=(int)($smtp['port']??0)?:null;
    $encryption=(string)($smtp['encryption']??'');
    if($driver==='gmail_api'){
        $host='gmail.googleapis.com';
        $port=443;
        $encryption='https';
    }

    // Older installs still have smtp_diagnostics.test_type as an ENUM
    // (configuration, connection, authentication, delivery, queue).  v0.6.9
    // wrote "unified_delivery", which strict MySQL correctly rejected with
    // SQLSTATE[01000] 1265.  Keep the dashboard label inside the message, but
    // store a legacy-safe value so test mail never fails because of diagnostics.
    $originalType = trim($type);
    $allowedTypes = ['configuration'=>true,'connection'=>true,'authentication'=>true,'delivery'=>true,'queue'=>true];
    $safeType = isset($allowedTypes[$originalType]) ? $originalType : 'delivery';
    if ($safeType !== $originalType && $originalType !== '') {
        $message = '[' . $originalType . '] ' . $message;
    }

    try {
        $pdo->prepare('INSERT INTO `' . table('smtp_diagnostics') . '` (user_id,test_type,status,host,port,encryption,message,transcript,created_at) VALUES (?,?,?,?,?,?,?,?,NOW())')->execute([
            (int)(current_user()['id']??0)?:null,$safeType,$status,$host,$port,$encryption,substr($message,0,4000),$transcript!==''?substr($transcript,0,20000):null,
        ]);
    } catch (Throwable $diagnosticException) {
        error_log('Email diagnostic record failed: '.$diagnosticException->getMessage());
    }
}

function email_is_hosted_smtp_provider(string $host): bool
{
    return (bool) preg_match('/(^|\.)(gmail\.com|googlemail\.com|google\.com|outlook\.com|office365\.com|hotmail\.com|live\.com|yahoo\.com|icloud\.com|zoho\.com)$/i', trim($host));
}

if($_SERVER['REQUEST_METHOD']==='POST'){
    try{
        verify_csrf();$action=(string)($_POST['action']??'');
        if($action==='save_queue'){
            $enabled=isset($_POST['automatic_enabled'])?'1':'0';
            $interval=max(1,min(60,(int)($_POST['interval_minutes']??2)));
            $batch=max(1,min(50,(int)($_POST['batch_size']??10)));
            setting_set('email_queue','automatic_enabled',$enabled);
            setting_set('email_queue','automatic_interval_minutes',(string)$interval);
            setting_set('email_queue','automatic_batch_size',(string)$batch);
            audit('email_queue_settings_updated','settings',null,['automatic_enabled'=>$enabled,'interval_minutes'=>$interval,'batch_size'=>$batch]);
            flash('success','Automatic email delivery settings saved.');
            header('Location: email_settings.php');exit;
        }
        if($action==='save_retention'){
            if(!superuser_primary_workspace())throw new RuntimeException('Email history retention is a Superuser system control. Return to the Superuser workspace first.');
            $values=[
                'outbox_days'=>max(30,min(3650,(int)($_POST['outbox_days']??365))),
                'email_log_days'=>max(30,min(3650,(int)($_POST['email_log_days']??365))),
                'run_days'=>max(7,min(730,(int)($_POST['run_days']??90))),
                'diagnostic_days'=>max(7,min(730,(int)($_POST['diagnostic_days']??90))),
                'transcript_days'=>max(1,min(90,(int)($_POST['transcript_days']??14))),
            ];
            foreach($values as $key=>$value)setting_set('email_history',$key,(string)$value);
            audit('email_history_retention_updated','settings',null,$values);
            flash('success','Email history retention policy saved.');
            header('Location: email_settings.php?history=overview#email-history');exit;
        }
        if($action==='run_history_cleanup'){
            if(!superuser_primary_workspace())throw new RuntimeException('Email history cleanup is a Superuser system control. Return to the Superuser workspace first.');
            $cleanup=email_history_maintenance($pdo,true);
            audit('email_history_cleanup_run','system',null,$cleanup);
            $removed=(int)$cleanup['outbox']+(int)$cleanup['email_log']+(int)$cleanup['runs']+(int)$cleanup['diagnostics'];
            flash('success','Email history cleanup completed. '.$removed.' expired row(s) removed and '.(int)$cleanup['transcripts'].' old transcript(s) cleared.');
            header('Location: email_settings.php?history=overview#email-history');exit;
        }
        if($action==='save_smtp'){
            $driver=(string)($_POST['driver']??'smtp');if(!in_array($driver,['smtp','gmail_api','mail','log'],true))$driver='smtp';
            $fromEmail=trim((string)($_POST['from_email']??''));if(!filter_var($fromEmail,FILTER_VALIDATE_EMAIL))throw new RuntimeException('Enter a valid sender email address.');
            $port=max(1,min(65535,(int)($_POST['smtp_port']??587)));$encryption=(string)($_POST['smtp_encryption']??'tls');if(!in_array($encryption,['tls','ssl','none'],true))$encryption='tls';
            $host=trim((string)($_POST['smtp_host']??''));if($driver==='smtp'&&$host==='')throw new RuntimeException('Enter the SMTP server hostname.');
            $username=trim((string)($_POST['smtp_username']??''));$password=(string)($_POST['smtp_password']??'');
            $auth=(string)($_POST['smtp_auth_method']??'auto');if(!in_array($auth,['auto','login','plain'],true))$auth='auto';
            $peerName=trim((string)($_POST['smtp_peer_name']??''));
            $verifyPeer=isset($_POST['smtp_verify_peer']);
            if($driver==='smtp' && email_is_hosted_smtp_provider($host)){
                if(!$verifyPeer)throw new RuntimeException('Keep TLS certificate verification enabled for Gmail/hosted SMTP providers. Do not disable it to bypass a redirected or mismatched server certificate.');
                if($peerName!=='')throw new RuntimeException('Leave Certificate host name blank for Gmail/hosted SMTP providers. If Gmail shows another server certificate, the hosting server is not reaching Gmail SMTP; use the Gmail API mail driver or have the host allow direct outbound Gmail SMTP.');
            }
            $gmailClientId=trim((string)($_POST['gmail_client_id']??''));
            $gmailClientSecret=(string)($_POST['gmail_client_secret']??'');
            $gmailRefreshToken=(string)($_POST['gmail_refresh_token']??'');
            $gmailSender=trim((string)($_POST['gmail_sender_email']??$fromEmail));
            $gmailTimeout=max(10,min(120,(int)($_POST['gmail_timeout']??30)));
            if($driver==='gmail_api'){
                if(!extension_loaded('curl'))throw new RuntimeException('PHP cURL must be enabled to use the Gmail API mail driver.');
                if($gmailClientId==='')throw new RuntimeException('Google OAuth Client ID is required for Gmail API delivery.');
                if($gmailSender===''||!filter_var($gmailSender,FILTER_VALIDATE_EMAIL))throw new RuntimeException('Enter the Gmail sender email address.');
            }
            dental_update_generated_config(static function(array $config) use($driver,$fromEmail,$port,$encryption,$host,$username,$password,$auth,$peerName,$verifyPeer,$gmailClientId,$gmailClientSecret,$gmailRefreshToken,$gmailSender,$gmailTimeout): array {
                $existing=(array)($config['mail']['smtp']??[]);
                $existingGmail=(array)($config['mail']['gmail_api']??[]);
                $config['mail']=[
                    'driver'=>$driver,
                    'from_email'=>$fromEmail,
                    'from_name'=>trim((string)($_POST['from_name']??'Dental Clinic'))?:'Dental Clinic',
                    'smtp'=>[
                        'host'=>$host,
                        'port'=>$port,
                        'encryption'=>$encryption,
                        'username'=>$username,
                        'password'=>$password!==''?$password:(string)($existing['password']??''),
                        'auth_method'=>$auth,
                        'timeout'=>max(5,min(120,(int)($_POST['smtp_timeout']??20))),
                        'verify_peer'=>$verifyPeer,
                        'local_domain'=>trim((string)($_POST['smtp_local_domain']??'')),
                        'peer_name'=>$peerName,
                    ],
                    'gmail_api'=>[
                        'client_id'=>$gmailClientId,
                        'client_secret'=>$gmailClientSecret!==''?$gmailClientSecret:(string)($existingGmail['client_secret']??''),
                        'refresh_token'=>$gmailRefreshToken!==''?$gmailRefreshToken:(string)($existingGmail['refresh_token']??''),
                        'sender_email'=>$gmailSender,
                        'timeout'=>$gmailTimeout,
                    ],
                ];
                return $config;
            });
            audit('smtp_configuration_updated','settings',null,['driver'=>$driver,'host'=>$host,'port'=>$port,'encryption'=>$encryption,'username'=>$username,'password_changed'=>$password!=='','gmail_secret_changed'=>$gmailClientSecret!==''||$gmailRefreshToken!=='']);
            flash('success','Email configuration saved. Run Connection Test, then Send Test Email.');
            header('Location: email_settings.php');exit;
        }

        $config=dental_config();$mail=(array)($config['mail']??[]);
        if($action==='test_connection'){
            $driver=(string)($mail['driver']??'smtp');
            if($driver==='gmail_api'){
                $mailer=new GmailApiMailer((array)($mail['gmail_api']??[]));$result=$mailer->diagnose();
            }elseif($driver==='smtp'){
                $mailer=new SmtpMailer((array)($mail['smtp']??[]));$result=$mailer->diagnose(true);
            }else{
                throw new RuntimeException('Connection diagnostics apply only to SMTP or Gmail API delivery.');
            }
            email_record_diagnostic($pdo,'authentication',$result['ok']?'success':'failed',$mail,$result['message'],$result['transcript']);
            flash($result['ok']?'success':'error',$result['message']);
            header('Location: email_settings.php');exit;
        }
        if($action==='send_test'){
            $recipient=trim((string)($_POST['test_recipient']??''));if(!filter_var($recipient,FILTER_VALIDATE_EMAIL))throw new RuntimeException('Enter a valid test recipient.');
            $driver=(string)($mail['driver']??'smtp');
            $driverLabel=['gmail_api'=>'Gmail API','smtp'=>'Domain SMTP','mail'=>'PHP mail()','log'=>'Log only'][$driver]??strtoupper($driver);
            $subject='DentalCare unified mail test · '.date('Y-m-d H:i:s');
            $html='<h2>DentalCare unified mail test</h2><p>This test uses the same selected mail engine used by password resets, staff invitations, appointment messages, portal invitations, receipts, and reminders.</p><p><strong>Mail path:</strong> '.e($driverLabel).'</p><p><strong>Host:</strong> '.e(dental_current_host()).'</p><p>Time: '.e(date(DATE_RFC2822)).'</p>';
            $service=new EmailService($config,$pdo);
            $outboxId=$service->queue($recipient,$subject,$html,'DentalCare unified mail test using '.$driverLabel.'.',['type'=>'unified_mail_health_test','mail_family'=>'system_test','transport_driver'=>$driver]);
            $delivery=$service->processMessage($outboxId);
            $feedback=email_delivery_feedback($delivery,'Unified mail test');
            email_queue_record_result(['selected'=>1,'sent'=>($delivery['status']??'')==='sent'?1:0,'retry'=>($delivery['status']??'')==='retry'?1:0,'failed'=>($delivery['status']??'')==='failed'?1:0,'skipped'=>($delivery['status']??'')==='skipped'?1:0,'recovered'=>0,'busy'=>false],'unified_health_test');
            $message=$feedback['message'].' Mail path: '.$driverLabel.'. Outbox #'.$outboxId.'.';
            if((string)($delivery['status']??'')!=='sent' && !empty($delivery['error'])) $message.=' Error: '.(string)$delivery['error'];
            email_record_diagnostic($pdo,'unified_delivery',($delivery['status']??'')==='sent'?'success':(($delivery['status']??'')==='failed'?'failed':'warning'),$mail,$message);
            flash($feedback['type'],$message);
            header('Location: email_settings.php');exit;
        }
        if($action==='process_queue'){
            $result=run_email_queue($pdo,max(1,min(100,(int)($_POST['queue_limit']??20))),'manual_settings');
            $message=$result['busy']?'Another queue worker is already running. No duplicate send was started.':'Queue processed: '.$result['sent'].' accepted, '.$result['retry'].' retry scheduled, '.$result['failed'].' failed, '.$result['recovered'].' recovered.';
            $queueNeedsAttention = !empty($result['busy']) || !empty($result['failed']) || !empty($result['retry']);
            email_record_diagnostic($pdo,'queue',$queueNeedsAttention?'warning':'success',$mail,$message);
            flash($queueNeedsAttention?'warning':'success',$message);header('Location: email_settings.php');exit;
        }
        if($action==='retry_failed'){
            $count=$pdo->exec('UPDATE `' . table('email_outbox') . '` SET status="pending",attempts=0,last_error=NULL,available_at=NOW(),updated_at=NOW() WHERE status="failed"');
            audit('failed_emails_requeued','email',null,['count'=>$count]);flash('success',(int)$count.' failed message(s) returned to the queue.');header('Location: email_settings.php');exit;
        }
        if($action==='retry_one'){
            $id=(int)($_POST['outbox_id']??0);if($id<1)throw new RuntimeException('Select a queued 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([$id]);
            if($retryStmt->rowCount()<1)throw new RuntimeException('This message is already accepted, cancelled, or currently being processed.');
            $delivery=(new EmailService($config,$pdo))->processMessage($id);
            audit('email_message_retried','email',$id,['status'=>$delivery['status']??'unknown']);
            flash(($delivery['status']??'')==='sent'?'success':'warning',($delivery['status']??'')==='sent'?'The mail server accepted the message.':'The message is '.strtolower(email_delivery_label((string)($delivery['status']??'retry'))).'. Review the error below.');header('Location: email_settings.php');exit;
        }
    }catch(Throwable $exception){flash('error',$exception->getMessage());header('Location: email_settings.php');exit;}
}

$config=dental_config();$mail=(array)($config['mail']??[]);$smtp=array_merge(['host'=>'','port'=>587,'encryption'=>'tls','username'=>'','auth_method'=>'auto','timeout'=>20,'verify_peer'=>true,'local_domain'=>'','peer_name'=>''],(array)($mail['smtp']??[]));$gmail=array_merge(['client_id'=>'','client_secret'=>'','refresh_token'=>'','sender_email'=>(string)($mail['from_email']??''),'timeout'=>30],(array)($mail['gmail_api']??[]));
$queue=['pending'=>0,'processing'=>0,'retry'=>0,'sent'=>0,'failed'=>0,'cancelled'=>0];try{$rows=$pdo->query('SELECT status,COUNT(*) total FROM `' . table('email_outbox') . '` GROUP BY status');foreach($rows as $row)$queue[$row['status']]=(int)$row['total'];}catch(Throwable){}
$queueConfig=email_queue_configuration();$health=email_queue_health($pdo);$retention=email_history_retention_configuration();
$historyType=(string)($_GET['history']??'overview');if(!in_array($historyType,['overview','delivery','runs','diagnostics'],true))$historyType='overview';
$historyPage=max(1,(int)($_GET['history_page']??1));$historyPerPage=(int)($_GET['history_per_page']??25);if(!in_array($historyPerPage,[10,25,50,100],true))$historyPerPage=25;
$historyStatus=trim((string)($_GET['history_status']??''));$historyQuery=trim((string)($_GET['history_q']??''));
$historyTotal=0;$historyRows=[];$attentionRows=[];
if($historyType==='delivery'){
    $allowed=['pending','processing','retry','sent','failed','cancelled'];$where=[];$args=[];
    if(in_array($historyStatus,$allowed,true)){$where[]='status=?';$args[]=$historyStatus;}
    if($historyQuery!==''){$where[]='(recipient_email LIKE ? OR subject LIKE ? OR CAST(id AS CHAR)=?)';$like=module_like_term($historyQuery);array_push($args,$like,$like,$historyQuery);}
    $whereSql=$where?' WHERE '.implode(' AND ',$where):'';
    $count=$pdo->prepare('SELECT COUNT(*) FROM `' . table('email_outbox') . '`'.$whereSql);$count->execute($args);$historyTotal=(int)$count->fetchColumn();
    $pages=max(1,(int)ceil($historyTotal/$historyPerPage));$historyPage=min($historyPage,$pages);$offset=($historyPage-1)*$historyPerPage;
    $stmt=$pdo->prepare('SELECT id,recipient_email,subject,status,attempts,last_error,sent_at,updated_at,created_at,metadata_json FROM `' . table('email_outbox') . '`'.$whereSql.' ORDER BY id DESC LIMIT '.$historyPerPage.' OFFSET '.$offset);$stmt->execute($args);$historyRows=$stmt->fetchAll();
}elseif($historyType==='runs'&&schema_table_exists(table('email_queue_runs'))){
    $allowed=['success','warning','failed','busy'];$where=[];$args=[];
    if(in_array($historyStatus,$allowed,true)){$where[]='r.status=?';$args[]=$historyStatus;}
    $whereSql=$where?' WHERE '.implode(' AND ',$where):'';
    $count=$pdo->prepare('SELECT COUNT(*) FROM `' . table('email_queue_runs') . '` r'.$whereSql);$count->execute($args);$historyTotal=(int)$count->fetchColumn();
    $pages=max(1,(int)ceil($historyTotal/$historyPerPage));$historyPage=min($historyPage,$pages);$offset=($historyPage-1)*$historyPerPage;
    $stmt=$pdo->prepare('SELECT r.*,u.name started_by_name FROM `' . table('email_queue_runs') . '` r LEFT JOIN `' . table('users') . '` u ON u.id=r.started_by'.$whereSql.' ORDER BY r.id DESC LIMIT '.$historyPerPage.' OFFSET '.$offset);$stmt->execute($args);$historyRows=$stmt->fetchAll();
}elseif($historyType==='diagnostics'){
    $allowed=['success','warning','failed'];$where=[];$args=[];
    if(in_array($historyStatus,$allowed,true)){$where[]='d.status=?';$args[]=$historyStatus;}
    $whereSql=$where?' WHERE '.implode(' AND ',$where):'';
    $count=$pdo->prepare('SELECT COUNT(*) FROM `' . table('smtp_diagnostics') . '` d'.$whereSql);$count->execute($args);$historyTotal=(int)$count->fetchColumn();
    $pages=max(1,(int)ceil($historyTotal/$historyPerPage));$historyPage=min($historyPage,$pages);$offset=($historyPage-1)*$historyPerPage;
    $stmt=$pdo->prepare('SELECT d.*,u.name user_name FROM `' . table('smtp_diagnostics') . '` d LEFT JOIN `' . table('users') . '` u ON u.id=d.user_id'.$whereSql.' ORDER BY d.id DESC LIMIT '.$historyPerPage.' OFFSET '.$offset);$stmt->execute($args);$historyRows=$stmt->fetchAll();
}else{
    $attentionRows=$pdo->query('SELECT id,recipient_email,subject,status,attempts,last_error,sent_at,updated_at,created_at,metadata_json FROM `' . table('email_outbox') . '` WHERE status IN ("pending","processing","retry","failed") ORDER BY id DESC LIMIT 10')->fetchAll();
}
render_header('Email & SMTP');
$driver=(string)($mail['driver']??'smtp');
$driverLabel=['gmail_api'=>'Gmail API','smtp'=>'Domain SMTP','mail'=>'PHP mail()','log'=>'Log only'][$driver]??strtoupper($driver);
$gmailConnected=trim((string)($gmail['refresh_token']??''))!=='';
?>
<section class="card smtp-heading mail-command-heading">
  <div><span class="eyebrow">Email delivery</span><h2>Email Settings</h2><p>Pick the correct mail path first. Password resets, staff invitations, appointment notices, receipts, reminders, and the test button now use the same central mail engine and outbox.</p></div>
  <div class="inline-actions"><a class="btn ghost" href="email_templates.php">Email Templates</a><span class="badge"><?=e($driverLabel)?></span></div>
</section>

<nav class="mail-path-jumpbar" aria-label="Email settings sections">
  <a href="#mail-path">Mail path</a>
  <a href="#sender-identity">Sender</a>
  <a href="#gmail-api-path">Gmail API</a>
  <a href="#domain-smtp-path">Domain SMTP</a>
  <a href="#php-log-path">PHP / Log</a>
  <a href="#email-queue-path">Queue</a>
  <a href="email_settings.php?history=diagnostics#email-history">History</a>
</nav>


<section class="card mail-delivery-contract"><div class="card-head"><div><h2>Unified mail path coverage</h2><p>These system messages now use the selected mail path and the same outbox/processing engine.</p></div><span class="badge"><?=e($driverLabel)?></span></div><div class="coverage-grid"><span>Password reset / staff invite</span><span>Appointment confirmation and cancellation</span><span>Patient portal invitation</span><span>Payment receipt</span><span>Reminders and recalls</span><span>Send test mail</span></div><p class="muted">If password reset sends but test mail fails, review the paginated delivery or diagnostics history. The test no longer uses a separate hidden route.</p></section>
<div class="mail-redesign-layout">
  <main class="mail-redesign-main">
    <form method="post" class="mail-settings-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="save_smtp">
      <section class="card" id="mail-path">
        <div class="card-head"><div><span class="eyebrow">Step 1</span><h2>Choose mail path</h2><p>Use one path at a time. Gmail API avoids shared-host SMTP routing. Domain SMTP is for mailbox providers such as cPanel/domain mail, Outlook SMTP, Zoho SMTP, or other hosted mail servers.</p></div><span class="badge">Current: <?=e($driverLabel)?></span></div>
        <div class="mail-path-cards">
          <label class="mail-path-card <?= $driver==='gmail_api'?'selected':'' ?>"><input type="radio" name="driver" value="gmail_api" <?= $driver==='gmail_api'?'checked':'' ?>><strong>Gmail API</strong><span>Best for Gmail / Google Workspace. Uses HTTPS OAuth, not SMTP ports.</span><small><?= $gmailConnected?'Connected token saved':'OAuth token needed' ?></small></label>
          <label class="mail-path-card <?= $driver==='smtp'?'selected':'' ?>"><input type="radio" name="driver" value="smtp" <?= $driver==='smtp'?'checked':'' ?>><strong>Domain SMTP</strong><span>Best for domain mailbox providers. Requires host, port, encryption, username, and password.</span><small><?= e((string)($smtp['host']?:'Not configured')) ?></small></label>
          <label class="mail-path-card <?= $driver==='mail'?'selected':'' ?>"><input type="radio" name="driver" value="mail" <?= $driver==='mail'?'checked':'' ?>><strong>PHP mail()</strong><span>Use only if hosting confirms PHP mail is configured and trusted.</span><small>Limited diagnostics</small></label>
          <label class="mail-path-card <?= $driver==='log'?'selected':'' ?>"><input type="radio" name="driver" value="log" <?= $driver==='log'?'checked':'' ?>><strong>Log only</strong><span>Demo/testing mode. Saves messages to log/outbox but does not deliver to inboxes.</span><small>Safe for orientation</small></label>
        </div>
      </section>

      <section class="card form-grid" id="sender-identity">
        <div class="card-head wide"><div><span class="eyebrow">Step 2</span><h2>Sender identity</h2><p>This is the name and email recipients will see. For domain SMTP, the From email should normally match the SMTP mailbox.</p></div></div>
        <label>From name<input name="from_name" value="<?=e($mail['from_name']??'Dental Clinic')?>" required></label>
        <label>From email<input type="email" name="from_email" value="<?=e($mail['from_email']??'')?>" required></label>
      </section>

      <section class="card form-grid mail-path-panel" id="gmail-api-path">
        <div class="card-head wide"><div><span class="eyebrow">Path A</span><h2>Gmail API / Google Workspace</h2><p>Use this when the client uses Gmail or Google Workspace. The Gmail API path avoids SMTP certificate mismatch, blocked ports, and hosting relay confusion.</p></div><span class="badge <?= $gmailConnected?'success':'warn' ?>"><?= $gmailConnected?'OAuth token saved':'Needs OAuth' ?></span></div>
        <label>Google OAuth Client ID<input name="gmail_client_id" value="<?=e($gmail['client_id'])?>" placeholder="Google OAuth Client ID"></label>
        <label>Gmail sender email<input type="email" name="gmail_sender_email" value="<?=e($gmail['sender_email'])?>" placeholder="clinic@gmail.com"></label>
        <label>Google OAuth Client Secret<input type="password" name="gmail_client_secret" placeholder="Leave blank to keep saved secret"></label>
        <label>Refresh token<input type="password" name="gmail_refresh_token" placeholder="Use Connect Gmail to generate automatically"></label>
        <label>API timeout<input type="number" min="10" max="120" name="gmail_timeout" value="<?=e($gmail['timeout'])?>"></label>
        <div class="wide alert info"><strong>Recommended:</strong> Click Connect Gmail so DentalCare stores the refresh token automatically. Do not configure Gmail as cPanel SMTP unless the hosting path is verified.</div>
        <div class="wide status-actions"><a class="btn ghost" href="gmail-oauth">Connect Gmail / Get Refresh Token</a></div>
      </section>

      <section class="card form-grid mail-path-panel" id="domain-smtp-path">
        <div class="card-head wide"><div><span class="eyebrow">Path B</span><h2>Domain SMTP mailbox</h2><p>Use this for a domain mailbox or provider SMTP account. The safest first try for many domain mailboxes is port 465 with SSL/TLS.</p></div><span class="badge"><?=e((string)($smtp['host']?:'No host'))?></span></div>
        <label>SMTP host<input name="smtp_host" value="<?=e($smtp['host'])?>" placeholder="mail.yourdomain.com"></label>
        <label>SMTP port<input type="number" name="smtp_port" value="<?=e($smtp['port'])?>"></label>
        <label>Encryption<select name="smtp_encryption"><option value="ssl" <?=$smtp['encryption']==='ssl'?'selected':''?>>SSL/TLS — usually 465</option><option value="tls" <?=$smtp['encryption']==='tls'?'selected':''?>>STARTTLS — usually 587</option><option value="none" <?=$smtp['encryption']==='none'?'selected':''?>>None — not recommended</option></select></label>
        <label>Authentication<select name="smtp_auth_method"><option value="auto" <?=$smtp['auth_method']==='auto'?'selected':''?>>Auto</option><option value="login" <?=$smtp['auth_method']==='login'?'selected':''?>>LOGIN</option><option value="plain" <?=$smtp['auth_method']==='plain'?'selected':''?>>PLAIN</option></select></label>
        <label>SMTP username<input name="smtp_username" autocomplete="username" value="<?=e($smtp['username'])?>" placeholder="Full email address"></label>
        <label>SMTP password<input type="password" name="smtp_password" autocomplete="new-password" placeholder="Leave blank to keep saved password"></label>
        <details class="wide mail-advanced"><summary>Advanced SMTP routing and certificate options</summary><div class="form-grid nested-grid"><label>Connection timeout<input type="number" min="5" max="120" name="smtp_timeout" value="<?=e($smtp['timeout'])?>"></label><label>EHLO/local domain<input name="smtp_local_domain" value="<?=e($smtp['local_domain'])?>" placeholder="Optional server hostname"></label><label>Certificate host name<input name="smtp_peer_name" value="<?=e($smtp['peer_name'])?>" placeholder="Leave blank to use SMTP host"><small>Use only when the intended mail server certificate is issued to a different host name.</small></label><label class="choice wide"><input type="checkbox" name="smtp_verify_peer" value="1" <?=!empty($smtp['verify_peer'])?'checked':''?>><span><strong>Verify the SMTP TLS certificate</strong><small>Keep enabled in production. Do not disable it to force Gmail or hosted SMTP through the wrong route.</small></span></label></div></details>
        <div class="wide alert warning"><strong>Certificate rule:</strong> For Gmail/Google Workspace, choose Gmail API. For domain mail, use the exact SMTP host printed by the mailbox provider. Do not use Certificate host name as a workaround for a completely different server.</div>
      </section>

      <section class="card form-grid" id="php-log-path">
        <div class="card-head wide"><div><span class="eyebrow">Path C / D</span><h2>PHP mail() and Log only</h2><p>PHP mail is host-dependent and has fewer diagnostics. Log only is for demo, orientation, and troubleshooting where no real inbox delivery should happen.</p></div></div>
        <div class="wide coverage-grid"><span>PHP mail: no SMTP login fields required</span><span>Log only: no real delivery</span><span>Queue still records messages</span><span>Use tests before client onboarding</span></div>
      </section>

      <section class="card">
        <div class="status-actions"><button class="btn primary">Save Email Settings</button><?php if(superuser_primary_workspace()): ?><a class="btn ghost" href="system_setup.php?tab=email">Back to System Setup</a><?php else: ?><a class="btn ghost" href="administration.php">Back to Administration</a><?php endif; ?></div>
      </section>
    </form>
  </main>

  <aside class="mail-redesign-side">
    <section class="card"><h2>Unified delivery test</h2><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="test_connection"><button class="btn ghost">Connection diagnostic only</button></form><form method="post" class="form-grid compact-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="send_test"><label class="wide">Test recipient<input type="email" name="test_recipient" value="<?=e($user['email']??'')?>" required></label><button class="btn primary wide">Send using same path as password reset</button></form><p class="muted">This creates an outbox message and processes it through the same engine used by password resets, invitations, appointments, receipts, reminders, and portal messages. Connection diagnostic is separate and should not block the full delivery test.</p></section>
    <section class="card" id="email-queue-path"><h2>Automatic queue</h2><?php if($health['issues']):?><div class="alert warning"><strong>Delivery needs attention</strong><ul><?php foreach($health['issues'] as $issue):?><li><?=e((string)$issue)?></li><?php endforeach;?></ul></div><?php else:?><div class="alert success">Automatic delivery is healthy.</div><?php endif;?><section class="stats mini-stats"><?php stat_card('Pending',$queue['pending'],'Ready');stat_card('Retry',$queue['retry'],'Scheduled');stat_card('Failed',$queue['failed'],'Needs review');?></section><form method="post" class="form-grid compact-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="save_queue"><label class="choice wide"><input type="checkbox" name="automatic_enabled" value="1" <?=$queueConfig['enabled']?'checked':''?>><span><strong>Process automatically during normal system use</strong><small>No permanent cron job is required. A lock prevents duplicate workers.</small></span></label><label>Interval<input type="number" name="interval_minutes" min="1" max="60" value="<?=(int)$queueConfig['interval_minutes']?>"></label><label>Batch size<input type="number" name="batch_size" min="1" max="50" value="<?=(int)$queueConfig['batch_size']?>"></label><button class="btn ghost wide">Save Queue</button></form><p class="muted">Last run: <?=e($health['last_run_at']?:'Never')?><?=!empty($health['last_trigger'])?' · '.e((string)$health['last_trigger']):''?></p><form method="post" class="inline-actions"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="process_queue"><input type="number" name="queue_limit" min="1" max="100" value="20"><button class="btn primary">Process Now</button></form><?php if($queue['failed']):?><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="retry_failed"><button class="btn ghost" data-confirm="Return all failed emails to the pending queue?">Retry Failed</button></form><?php endif;?></section>
  </aside>
</div>

<section class="card mail-history-command" id="email-history">
  <div class="card-head"><div><span class="eyebrow">Scalable history</span><h2>Email activity</h2><p>Only one paginated history is loaded at a time. Empty automatic queue checks are no longer stored as run records.</p></div><?php if($historyType!=='overview'):?><a class="btn ghost" href="email_settings.php?history=overview#email-history">Back to summary</a><?php endif;?></div>
  <div class="mail-history-links">
    <a class="mail-history-link <?=$historyType==='delivery'?'active':''?>" href="email_settings.php?history=delivery#email-history"><strong>Delivery history</strong><span>Queued, accepted, retry, failed, and cancelled messages</span><small><?=number_format(array_sum($queue))?> current outbox rows</small></a>
    <a class="mail-history-link <?=$historyType==='runs'?'active':''?>" href="email_settings.php?history=runs#email-history"><strong>Automatic run history</strong><span>Only queue cycles that performed work or found a problem</span><small>Retained for <?=$retention['run_days']?> days</small></a>
    <a class="mail-history-link <?=$historyType==='diagnostics'?'active':''?>" href="email_settings.php?history=diagnostics#email-history"><strong>Diagnostics history</strong><span>Connection, authentication, delivery, and queue tests</span><small>Retained for <?=$retention['diagnostic_days']?> days</small></a>
  </div>
  <div class="alert info"><strong>Retention protection:</strong> unresolved pending, retry, processing, and failed messages are never removed automatically. Completed outbox rows are retained for <?=$retention['outbox_days']?> days; diagnostic transcripts are cleared after <?=$retention['transcript_days']?> days.</div>
  <?php if(superuser_primary_workspace()):?><details class="mail-retention-control"><summary>Superuser history retention and cleanup</summary><div class="mail-retention-grid"><form method="post" class="form-grid compact-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="save_retention"><label>Completed delivery days<input type="number" name="outbox_days" min="30" max="3650" value="<?=$retention['outbox_days']?>"></label><label>Email log days<input type="number" name="email_log_days" min="30" max="3650" value="<?=$retention['email_log_days']?>"></label><label>Automatic run days<input type="number" name="run_days" min="7" max="730" value="<?=$retention['run_days']?>"></label><label>Diagnostic days<input type="number" name="diagnostic_days" min="7" max="730" value="<?=$retention['diagnostic_days']?>"></label><label>Transcript days<input type="number" name="transcript_days" min="1" max="90" value="<?=$retention['transcript_days']?>"></label><button class="btn primary wide">Save retention</button></form><form method="post" class="retention-cleanup-form"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="run_history_cleanup"><p>Cleanup runs automatically at most once per day in bounded batches. Use this only when old installations already contain excessive history.</p><button class="btn ghost" data-confirm="Remove expired completed email history now? Pending, retry, processing, and failed messages will be preserved.">Clean expired history now</button></form></div></details><?php endif;?>
</section>

<?php if($historyType!=='overview'):?>
<section class="card server-list-card email-history-table">
  <div class="card-head"><div><h2><?=e($historyType==='delivery'?'Email delivery history':($historyType==='runs'?'Automatic delivery runs':'Email diagnostics'))?></h2><p><?=e($historyType==='delivery'?'Search and filter the outbox without loading the full table.':($historyType==='runs'?'No-op automatic checks are excluded from this history.':'Transcripts are available only during the protected transcript-retention period.'))?></p></div><form method="get" class="inline-form"><input type="hidden" name="history" value="<?=e($historyType)?>"><?php if($historyType==='delivery'):?><label>Search<input type="search" name="history_q" value="<?=e($historyQuery)?>" placeholder="Recipient, subject, or ID"></label><?php endif;?><label>Status<select name="history_status"><option value="">All statuses</option><?php $statuses=$historyType==='delivery'?['pending','processing','retry','sent','failed','cancelled']:($historyType==='runs'?['success','warning','failed','busy']:['success','warning','failed']);foreach($statuses as $statusOption):?><option value="<?=e($statusOption)?>" <?=$historyStatus===$statusOption?'selected':''?>><?=e(ucfirst($statusOption))?></option><?php endforeach;?></select></label><button class="btn primary">Apply</button><a class="btn ghost" href="email_settings.php?history=<?=e($historyType)?>#email-history">Reset</a></form></div>
  <?php module_render_server_pagination($historyTotal,$historyPage,$historyPerPage,'history_page','history_per_page',$historyType==='delivery'?'messages':($historyType==='runs'?'runs':'diagnostics'));?>
  <div class="table-wrap"><table>
  <?php if($historyType==='delivery'):?><thead><tr><th>Created</th><th>Recipient</th><th>Subject</th><th>Status</th><th>Attempts</th><th>Last error</th><th></th></tr></thead><tbody><?php foreach($historyRows as $message):?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$message['created_at'])))?></td><td><?=e((string)$message['recipient_email'])?></td><td><strong><?=e((string)$message['subject'])?></strong></td><td><span class="badge email-<?=e((string)$message['status'])?>"><?=e(email_delivery_label((string)$message['status']))?></span></td><td><?=(int)$message['attempts']?></td><td><?php if($message['last_error']):?><details><summary>View error</summary><small><?=e((string)$message['last_error'])?></small></details><?php else:?>—<?php endif;?></td><td><?php if(in_array((string)$message['status'],['failed','retry','pending'],true)):?><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="retry_one"><input type="hidden" name="outbox_id" value="<?=(int)$message['id']?>"><button class="btn ghost compact">Retry</button></form><?php endif;?></td></tr><?php endforeach;if(!$historyRows):?><tr><td colspan="7" class="muted">No delivery records match this view.</td></tr><?php endif;?></tbody>
  <?php elseif($historyType==='runs'):?><thead><tr><th>Started</th><th>Trigger</th><th>Status</th><th>Selected</th><th>Accepted</th><th>Retry</th><th>Failed</th><th>Recovered</th></tr></thead><tbody><?php foreach($historyRows as $run):?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$run['started_at'])))?></td><td><?=e(ucwords(str_replace('_',' ',(string)$run['trigger_type'])))?></td><td><span class="badge"><?=e(ucfirst((string)$run['status']))?></span></td><td><?=(int)$run['selected_count']?></td><td><?=(int)$run['sent_count']?></td><td><?=(int)$run['retry_count']?></td><td><?=(int)$run['failed_count']?></td><td><?=(int)$run['recovered_count']?></td></tr><?php endforeach;if(!$historyRows):?><tr><td colspan="8" class="muted">No automatic run records match this view.</td></tr><?php endif;?></tbody>
  <?php else:?><thead><tr><th>Date</th><th>Test</th><th>Status</th><th>Server</th><th>Result</th><th></th></tr></thead><tbody><?php foreach($historyRows as $diagnostic):?><tr><td><?=e(date('M j, Y g:i A',strtotime((string)$diagnostic['created_at'])))?></td><td><?=e(ucfirst((string)$diagnostic['test_type']))?></td><td><span class="badge smtp-<?=e((string)$diagnostic['status'])?>"><?=e(ucfirst((string)$diagnostic['status']))?></span></td><td><?=e(((string)($diagnostic['host']?:'—')).($diagnostic['port']?':'.$diagnostic['port']:''))?></td><td><?=e((string)$diagnostic['message'])?></td><td><?php if($diagnostic['transcript']):?><details><summary>Transcript</summary><pre class="smtp-transcript"><?=e((string)$diagnostic['transcript'])?></pre></details><?php else:?><span class="muted">Expired or unavailable</span><?php endif;?></td></tr><?php endforeach;if(!$historyRows):?><tr><td colspan="6" class="muted">No diagnostic records match this view.</td></tr><?php endif;?></tbody><?php endif;?>
  </table></div>
  <?php module_render_server_pagination($historyTotal,$historyPage,$historyPerPage,'history_page','history_per_page',$historyType==='delivery'?'messages':($historyType==='runs'?'runs':'diagnostics'));?>
</section>
<?php else:?>
<section class="card table-wrap"><div class="card-head"><div><h2>Messages requiring attention</h2><p>Only unresolved queue records are shown on the settings overview. Completed delivery history is available through the paginated view above.</p></div><a class="btn ghost" href="email_settings.php?history=delivery&amp;history_status=failed#email-history">Review failures</a></div><table><thead><tr><th>Created</th><th>Recipient</th><th>Subject</th><th>Status</th><th>Attempts</th><th>Last error</th></tr></thead><tbody><?php foreach($attentionRows as $message):?><tr><td><?=e(date('M j, g:i A',strtotime((string)$message['created_at'])))?></td><td><?=e((string)$message['recipient_email'])?></td><td><strong><?=e((string)$message['subject'])?></strong></td><td><span class="badge email-<?=e((string)$message['status'])?>"><?=e(email_delivery_label((string)$message['status']))?></span></td><td><?=(int)$message['attempts']?></td><td><?=e((string)($message['last_error']?:'—'))?></td></tr><?php endforeach;if(!$attentionRows):?><tr><td colspan="6" class="muted">No pending, retry, processing, or failed email requires attention.</td></tr><?php endif;?></tbody></table></section>
<?php endif;?>
<?php render_footer();
