<?php
require_once __DIR__ . '/config.php';

// ─── Security ────────────────────────────────────────────────
function csrf_token(): string {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}
function csrf_field(): string {
    return '<input type="hidden" name="csrf_token" value="' . csrf_token() . '">';
}
function verify_csrf(): bool {
    return isset($_POST['csrf_token']) && hash_equals(csrf_token(), $_POST['csrf_token']);
}
function sanitize(string $val): string {
    return htmlspecialchars(trim($val), ENT_QUOTES, 'UTF-8');
}
function flash(string $key, string $msg): void {
    $_SESSION['flash'][$key] = $msg;
}
function get_flash(string $key): string {
    $msg = $_SESSION['flash'][$key] ?? '';
    unset($_SESSION['flash'][$key]);
    return $msg;
}

// ─── Format helpers ──────────────────────────────────────────
function money(float $amount, string $currency = 'USD'): string {
    $symbols = ['USD'=>'$','GBP'=>'£','EUR'=>'€','NGN'=>'₦','CAD'=>'CA$','SGD'=>'S$'];
    $sym = $symbols[$currency] ?? $currency . ' ';
    return $sym . number_format($amount, 2);
}
function timeAgo(string $datetime): string {
    $diff = time() - strtotime($datetime);
    if ($diff < 60) return 'Just now';
    if ($diff < 3600) return floor($diff/60) . 'm ago';
    if ($diff < 86400) return floor($diff/3600) . 'h ago';
    if ($diff < 604800) return floor($diff/86400) . 'd ago';
    return date('M j, Y', strtotime($datetime));
}
function formatDate(string $dt, string $fmt = 'M j, Y g:i A'): string {
    return date($fmt, strtotime($dt));
}
function maskAccount(string $acc): string {
    return '****' . substr($acc, -4);
}
function generateRef(string $prefix = 'FLE'): string {
    return $prefix . '/' . strtoupper(bin2hex(random_bytes(5))) . '-' . date('dm');
}
function generateAccountNumber(): string {
    return (string)rand(1000000000, 9999999999);
}
function generateOTP(): string {
    return str_pad((string)random_int(0, 999999), 6, '0', STR_PAD_LEFT);
}

// ─── DB helpers ──────────────────────────────────────────────
function getUserById(PDO $pdo, int $id): ?array {
    $s = $pdo->prepare("SELECT * FROM users WHERE id = ? LIMIT 1");
    $s->execute([$id]);
    return $s->fetch() ?: null;
}
function getAdminById(PDO $pdo, int $id): ?array {
    $s = $pdo->prepare("SELECT * FROM admin_users WHERE id = ? LIMIT 1");
    $s->execute([$id]);
    return $s->fetch() ?: null;
}
function logActivity(PDO $pdo, ?int $userId, ?int $adminId, string $action, string $description = ''): void {
    $ip = $_SERVER['REMOTE_ADDR'] ?? '';
    $ua = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 500);
    $s = $pdo->prepare("INSERT INTO activity_logs (user_id,admin_id,action,description,ip_address,user_agent) VALUES (?,?,?,?,?,?)");
    $s->execute([$userId, $adminId, $action, $description, $ip, $ua]);
}
function addNotification(PDO $pdo, int $userId, string $title, string $message, string $type = 'info', ?int $relId = null, ?string $relType = null): void {
    $s = $pdo->prepare("INSERT INTO notifications (user_id,title,message,type,related_id,related_type) VALUES (?,?,?,?,?,?)");
    $s->execute([$userId, $title, $message, $type, $relId, $relType]);
}
function creditAccount(PDO $pdo, int $userId, float $amount, string $description, string $ref = '', string $type = 'credit'): bool {
    if ($ref === '') $ref = generateRef();
    $pdo->beginTransaction();
    try {
        $pdo->prepare("UPDATE users SET account_balance = account_balance + ?, available_balance = available_balance + ? WHERE id = ?")->execute([$amount, $amount, $userId]);
        $pdo->prepare("INSERT INTO transactions (user_id,transaction_type,amount,currency,description,reference_number,status,processed_at) VALUES (?,?,?,(SELECT currency FROM users WHERE id=? LIMIT 1),?,?,'completed',NOW())")->execute([$userId, $type, $amount, $userId, $description, $ref]);
        $pdo->commit();
        return true;
    } catch (Exception $e) {
        $pdo->rollBack();
        return false;
    }
}
function debitAccount(PDO $pdo, int $userId, float $amount, string $description, string $ref = '', array $extras = []): bool {
    if ($ref === '') $ref = generateRef();
    $pdo->beginTransaction();
    try {
        $pdo->prepare("UPDATE users SET account_balance = account_balance - ?, available_balance = available_balance - ? WHERE id = ?")->execute([$amount, $amount, $userId]);
        $cols = 'user_id,transaction_type,amount,fee,currency,description,reference_number,status,beneficiary_name,beneficiary_account,beneficiary_bank,beneficiary_swift,transfer_type,processed_at';
        $pdo->prepare("INSERT INTO transactions ($cols) VALUES (?,?,?,?,(SELECT currency FROM users WHERE id=? LIMIT 1),?,?,'completed',?,?,?,?,?,NOW())")->execute([
            $userId, 'debit', $amount, $extras['fee'] ?? 0, $userId,
            $description, $ref,
            $extras['ben_name'] ?? null, $extras['ben_account'] ?? null,
            $extras['ben_bank'] ?? null, $extras['ben_swift'] ?? null,
            $extras['transfer_type'] ?? 'local',
        ]);
        $pdo->commit();
        return true;
    } catch (Exception $e) {
        $pdo->rollBack();
        return false;
    }
}

