package cbr

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

	"go.uber.org/zap"
)

const (
	defaultUserAgent = "Mozilla/5.0 (compatible; SendicoFX/1.0; +https://app.sendico.io)"
	defaultAccept    = "application/xml,text/xml;q=0.9,*/*;q=0.8"
)

// httpClient wraps http.Client to ensure CBR requests always carry required headers.
type httpClient struct {
	client  *http.Client
	headers http.Header
	logger  *zap.Logger
}

type httpClientOptions struct {
	userAgent string
	accept    string
	referer   string
}

func newHTTPClient(logger *zap.Logger, client *http.Client, opts httpClientOptions) *httpClient {
	userAgent := opts.userAgent
	if strings.TrimSpace(userAgent) == "" {
		userAgent = defaultUserAgent
	}

	accept := opts.accept
	if strings.TrimSpace(accept) == "" {
		accept = defaultAccept
	}

	referer := opts.referer
	if strings.TrimSpace(referer) == "" {
		referer = defaultCBRBaseURL
	}
	l := logger.Named("http_client")

	headers := make(http.Header, 3)
	headers.Set("User-Agent", userAgent)
	headers.Set("Accept", accept)
	headers.Set("Referer", referer)

	l.Info("HTTP client initialized", zap.String("user_agent", userAgent),
		zap.String("accept", accept), zap.String("referrer", referer))

	return &httpClient{
		client:  client,
		headers: headers,
		logger:  l,
	}
}

func (h *httpClient) NewRequest(ctx context.Context, method, endpoint string) (*http.Request, error) {
	return http.NewRequestWithContext(ctx, method, endpoint, nil)
}

func (h *httpClient) Do(req *http.Request) (*http.Response, error) {
	enriched := req.Clone(req.Context())
	for key, values := range h.headers {
		if enriched.Header.Get(key) != "" {
			continue
		}
		for _, value := range values {
			enriched.Header.Add(key, value)
		}
	}
	r, err := h.client.Do(enriched)
	if err != nil {
		h.logger.Warn("HTTP request failed", zap.Error(err), zap.String("method", req.Method),
			zap.String("url", req.URL.String()))
	}
	return r, err
}

func (h *httpClient) headerValue(name string) string {
	return h.headers.Get(name)
}
