package wire

import (
	"context"
	"net/http"
	"strings"

	"github.com/tidbcloud/AgentTeam/desktop/internal/wire/apiclient"
)

// APIClient returns an authenticated AgentTeam HTTP API client bound to this channel.
// If agentID is provided, the client uses the per-agent auth token instead of the
// channel-level token.
func (c *Protocol) APIClient(agentID ...string) *apiclient.Client {
	serverURL, apiKey, workspaceID, machineID, defaultAgentID, authToken := c.identitySnapshot()
	token := authToken
	effectiveAgentID := defaultAgentID
	var refreshAuthToken func(context.Context, string) (string, error)

	c.mu.Lock()
	if c.targetResolver == nil {
		c.targetResolver = apiclient.NewTargetResolver()
	}
	targetResolver := c.targetResolver
	if len(agentID) > 0 {
		effectiveAgentID = strings.TrimSpace(agentID[0])
		token = ""
		if st, ok := c.agents[effectiveAgentID]; ok {
			token = strings.TrimSpace(st.Token)
		}
	}
	c.mu.Unlock()
	if len(agentID) > 0 && effectiveAgentID != "" && strings.TrimSpace(apiKey) != "" {
		refreshAuthToken = func(ctx context.Context, staleToken string) (string, error) {
			return c.refreshAgentToken(ctx, effectiveAgentID, staleToken)
		}
	}

	return &apiclient.Client{
		ServerURL:           strings.TrimRight(serverURL, "/"),
		AgentID:             effectiveAgentID,
		AuthToken:           token,
		RouteWorkspaceID:    workspaceID,
		MachineID:           machineID,
		HTTPClient:          c.httpClient,
		StreamingHTTPClient: c.streamingAPIHTTPClient(),
		RecordAPIRetry:      func() { c.metrics.apiRetries.Add(1) },
		TargetResolver:      targetResolver,
		RefreshAuthToken:    refreshAuthToken,
	}
}

func (c *Protocol) streamingAPIHTTPClient() *http.Client {
	c.streamingAPIClientMu.Lock()
	defer c.streamingAPIClientMu.Unlock()
	if c.streamingAPIClient == nil {
		c.streamingAPIClient = apiclient.NewStreamingHTTPClient(
			c.httpClient, apiclient.DefaultStreamingResponseHeaderTimeout,
		)
	}
	return c.streamingAPIClient
}

func (c *Protocol) closeStreamingAPIClientIdleConnections() {
	c.streamingAPIClientMu.Lock()
	client := c.streamingAPIClient
	c.streamingAPIClientMu.Unlock()
	if client == nil {
		return
	}
	if transport, ok := client.Transport.(interface{ CloseIdleConnections() }); ok {
		transport.CloseIdleConnections()
	}
}

func (c *Protocol) removeResolvedTargetsForAgent(agentID string) {
	c.mu.Lock()
	targetResolver := c.targetResolver
	c.mu.Unlock()
	if targetResolver != nil {
		targetResolver.RemoveAgent(agentID)
	}
}
