package chatgpt

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"

	"encoding/json"
)

// TokenResult holds the result of a token refresh.
type TokenResult struct {
	AccessToken  string
	RefreshToken string
	IDToken      string
	ExpiresIn    int
}

// GetEmail extracts the user's email from the ID token or Access token.
func (tr *TokenResult) GetEmail() string {
	if tr.IDToken != "" {
		claims, err := decodeJWTPayload(tr.IDToken)
		if err == nil {
			if email, ok := claims["email"].(string); ok && email != "" {
				return email
			}
		}
	}
	if tr.AccessToken != "" {
		claims, err := decodeJWTPayload(tr.AccessToken)
		if err == nil {
			if email, ok := claims["email"].(string); ok && email != "" {
				return email
			}
		}
	}
	return ""
}

// RefreshAccessToken exchanges a refresh token for a new access token.
func (c *Client) RefreshAccessToken(refreshToken string) (*TokenResult, error) {
	rt := strings.TrimSpace(refreshToken)
	if rt == "" {
		return nil, fmt.Errorf("refresh token 为空")
	}

	form := url.Values{}
	form.Set("grant_type", "refresh_token")
	form.Set("client_id", openaiClientID)
	form.Set("refresh_token", rt)
	form.Set("scope", "openid profile email")

	req, err := http.NewRequest("POST", "https://auth.openai.com/oauth/token", strings.NewReader(form.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("刷新 token 网络错误: %w", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)

	if resp.StatusCode != 200 {
		var errData struct {
			Error            string `json:"error"`
			ErrorDescription string `json:"error_description"`
		}
		_ = json.Unmarshal(body, &errData)
		msg := errData.ErrorDescription
		if msg == "" {
			msg = errData.Error
		}
		if msg == "" {
			msg = fmt.Sprintf("HTTP %d", resp.StatusCode)
		}
		return nil, fmt.Errorf("刷新 token 失败: %s", msg)
	}

	var result struct {
		AccessToken  string `json:"access_token"`
		RefreshToken string `json:"refresh_token"`
		IDToken      string `json:"id_token"`
		ExpiresIn    int    `json:"expires_in"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("解析刷新结果失败: %w", err)
	}
	if result.AccessToken == "" {
		return nil, fmt.Errorf("刷新 token 失败: 未返回有效凭证")
	}

	newRT := result.RefreshToken
	if newRT == "" {
		newRT = rt
	}

	return &TokenResult{
		AccessToken:  result.AccessToken,
		RefreshToken: newRT,
		IDToken:      result.IDToken,
		ExpiresIn:    result.ExpiresIn,
	}, nil
}
