<?php
/**
 * OAuth backend resolver.
 *
 * @package NimblyMail\SMTP
 */

namespace NimblyMail\SMTP\OAuth;

use NimblyMail\SMTP\OAuth\Contracts\OAuthBackend;
use NimblyMail\SMTP\Options;

defined( 'ABSPATH' ) || exit;

/**
 * Class BackendFactory
 *
 * Resolves the appropriate {@see OAuthBackend} for a provider based on the
 * stored `auth_method` setting. Mailers and the disconnect endpoint use this
 * so a single caller handles both hosted-proxy and bring-your-own-keys
 * installs without branching.
 *
 * @since 1.0.0
 */
class BackendFactory {

    /**
     * Resolve a backend for the given OAuth provider.
     *
     * Reads the provider's `auth_method` option ('hosted' default) and
     * returns either a {@see ProxyClient} configured with the
     * proxy-issued install identity or a {@see DirectClient} configured
     * with the user-supplied client credentials.
     *
     * @since 1.0.0
     *
     * @param string $provider OAuth provider slug ('google' | 'microsoft').
     *
     * @return OAuthBackend
     */
    public static function for_provider( string $provider ): OAuthBackend {
        $option_group = self::provider_to_option_group( $provider );
        $options      = Options::init();
        $auth_method  = (string) $options->get( $option_group, 'auth_method' );

        if ( 'byok' === $auth_method ) {
            // Pass BOTH access_token and refresh_token so DirectClient::revoke()
            // can prefer the refresh_token for Google (it invalidates the whole
            // grant) and only fall back to the access_token if no refresh was
            // ever issued.
            return new DirectClient(
                $provider,
                (string) $options->get( $option_group, 'client_id' ),
                (string) $options->get( $option_group, 'client_secret' ),
                (string) $options->get( $option_group, 'tenant' ),
                (string) $options->get( $option_group, 'access_token' ),
                (string) $options->get( $option_group, 'refresh_token' )
            );
        }

        return new ProxyClient(
            $provider,
            (string) $options->get( $option_group, 'install_id' ),
            (string) $options->get( $option_group, 'install_secret' )
        );
    }

    /**
     * Map an OAuth provider slug to its Options group key.
     *
     * @since 1.0.0
     *
     * @param string $provider OAuth provider slug.
     *
     * @return string Options group key.
     */
    private static function provider_to_option_group( string $provider ): string {
        return 'google' === $provider ? 'gmail' : 'outlook';
    }
}
