package ai.sentryagent.idp;

import ai.sentryagent.idp.internal.HttpHelper;
import ai.sentryagent.idp.services.*;

import java.net.http.HttpClient;
import java.time.Duration;

/**
 * Top-level client for the SentryAgent.ai AgentIdP API.
 * Composes all four service clients and manages token acquisition automatically.
 *
 * <pre>{@code
 * AgentIdPClient client = new AgentIdPClient(
 *     "https://idp.example.com",
 *     "my-client-id",
 *     "sk_live_...",
 *     "agents:read agents:write tokens:read audit:read"
 * );
 *
 * Agent agent = client.agents().getAgent("uuid-1");
 * }</pre>
 */
public final class AgentIdPClient {

    private static final String DEFAULT_SCOPE = "agents:read agents:write tokens:read audit:read";

    private final TokenManager tokenManager;
    private final AgentRegistryClient agentsClient;
    private final CredentialClient credentialsClient;
    private final TokenClient tokensClient;
    private final AuditClient auditClient;

    /**
     * Creates a new AgentIdPClient with default scope and a shared HttpClient.
     *
     * @param baseUrl      Root URL of the AgentIdP server (e.g. {@code "https://idp.example.com"})
     * @param clientId     OAuth 2.0 client ID
     * @param clientSecret OAuth 2.0 client secret
     */
    public AgentIdPClient(String baseUrl, String clientId, String clientSecret) {
        this(baseUrl, clientId, clientSecret, DEFAULT_SCOPE);
    }

    /**
     * Creates a new AgentIdPClient with a custom scope.
     *
     * @param baseUrl      Root URL of the AgentIdP server
     * @param clientId     OAuth 2.0 client ID
     * @param clientSecret OAuth 2.0 client secret
     * @param scope        Space-separated OAuth 2.0 scopes to request
     */
    public AgentIdPClient(String baseUrl, String clientId, String clientSecret, String scope) {
        this(baseUrl, clientId, clientSecret, scope,
            HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(10))
                .build());
    }

    /**
     * Package-visible constructor that accepts a custom HttpClient (for testing).
     */
    AgentIdPClient(String baseUrl, String clientId, String clientSecret, String scope, HttpClient httpClient) {
        String base = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
        this.tokenManager = new TokenManager(base, clientId, clientSecret, scope, httpClient);

        HttpHelper httpHelper = new HttpHelper(httpClient);
        this.agentsClient      = new AgentRegistryClient(base, tokenManager::getToken, httpHelper);
        this.credentialsClient = new CredentialClient(base, tokenManager::getToken, httpHelper);
        this.tokensClient      = new TokenClient(base, tokenManager::getToken, httpClient);
        this.auditClient       = new AuditClient(base, tokenManager::getToken, httpHelper);
    }

    /** Returns the Agent Registry service client. */
    public AgentRegistryClient agents()      { return agentsClient; }

    /** Returns the Credential Management service client. */
    public CredentialClient credentials()    { return credentialsClient; }

    /** Returns the Token service client (introspect + revoke). */
    public TokenClient tokens()              { return tokensClient; }

    /** Returns the Audit Log service client. */
    public AuditClient audit()               { return auditClient; }

    /** Invalidates the cached access token. The next API call will fetch a fresh one. */
    public void clearTokenCache()            { tokenManager.clearCache(); }
}
