package runner

import (
	"net/http"
	"net/url"
	"strings"
	"sync"
	"time"

	"github.com/easyai/easyai-ai-gateway/apps/api/internal/clients"
	"github.com/easyai/easyai-ai-gateway/apps/api/internal/netproxy"
	"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
)

type httpClientCache struct {
	none   *http.Client
	global *http.Client
	mu     sync.Mutex
	custom map[string]*http.Client
}

func newHTTPClientCache() *httpClientCache {
	return &httpClientCache{
		none:   newHTTPClient(nil),
		global: newHTTPClient(http.ProxyFromEnvironment),
		custom: map[string]*http.Client{},
	}
}

func (s *Service) httpClientForCandidate(candidate store.RuntimeModelCandidate, simulated bool) (*http.Client, error) {
	if simulated {
		return s.httpClients.none, nil
	}
	config, err := netproxy.Normalize(netproxy.FromPlatformConfig(candidate.PlatformConfig))
	if err != nil {
		return nil, &clients.ClientError{Code: "invalid_proxy", Message: err.Error(), Retryable: false}
	}
	switch config.Mode {
	case netproxy.ModeGlobal:
		if strings.TrimSpace(s.cfg.GlobalHTTPProxy) != "" {
			return s.httpClients.customClient(s.cfg.GlobalHTTPProxy)
		}
		return s.httpClients.global, nil
	case netproxy.ModeCustom:
		return s.httpClients.customClient(config.HTTPProxy)
	default:
		return s.httpClients.none, nil
	}
}

func (c *httpClientCache) customClient(rawProxy string) (*http.Client, error) {
	normalized, proxyURL, err := netproxy.ParseHTTPProxy(rawProxy)
	if err != nil {
		return nil, &clients.ClientError{Code: "invalid_proxy", Message: err.Error(), Retryable: false}
	}
	c.mu.Lock()
	defer c.mu.Unlock()
	if client := c.custom[normalized]; client != nil {
		return client, nil
	}
	client := newHTTPClient(http.ProxyURL(proxyURL))
	c.custom[normalized] = client
	return client, nil
}

func newHTTPClient(proxy func(*http.Request) (*url.URL, error)) *http.Client {
	transport := http.DefaultTransport.(*http.Transport).Clone()
	transport.Proxy = proxy
	return &http.Client{
		Timeout:   120 * time.Second,
		Transport: transport,
	}
}
