<?php
// /mobile/remember_me.php
if (!function_exists('sa_ip_bin')) {
    function sa_ip_bin(): ?string {
        $ip = $_SERVER['REMOTE_ADDR'] ?? '';
        $bin = @inet_pton($ip);
        return $bin !== false ? $bin : null;
    }
}

if (!function_exists('sa_secure_cookie_set')) {
    function sa_secure_cookie_set(string $name, string $value, int $days = 365): void {
        $expire = time() + (86400 * $days);
        $params = session_get_cookie_params();
        setcookie($name, $value, [
            'expires'  => $expire,
            'path'     => $params['path'] ?? '/',
            'domain'   => $params['domain'] ?? '',
            'secure'   => true,           // IMPORTANT (HTTPS)
            'httponly' => true,           // JS cannot read
            'samesite' => 'Lax',
        ]);
    }
}

if (!function_exists('sa_secure_cookie_clear')) {
    function sa_secure_cookie_clear(string $name): void {
        $params = session_get_cookie_params();
        setcookie($name, '', [
            'expires'  => time() - 3600,
            'path'     => $params['path'] ?? '/',
            'domain'   => $params['domain'] ?? '',
            'secure'   => true,
            'httponly' => true,
            'samesite' => 'Lax',
        ]);
    }
}

/**
 * Issue a new persistent token (selector + validator) for a user.
 * - Writes to DB
 * - Sets cookie "rm" = base64(selector) . '|' . base64(validator)
 */
if (!function_exists('sa_remember_issue')) {
    function sa_remember_issue(mysqli $db, int $user_id, int $days = 365): void {
        $selector  = random_bytes(12);
        $validator = random_bytes(32);
        $tokenHash = hash('sha256', $validator, true);

        $ua  = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 255);
        $ipb = sa_ip_bin();

        $expires = (new DateTimeImmutable('+'.$days.' days'))->format('Y-m-d H:i:s');

        $sql = "INSERT INTO auth_remember_tokens (user_id, selector, token_hash, user_agent, ip_address, expires_at, last_used_at)
                VALUES (?, ?, ?, ?, ?, ?, NOW())";
        $stmt = $db->prepare($sql);
        $stmt->bind_param('isssss', $user_id, $selector, $tokenHash, $ua, $ipb, $expires);
        $stmt->send_long_data(1, $selector);
        $stmt->send_long_data(2, $tokenHash);
        $stmt->execute();
        $stmt->close();

        $cookie = base64_encode($selector) . '|' . base64_encode($validator);
        sa_secure_cookie_set('rm', $cookie, $days);
    }
}

/**
 * Clear ALL remember tokens for a user (e.g., on logout)
 */
if (!function_exists('sa_remember_clear_all')) {
    function sa_remember_clear_all(mysqli $db, int $user_id): void {
        $stmt = $db->prepare("DELETE FROM auth_remember_tokens WHERE user_id = ?");
        $stmt->bind_param('i', $user_id);
        $stmt->execute();
        $stmt->close();
        sa_secure_cookie_clear('rm');
    }
}

/**
 * Auto-login using "rm" cookie (if session not present).
 * On success: rotates validator (+ cookie), sets $_SESSION['auth'].
 */
if (!function_exists('sa_remember_autologin')) {
    function sa_remember_autologin(mysqli $db, callable $loadUserById): void {
        if (!empty($_SESSION['auth'])) return; // already logged in

        $cookie = $_COOKIE['rm'] ?? '';
        if (!$cookie || strpos($cookie, '|') === false) return;

        list($selB64, $valB64) = explode('|', $cookie, 2);
        $selector  = base64_decode($selB64, true);
        $validator = base64_decode($valB64, true);
        if ($selector === false || $validator === false) return;

        $stmt = $db->prepare("SELECT id, user_id, token_hash, expires_at FROM auth_remember_tokens WHERE selector = ? LIMIT 1");
        $stmt->bind_param('s', $selector);
        $stmt->send_long_data(0, $selector);
        $stmt->execute();
        $stmt->bind_result($rid, $user_id, $token_hash, $expires_at);
        if (!$stmt->fetch()) { $stmt->close(); return; }
        $stmt->close();

        // Expired?
        if (new DateTimeImmutable($expires_at) < new DateTimeImmutable('now')) {
            // remove this token
            $del = $db->prepare("DELETE FROM auth_remember_tokens WHERE id = ?");
            $del->bind_param('i', $rid);
            $del->execute();
            $del->close();
            sa_secure_cookie_clear('rm');
            return;
        }

        // Verify validator
        $calc = hash('sha256', $validator, true);
        if (!hash_equals($token_hash, $calc)) {
            // Possible theft; delete this token
            $del = $db->prepare("DELETE FROM auth_remember_tokens WHERE id = ?");
            $del->bind_param('i', $rid);
            $del->execute();
            $del->close();
            sa_secure_cookie_clear('rm');
            return;
        }

        // Ok — load user + set session
        $user = $loadUserById($db, (int)$user_id);
        if (!$user) {
            // Orphan token — clean up
            $del = $db->prepare("DELETE FROM auth_remember_tokens WHERE id = ?");
            $del->bind_param('i', $rid);
            $del->execute();
            $del->close();
            sa_secure_cookie_clear('rm');
            return;
        }
        $_SESSION['auth'] = $user;

        // Rotate validator for this token (defense in depth)
        $newValidator = random_bytes(32);
        $newHash      = hash('sha256', $newValidator, true);
        $upd = $db->prepare("UPDATE auth_remember_tokens SET token_hash = ?, last_used_at = NOW() WHERE id = ?");
        $upd->bind_param('si', $newHash, $rid);
        $upd->send_long_data(0, $newHash);
        $upd->execute();
        $upd->close();

        // Refresh cookie (same selector, new validator)
        $cookie = base64_encode($selector) . '|' . base64_encode($newValidator);
        sa_secure_cookie_set('rm', $cookie, 365);
    }
}
