package dxf

import (
	"context"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net/http"
	"sync"
)

var (
	transportsMu sync.RWMutex
	transports   = make(map[string]*http.Transport)
)

func ensureTransport(tlsConfig *tls.Config, configID string) *http.Transport {
	transportsMu.Lock()
	defer transportsMu.Unlock()

	if t, ok := transports[configID]; ok {
		return t
	}

	defaultTransport, _ := http.DefaultTransport.(*http.Transport)
	t := defaultTransport.Clone()
	t.MaxIdleConns = 2
	t.TLSClientConfig = tlsConfig
	transports[configID] = t
	return t
}

type Client struct {
	endpoint   string
	httpClient *http.Client
}

func NewClient(endpoint string, tlsConfig *tls.Config, tlsSecretName string) *Client {
	transport := ensureTransport(tlsConfig, tlsSecretName)
	return &Client{
		endpoint: endpoint,
		httpClient: &http.Client{
			Transport: transport,
		},
	}
}

func (c *Client) doRequest(req *http.Request) ([]byte, error) {
	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer func() { _ = resp.Body.Close() }()
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode > 300 {
		return nil, errors.New(string(data))
	}
	return data, nil
}

func (c *Client) GetDXFScheduleStatus(ctx context.Context) (*DXFScheduleStatus, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/dxf/schedule/status", c.endpoint), http.NoBody)
	if err != nil {
		return nil, err
	}
	bs, err := c.doRequest(req)
	if err != nil {
		return nil, err
	}
	slog.Info("call dxf schedule status api", "resp", string(bs))
	out := new(DXFScheduleStatus)
	if err := json.Unmarshal(bs, out); err != nil {
		return nil, err
	}
	return out, nil
}