// ─── OTP helpers ─────────────────────────────────────────────
function createOTP(PDO $pdo, int $userId, string $purpose): string {
    $code = generateOTP();
    $pdo->prepare("DELETE FROM otp_codes WHERE user_id=? AND purpose=?")->execute([$userId, $purpose]);
    $expires = date('Y-m-d H:i:s', time() + OTP_EXPIRY);
    $pdo->prepare("INSERT INTO otp_codes (user_id,code,purpose,expires_at) VALUES (?,?,?,?)")->execute([$userId, $code, $purpose, $expires]);
    return $code;
}
function verifyOTP(PDO $pdo, int $userId, string $code, string $purpose): bool {
    $s = $pdo->prepare("SELECT id FROM otp_codes WHERE user_id=? AND code=? AND purpose=? AND used=0 AND expires_at > NOW() LIMIT 1");
    $s->execute([$userId, $code, $purpose]);
    $row = $s->fetch();
    if ($row) {
        $pdo->prepare("UPDATE otp_codes SET used=1 WHERE id=?")->execute([$row['id']]);
        return true;
    }
    return false;
}

// ─── Email (PHPMailer stub – wire up your SMTP) ───────────────
function sendEmail(string $toEmail, string $toName, string $subject, string $htmlBody): bool {
    // Requires PHPMailer. Install via composer: composer require phpmailer/phpmailer
    // Then uncomment and configure:
    /*
    use PHPMailer\PHPMailer\PHPMailer;
    $mail = new PHPMailer(true);
    $mail->isSMTP();
    $mail->Host       = 'smtp.yourdomain.com';
    $mail->SMTPAuth   = true;
    $mail->Username   = 'smtp_user';
    $mail->Password   = 'smtp_pass';
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
    $mail->Port       = 587;
    $mail->setFrom(SITE_EMAIL, SITE_NAME);
    $mail->addAddress($toEmail, $toName);
    $mail->isHTML(true);
    $mail->Subject = $subject;
    $mail->Body    = $htmlBody;
    return $mail->send();
    */
    return true; // Remove this line when PHPMailer is configured
}

function sendOTPEmail(string $email, string $name, string $otp, string $purpose): bool {
    $purposeLabel = ucfirst(str_replace('_', ' ', $purpose));
    $html = "
    <div style='font-family:Arial,sans-serif;max-width:600px;margin:auto;background:#f5f5f5;padding:30px;border-radius:10px;'>
        <div style='background:#c0392b;padding:20px;border-radius:8px 8px 0 0;text-align:center;'>
            <h1 style='color:#fff;margin:0;font-size:24px;'>Flexi Access Bank</h1>
        </div>
        <div style='background:#fff;padding:30px;border-radius:0 0 8px 8px;'>
            <h2 style='color:#333;'>One-Time Password</h2>
            <p>Dear $name,</p>
            <p>Your OTP for <strong>$purposeLabel</strong> is:</p>
            <div style='background:#f8f9fa;border:2px dashed #c0392b;padding:20px;text-align:center;border-radius:8px;margin:20px 0;'>
                <span style='font-size:36px;font-weight:bold;color:#c0392b;letter-spacing:10px;'>$otp</span>
            </div>
            <p>This code expires in <strong>10 minutes</strong>. Do not share it with anyone.</p>
            <p style='color:#999;font-size:12px;margin-top:30px;'>If you did not request this, please contact support immediately.</p>
        </div>
    </div>";
    return sendEmail($email, $name, SITE_NAME . ': Your OTP Code', $html);
}

// ─── File upload helper ───────────────────────────────────────
function uploadFile(array $file, string $destDir, array $allowedTypes = ['image/jpeg','image/png','image/gif','application/pdf'], int $maxBytes = 5242880): string|false {
    if ($file['error'] !== UPLOAD_ERR_OK) return false;
    if ($file['size'] > $maxBytes) return false;
    if (!in_array(mime_content_type($file['tmp_name']), $allowedTypes)) return false;
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    $name = strtoupper(bin2hex(random_bytes(6))) . date('YmdHis') . '.' . strtolower($ext);
    if (!is_dir($destDir)) mkdir($destDir, 0755, true);
    if (!move_uploaded_file($file['tmp_name'], $destDir . $name)) return false;
    return $name;
}

// ─── Status badge helper ─────────────────────────────────────
function statusBadge(string $status): string {
    $map = [
        'active'    => 'success', 'completed' => 'success', 'verified' => 'success',
        'approved'  => 'success', 'credited'  => 'success', 'paid'     => 'success',
        'pending'   => 'warning', 'processing'=> 'warning', 'under_review' => 'warning',
        'open'      => 'warning', 'in_progress'=> 'primary',
        'suspended' => 'danger',  'rejected'  => 'danger',  'failed'   => 'danger',
        'blocked'   => 'danger',  'cancelled' => 'secondary', 'closed' => 'secondary',
        'frozen'    => 'info',    'matured'   => 'info',
    ];
    $cls = $map[$status] ?? 'secondary';
    return '<span class="badge bg-' . $cls . '">' . ucfirst(str_replace('_', ' ', $status)) . '</span>';
}
