package region_sync

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"

	"github.com/QuantumNous/new-api/common"
	"github.com/QuantumNous/new-api/logger"
)

// SyncClient 调用远程节点的 HTTP 客户端
type SyncClient struct {
	endpoint   string
	apiKey     string
	httpClient *http.Client
}

func NewSyncClient(endpoint, apiKey string) *SyncClient {
	return &SyncClient{
		endpoint:   endpoint,
		apiKey:     apiKey,
		httpClient: &http.Client{Timeout: 30 * time.Second},
	}
}

func (c *SyncClient) doRequest(method, path string, body interface{}) ([]byte, error) {
	var reqBody io.Reader
	if body != nil {
		data, err := json.Marshal(body)
		if err != nil {
			return nil, fmt.Errorf("marshal request: %w", err)
		}
		reqBody = bytes.NewReader(data)
	}

	// 处理 URL 拼接，避免双斜杠问题
	endpoint := strings.TrimRight(c.endpoint, "/")
	path = strings.TrimLeft(path, "/")
	url := endpoint + "/" + path

	common.SysLog(fmt.Sprintf("[RegionSync] HTTP %s %s", method, url))
	logger.LogDebug(nil, "[RegionSync] HTTP %s %s", method, url)

	req, err := http.NewRequest(method, url, reqBody)
	if err != nil {
		return nil, fmt.Errorf("create request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Sync-API-Key", c.apiKey)
	req.Header.Set("X-Sync-Node", c.endpoint)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("http request: %w", err)
	}
	defer resp.Body.Close()

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read response: %w", err)
	}

	// 如果返回状态码不是 200，记录错误信息
	if resp.StatusCode != http.StatusOK {
		common.SysError(fmt.Sprintf("[RegionSync] HTTP error %d from %s: %s", resp.StatusCode, url, string(data)))
		return nil, fmt.Errorf("http status %d: %s", resp.StatusCode, string(data))
	}

	return data, nil
}

func (c *SyncClient) SyncUserCreate(req *SyncUserRequest) (*SyncUserResponse, error) {
	data, err := c.doRequest("POST", "/api/internal/sync/user/create", req)
	if err != nil {
		return nil, err
	}
	var resp SyncUserResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("unmarshal response: %w", err)
	}
	return &resp, nil
}

func (c *SyncClient) QueryQuota(userId int) (*QueryQuotaResponse, error) {
	data, err := c.doRequest("POST", "/api/internal/sync/quota/query", &QueryQuotaRequest{UserId: userId})
	if err != nil {
		return nil, err
	}
	var resp QueryQuotaResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("unmarshal response: %w", err)
	}
	logger.LogDebug(nil, "[RegionSync] QueryQuota: userId=%d, quota=%d, success=%v", userId, resp.Quota, resp.Success)
	return &resp, nil
}

func (c *SyncClient) BatchDeduct(req *BatchDeductRequest) (*BatchDeductResponse, error) {
	logger.LogDebug(nil, "[RegionSync] BatchDeduct: sending %d records", len(req.Records))
	data, err := c.doRequest("POST", "/api/internal/sync/quota/batch-deduct", req)
	if err != nil {
		return nil, err
	}
	var resp BatchDeductResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("unmarshal response: %w", err)
	}
	successCount := 0
	for _, r := range resp.Results {
		if r.Success {
			successCount++
		}
	}
	logger.LogDebug(nil, "[RegionSync] BatchDeduct: response success=%d, total=%d", successCount, len(resp.Results))
	return &resp, nil
}

func (c *SyncClient) UpdateQuota(remoteUserId, quota int) (*UpdateQuotaResponse, error) {
	data, err := c.doRequest("POST", "/api/internal/sync/quota/update", &UpdateQuotaRequest{RemoteUserId: remoteUserId, Quota: quota})
	if err != nil {
		return nil, err
	}
	var resp UpdateQuotaResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("unmarshal response: %w", err)
	}
	return &resp, nil
}

func (c *SyncClient) FetchConfig() (*SyncConfigResponse, error) {
	data, err := c.doRequest("GET", "/api/internal/sync/config", nil)
	if err != nil {
		return nil, err
	}
	var resp SyncConfigResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("unmarshal response: %w", err)
	}
	return &resp, nil
}

func (c *SyncClient) BatchQueryQuota(userIds []int) (*BatchQueryQuotaResponse, error) {
	data, err := c.doRequest("POST", "/api/internal/sync/quota/batch-query", &BatchQueryQuotaRequest{UserIds: userIds})
	if err != nil {
		return nil, err
	}
	var resp BatchQueryQuotaResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("unmarshal response: %w", err)
	}
	return &resp, nil
}
