package chatgpt

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

	"go-helper/internal/model"
)

const (
	maxInviteAttempts = 3
	retryBaseDelay    = 800 * time.Millisecond
	retryMaxDelay     = 5 * time.Second
)

// InviteUser sends an invitation to the given email on the specified team account.
func (c *Client) InviteUser(email string, account *model.GptAccount) error {
	email = strings.TrimSpace(strings.ToLower(email))
	if email == "" {
		return fmt.Errorf("缺少邀请邮箱")
	}
	if account.Token == "" || account.ChatgptAccountID == "" {
		return fmt.Errorf("账号配置不完整")
	}

	apiURL := fmt.Sprintf("https://chatgpt.com/backend-api/accounts/%s/invites", account.ChatgptAccountID)
	payload := map[string]interface{}{
		"email_addresses": []string{email},
		"role":            "standard-user",
		"resend_emails":   true,
	}
	bodyBytes, _ := json.Marshal(payload)

	var lastErr error
	for attempt := 1; attempt <= maxInviteAttempts; attempt++ {
		req, err := http.NewRequest("POST", apiURL, bytes.NewReader(bodyBytes))
		if err != nil {
			return err
		}
		headers := buildHeaders(account.Token, account.ChatgptAccountID)
		req.Header = headers
		req.Header.Set("Content-Type", "application/json")
		if account.OaiDeviceID != "" {
			req.Header.Set("Oai-Device-Id", account.OaiDeviceID)
		}

		resp, err := c.httpClient.Do(req)
		if err != nil {
			lastErr = fmt.Errorf("网络错误: %w", err)
			log.Printf("[Invite] 尝试 %d/%d 网络错误: %v", attempt, maxInviteAttempts, err)
			if attempt < maxInviteAttempts {
				sleepRetry(attempt)
			}
			continue
		}

		respBody, _ := io.ReadAll(resp.Body)
		resp.Body.Close()

		if resp.StatusCode >= 200 && resp.StatusCode < 300 {
			log.Printf("[Invite] 成功邀请 %s 到账号 %s", email, account.ChatgptAccountID)
			return nil
		}

		lastErr = fmt.Errorf("HTTP %d: %s", resp.StatusCode, truncate(string(respBody), 300))
		log.Printf("[Invite] 尝试 %d/%d 失败: %v", attempt, maxInviteAttempts, lastErr)

		if !isRetryableStatus(resp.StatusCode) || attempt >= maxInviteAttempts {
			break
		}
		sleepRetry(attempt)
	}
	return fmt.Errorf("邀请失败（已尝试 %d 次）: %v", maxInviteAttempts, lastErr)
}

func sleepRetry(attempt int) {
	delay := float64(retryBaseDelay) * math.Pow(2, float64(attempt-1))
	if delay > float64(retryMaxDelay) {
		delay = float64(retryMaxDelay)
	}
	time.Sleep(time.Duration(delay))
}

func isRetryableStatus(status int) bool {
	return status == 408 || status == 429 || (status >= 500 && status <= 599)
}
