<?php
// optimized_fetch_emails.php
// Strategy: UID Incremental Sync (Saves 99% Bandwidth)

declare(strict_types=1);

// 🔐 CLI ONLY (Security: prevents web-based execution)
// Uncomment the lines below after your initial browser sync is complete!

if (php_sapi_name() !== 'cli') {
    http_response_code(403);
    exit('Forbidden: This script must be run via Cron/CLI.');
}


set_time_limit(0);
error_reporting(E_ALL);
ini_set('display_errors', '0');

// Database Connection
require __DIR__ . '/includes/dbconnection.php';

/**
 * Logs messages to the terminal/cron/browser output
 */
function logMessage(string $msg): void
{
    echo "[" . date('Y-m-d H:i:s') . "] $msg\n";
    // Flush buffer for real-time browser feedback
    if (php_sapi_name() !== 'cli') {
        ob_flush();
        flush();
    }
}

/**
 * Loads email credentials from .env file
 */
function getEnvEmails(): array
{
    $envPath = __DIR__ . '/.env';
    if (!file_exists($envPath))
        return [];

    $lines = file($envPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    $accounts = [];

    foreach ($lines as $line) {
        if (strpos($line, '=') !== false && strpos(trim($line), '#') !== 0) {
            [$key, $value] = explode('=', $line, 2);
            $key = strtoupper(trim($key));
            $value = trim($value, "\" ");

            if (str_ends_with($key, '_EMAIL')) {
                $prefix = substr($key, 0, -6);
                $accounts[$prefix]['email'] = $value;
            } elseif (str_ends_with($key, '_PASS')) {
                $prefix = substr($key, 0, -5);
                $accounts[$prefix]['password'] = $value;
            }
        }
    }

    $result = [];
    foreach ($accounts as $acc) {
        if (!empty($acc['email']) && !empty($acc['password'])) {
            $result[$acc['email']] = $acc;
        }
    }
    return $result;
}

/**
 * Gets the highest UID already processed for a specific account
 */
function getLastUID(mysqli $con, string $email): int
{
    $stmt = $con->prepare("SELECT MAX(uid) as last_uid FROM emails WHERE email_account = ?");
    $stmt->bind_param('s', $email);
    $stmt->execute();
    $res = $stmt->get_result()->fetch_assoc();
    return (int) ($res['last_uid'] ?? 0);
}

/**
 * Safely fetches and decodes the email body based on its encoding type
 */
function getMessageBody($inbox, int $msgNumber): string
{
    $structure = imap_fetchstructure($inbox, $msgNumber);

    if (!isset($structure->parts)) {
        $partNumber = "1";
        $encoding = $structure->encoding ?? 0;
    } else {
        $partNumber = "1";
        $encoding = 0;
        foreach ($structure->parts as $index => $part) {
            if ($part->type == 0 && strtolower($part->subtype) == 'html') {
                $partNumber = (string) ($index + 1);
                $encoding = $part->encoding;
                break;
            }
            if ($part->type == 0 && strtolower($part->subtype) == 'plain') {
                $partNumber = (string) ($index + 1);
                $encoding = $part->encoding;
            }
        }
    }

    $body = imap_fetchbody($inbox, $msgNumber, $partNumber);

    switch ($encoding) {
        case 3:
            $body = base64_decode($body);
            break;
        case 4:
            $body = quoted_printable_decode($body);
            break;
    }
    return trim($body);
}

// --- START PROCESSING ---

$accounts = getEnvEmails();
if (empty($accounts)) {
    logMessage("Error: No accounts found in .env.");
    exit;
}

$hostname = '{mail.acionlineportal.com.ng:993/imap/ssl/novalidate-cert}INBOX';

foreach ($accounts as $email => $info) {
    logMessage("Checking: $email");

    $inbox = @imap_open($hostname, $email, $info['password']);
    if (!$inbox) {
        logMessage("Failed to connect to $email. Error: " . imap_last_error());
        continue;
    }

    $lastUID = getLastUID($con, $email);

    // --- INTEGRATED SEARCH LOGIC ---
// --- REFINED SEARCH LOGIC ---
    if ($lastUID === 0) {
        logMessage("Performing initial full sync for $email...");
        $emails = imap_search($inbox, 'ALL', SE_UID);
    } else {
        // Instead of UID range search which can be finicky across servers,
        // search for all UIDs and filter locally, OR use the correct sequence syntax.
        // Try this syntax first:
        $emails = imap_search($inbox, "UID " . ($lastUID + 1) . ":*", SE_UID);

        // Fallback: If UID search returns nothing but you suspect new mail, 
        // it might be because the server doesn't support that specific range syntax.
        if (!$emails) {
            // Search for UNSEEN as a backup if UID range fails
            $emails = imap_search($inbox, 'UNSEEN', SE_UID);
        }
    }
    // -------------------------------

    if (!$emails) {
        logMessage("No emails found for $email (Last UID: $lastUID)");
        imap_close($inbox);
        continue;
    }

    sort($emails);

    foreach ($emails as $uid) {
        if ($uid <= $lastUID && $lastUID !== 0)
            continue;

        $msgNumber = imap_msgno($inbox, $uid);
        if (!$msgNumber)
            continue;

        $header = imap_headerinfo($inbox, $msgNumber);

        $fromEmail = '';
        if (isset($header->from[0]->mailbox, $header->from[0]->host)) {
            $fromEmail = strtolower($header->from[0]->mailbox . '@' . $header->from[0]->host);
        }

        if (!filter_var($fromEmail, FILTER_VALIDATE_EMAIL))
            continue;
        if (preg_match('/(mailer-daemon|postmaster|no-reply)/i', $fromEmail))
            continue;

        $subject = isset($header->subject) ? imap_utf8($header->subject) : '(No Subject)';
        $body = getMessageBody($inbox, $msgNumber);
        $timestamp = date('Y-m-d H:i:s', strtotime($header->date));
        $message_id = strtolower(trim($header->message_id ?? uniqid('msg_', true)));

        $stmt = $con->prepare("
            INSERT INTO emails 
            (email_account, sender, subject, body, timestamp, folder, message_id, uid, read_status) 
            VALUES (?, ?, ?, ?, ?, 'INBOX', ?, ?, 0)
            ON DUPLICATE KEY UPDATE uid = VALUES(uid), timestamp = VALUES(timestamp)
        ");

        $stmt->bind_param(
            'ssssssi',
            $email,
            $fromEmail,
            $subject,
            $body,
            $timestamp,
            $message_id,
            $uid
        );

        if ($stmt->execute()) {
            if ($stmt->affected_rows === 1) {
                logMessage("Inserted New UID: $uid");
            } else {
                logMessage("Updated Existing UID: $uid");
            }
        }
        $stmt->close();
    }

    imap_close($inbox);
    logMessage("Finished: $email\n");
}

logMessage("Sync process complete.");

?>