<?php
// src/OAuth.php - Google OAuth 2.0 Authentication Handler

class OAuth {
    private $client_id;
    private $client_secret;
    private $redirect_uri;
    private $scopes = [
        'https://www.googleapis.com/auth/admob.readonly',
        'https://www.googleapis.com/auth/admob.report',
        'https://www.googleapis.com/auth/userinfo.email',
        'https://www.googleapis.com/auth/userinfo.profile'
    ];

    public function __construct($client_id, $client_secret, $redirect_uri) {
        $this->client_id = $client_id;
        $this->client_secret = $client_secret;
        $this->redirect_uri = $redirect_uri;
    }

    /**
     * Generate authorization URL
     */
    public function getAuthorizationUrl($state = null) {
        if ($state === null) {
            $state = bin2hex(random_bytes(16));
        }

        $params = [
            'client_id' => $this->client_id,
            'redirect_uri' => $this->redirect_uri,
            'response_type' => 'code',
            'scope' => implode(' ', $this->scopes),
            'access_type' => 'offline',
            'prompt' => 'consent',
            'state' => $state
        ];

        return 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query($params);
    }

    /**
     * Exchange authorization code for access tokens
     */
    public function exchangeCodeForTokens($code) {
        $token_url = 'https://oauth2.googleapis.com/token';
        
        $post_data = [
            'code' => $code,
            'client_id' => $this->client_id,
            'client_secret' => $this->client_secret,
            'redirect_uri' => $this->redirect_uri,
            'grant_type' => 'authorization_code'
        ];

        $ch = curl_init($token_url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded'
        ]);

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if (curl_errno($ch)) {
            $error = curl_error($ch);
            curl_close($ch);
            throw new Exception('cURL error: ' . $error);
        }
        
        curl_close($ch);

        if ($http_code !== 200) {
            $error_data = json_decode($response, true);
            $error_message = $error_data['error_description'] ?? $error_data['error'] ?? 'Unknown error';
            throw new Exception('Token exchange failed: ' . $error_message);
        }

        return json_decode($response, true);
    }

    /**
     * Get user info from Google
     */
    public function getUserInfo($access_token) {
        $user_info_url = 'https://www.googleapis.com/oauth2/v2/userinfo';

        $ch = curl_init($user_info_url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $access_token
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if (curl_errno($ch)) {
            $error = curl_error($ch);
            curl_close($ch);
            throw new Exception('cURL error: ' . $error);
        }
        
        curl_close($ch);

        if ($http_code !== 200) {
            $error_data = json_decode($response, true);
            $error_message = $error_data['error']['message'] ?? 'Failed to get user info';
            throw new Exception($error_message);
        }

        return json_decode($response, true);
    }

    /**
     * Refresh access token using refresh token
     */
    public function refreshAccessToken($refresh_token) {
        $token_url = 'https://oauth2.googleapis.com/token';
        
        $post_data = [
            'refresh_token' => $refresh_token,
            'client_id' => $this->client_id,
            'client_secret' => $this->client_secret,
            'grant_type' => 'refresh_token'
        ];

        $ch = curl_init($token_url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded'
        ]);

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if (curl_errno($ch)) {
            $error = curl_error($ch);
            curl_close($ch);
            throw new Exception('cURL error: ' . $error);
        }
        
        curl_close($ch);

        if ($http_code !== 200) {
            $error_data = json_decode($response, true);
            $error_message = $error_data['error_description'] ?? $error_data['error'] ?? 'Unknown error';
            throw new Exception('Token refresh failed: ' . $error_message);
        }

        return json_decode($response, true);
    }

    /**
     * Revoke access token
     */
    public function revokeToken($token) {
        $revoke_url = 'https://oauth2.googleapis.com/revoke';
        
        $post_data = [
            'token' => $token
        ];

        $ch = curl_init($revoke_url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded'
        ]);

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        curl_close($ch);

        return $http_code === 200;
    }

    /**
     * Ensure valid access token for user
     */
    public function ensureValidToken($user_id) {
        require_once __DIR__ . '/Database.php';
        
        $db = Database::getInstance();
        
        // Get token from database
        $stmt = $db->prepare("
            SELECT access_token, refresh_token, expires_at 
            FROM oauth_tokens 
            WHERE user_id = :user_id 
            LIMIT 1
        ");
        
        $stmt->execute([':user_id' => $user_id]);
        $token_data = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$token_data) {
            return null;
        }
        
        // Check if token is expired
        $expires_at = strtotime($token_data['expires_at']);
        
        if (time() >= $expires_at - 300) { // Refresh if expires in 5 minutes
            // Token expired or about to expire, refresh it
            if (!empty($token_data['refresh_token'])) {
                try {
                    $new_tokens = $this->refreshAccessToken($token_data['refresh_token']);
                    
                    // Update database with new tokens
                    $new_expires_at = date('Y-m-d H:i:s', time() + ($new_tokens['expires_in'] ?? 3600));
                    
                    $stmt = $db->prepare("
                        UPDATE oauth_tokens 
                        SET access_token = :access_token,
                            expires_at = :expires_at,
                            updated_at = NOW()
                        WHERE user_id = :user_id
                    ");
                    
                    $stmt->execute([
                        ':access_token' => $new_tokens['access_token'],
                        ':expires_at' => $new_expires_at,
                        ':user_id' => $user_id
                    ]);
                    
                    return $new_tokens['access_token'];
                } catch (Exception $e) {
                    error_log('Token refresh error: ' . $e->getMessage());
                    return null;
                }
            }
            
            return null;
        }
        
        return $token_data['access_token'];
    }

    /**
     * Validate access token
     */
    public function validateToken($access_token) {
        $validate_url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' . urlencode($access_token);

        $ch = curl_init($validate_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($http_code === 200) {
            return json_decode($response, true);
        }

        return false;
    }
}
?>