package agentidp

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"strings"
)

// CredentialClient provides methods for the Credential Management API endpoints.
type CredentialClient struct {
	baseURL    string
	getToken   func(ctx context.Context) (string, error)
	httpClient *http.Client
}

func newCredentialClient(baseURL string, getToken func(ctx context.Context) (string, error), httpClient *http.Client) *CredentialClient {
	return &CredentialClient{
		baseURL:    strings.TrimRight(baseURL, "/"),
		getToken:   getToken,
		httpClient: httpClient,
	}
}

// GenerateCredential creates a new credential for the given agent.
// POST /api/v1/agents/:id/credentials → 201 CredentialWithSecret
func (c *CredentialClient) GenerateCredential(ctx context.Context, agentID string) (*CredentialWithSecret, error) {
	token, err := c.getToken(ctx)
	if err != nil {
		return nil, err
	}
	var cred CredentialWithSecret
	if err := doRequest(ctx, c.httpClient, http.MethodPost, c.baseURL+"/api/v1/agents/"+agentID+"/credentials", struct{}{}, token, &cred); err != nil {
		return nil, err
	}
	return &cred, nil
}

// ListCredentials returns a paginated list of credentials for the given agent.
// GET /api/v1/agents/:id/credentials → 200 PaginatedCredentials
func (c *CredentialClient) ListCredentials(ctx context.Context, agentID string, page, limit int) (*PaginatedCredentials, error) {
	token, err := c.getToken(ctx)
	if err != nil {
		return nil, err
	}
	rawURL := c.baseURL + "/api/v1/agents/" + agentID + "/credentials"
	q := url.Values{}
	if page > 0 {
		q.Set("page", fmt.Sprintf("%d", page))
	}
	if limit > 0 {
		q.Set("limit", fmt.Sprintf("%d", limit))
	}
	if len(q) > 0 {
		rawURL += "?" + q.Encode()
	}
	var result PaginatedCredentials
	if err := doRequest(ctx, c.httpClient, http.MethodGet, rawURL, nil, token, &result); err != nil {
		return nil, err
	}
	return &result, nil
}

// RotateCredential generates a new secret for the given credential.
// POST /api/v1/agents/:id/credentials/:credId/rotate → 200 CredentialWithSecret
func (c *CredentialClient) RotateCredential(ctx context.Context, agentID, credentialID string) (*CredentialWithSecret, error) {
	token, err := c.getToken(ctx)
	if err != nil {
		return nil, err
	}
	rawURL := c.baseURL + "/api/v1/agents/" + agentID + "/credentials/" + credentialID + "/rotate"
	var cred CredentialWithSecret
	if err := doRequest(ctx, c.httpClient, http.MethodPost, rawURL, struct{}{}, token, &cred); err != nil {
		return nil, err
	}
	return &cred, nil
}

// RevokeCredential permanently revokes a credential.
// DELETE /api/v1/agents/:id/credentials/:credId → 200 Credential
func (c *CredentialClient) RevokeCredential(ctx context.Context, agentID, credentialID string) (*Credential, error) {
	token, err := c.getToken(ctx)
	if err != nil {
		return nil, err
	}
	rawURL := c.baseURL + "/api/v1/agents/" + agentID + "/credentials/" + credentialID
	var cred Credential
	if err := doRequest(ctx, c.httpClient, http.MethodDelete, rawURL, nil, token, &cred); err != nil {
		return nil, err
	}
	return &cred, nil
}
