<?php
/**
 * google_oauth.php
 *
 * Small helper library for "Sign in with Google" used to connect a
 * merchant's FamPay Gmail inbox instead of asking them to paste a Gmail
 * App Password. Client ID / Secret / Redirect URI come from the
 * `site_settings` table (Website Manage / sitesetting.php admin page).
 *
 * Scopes requested: read-only Gmail access (to detect "money received"
 * mails, same job fampay_mail_check.php was already doing via IMAP) plus
 * the user's email address.
 */

if (!defined('GOOGLE_OAUTH_SCOPE')) {
    define('GOOGLE_OAUTH_SCOPE', 'openid email https://www.googleapis.com/auth/gmail.readonly');
}

/**
 * Builds the Google OAuth consent screen URL.
 */
function google_oauth_authorize_url($state, $site_settings) {
    $params = [
        'client_id'              => $site_settings['google_client_id'],
        'redirect_uri'           => $site_settings['google_redirect_uri'],
        'response_type'          => 'code',
        'scope'                  => GOOGLE_OAUTH_SCOPE,
        'access_type'            => 'offline', // needed to get a refresh_token
        'prompt'                 => 'consent', // force refresh_token every time
        'include_granted_scopes' => 'true',
        'state'                  => $state,
    ];
    return 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query($params);
}

/**
 * Low-level POST helper (cURL) that returns the decoded JSON response.
 */
function google_oauth_http_post($url, $fields) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
    $response = curl_exec($ch);
    $err = curl_error($ch);
    curl_close($ch);
    if ($response === false) {
        return ['error' => $err ?: 'curl_failed'];
    }
    $decoded = json_decode($response, true);
    return is_array($decoded) ? $decoded : ['error' => 'invalid_json_response'];
}

/**
 * Exchanges the ?code=... Google sent back for access_token / refresh_token.
 */
function google_oauth_exchange_code($code, $site_settings) {
    $res = google_oauth_http_post('https://oauth2.googleapis.com/token', [
        'code'          => $code,
        'client_id'     => $site_settings['google_client_id'],
        'client_secret' => $site_settings['google_client_secret'],
        'redirect_uri'  => $site_settings['google_redirect_uri'],
        'grant_type'    => 'authorization_code',
    ]);
    return isset($res['access_token']) ? $res : false;
}

/**
 * Uses a stored refresh_token to get a fresh access_token.
 */
function google_oauth_refresh($refresh_token, $site_settings) {
    $res = google_oauth_http_post('https://oauth2.googleapis.com/token', [
        'refresh_token' => $refresh_token,
        'client_id'     => $site_settings['google_client_id'],
        'client_secret' => $site_settings['google_client_secret'],
        'grant_type'    => 'refresh_token',
    ]);
    return isset($res['access_token']) ? $res : false;
}

/**
 * Fetches the connected Google account's email address.
 */
function google_oauth_get_userinfo($access_token) {
    $ch = curl_init('https://www.googleapis.com/oauth2/v3/userinfo');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $access_token]);
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
    $response = curl_exec($ch);
    curl_close($ch);
    $decoded = json_decode($response, true);
    return is_array($decoded) ? $decoded : false;
}

/**
 * Returns a valid (non-expired) access_token for a fampay_tokens row,
 * refreshing + persisting it via the refresh_token when needed.
 *
 * $fampayRow must contain: id, refresh_token, access_token, token_expiry.
 * Returns null if there's no refresh_token (legacy / not-OAuth-connected
 * account) or if the refresh call fails.
 */
function google_oauth_get_valid_access_token($conn, $fampayRow, $site_settings) {
    if (empty($fampayRow['refresh_token'])) {
        return null;
    }

    $notExpiredYet = !empty($fampayRow['token_expiry']) && (int)$fampayRow['token_expiry'] > (time() + 60);
    if ($notExpiredYet && !empty($fampayRow['access_token'])) {
        return $fampayRow['access_token'];
    }

    $refreshed = google_oauth_refresh($fampayRow['refresh_token'], $site_settings);
    if (!$refreshed) {
        return null;
    }

    $newAccessToken = $refreshed['access_token'];
    $newExpiry = time() + (int)($refreshed['expires_in'] ?? 3300);

    $accessTokenEsc = mysqli_real_escape_string($conn, $newAccessToken);
    $id = (int)$fampayRow['id'];
    mysqli_query($conn, "UPDATE fampay_tokens SET access_token='$accessTokenEsc', token_expiry=$newExpiry WHERE id=$id");

    return $newAccessToken;
}
