package providers

import (
	"context"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"time"
)

// TwitterProvider Twitter OAuth提供者 (OAuth 2.0 with PKCE)
type TwitterProvider struct {
	ClientID    string
	RedirectURI string
}

// TwitterAuthURLResponse Twitter授权URL响应
type TwitterAuthURLResponse struct {
	URL          string `json:"url"`
	CodeVerifier string `json:"code_verifier"`
	State        string `json:"state"`
	Redirect     string `json:"redirect,omitempty"`
}

// TwitterTokenResponse Twitter Token响应
type TwitterTokenResponse struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    int    `json:"expires_in"`
	RefreshToken string `json:"refresh_token"`
	Scope        string `json:"scope"`
}

// TwitterUserInfo Twitter用户信息
type TwitterUserInfo struct {
	Data struct {
		ID            string `json:"id"`
		Name          string `json:"name"`
		Username      string `json:"username"`
		CreatedAt     string `json:"created_at"`
		Description   string `json:"description"`
		PublicMetrics struct {
			FollowersCount int `json:"followers_count"`
			FollowingCount int `json:"following_count"`
			TweetCount     int `json:"tweet_count"`
			ListedCount    int `json:"listed_count"`
		} `json:"public_metrics"`
		ProfileImageURL string `json:"profile_image_url"`
	} `json:"data"`
}

// TwitterErrorResponse Twitter错误响应
type TwitterErrorResponse struct {
	Title  string `json:"title"`
	Detail string `json:"detail"`
	Type   string `json:"type"`
	Status int    `json:"status"`
}

// NewTwitterProvider 创建Twitter OAuth提供者
func NewTwitterProvider(clientID, redirectURI string) *TwitterProvider {
	return &TwitterProvider{
		ClientID:    clientID,
		RedirectURI: redirectURI,
	}
}

// GenerateCodeVerifier 生成PKCE Code Verifier
func (t *TwitterProvider) GenerateCodeVerifier() (string, error) {
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}
	return base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(b), nil
}

// GenerateCodeChallenge 从Code Verifier生成Code Challenge
func (t *TwitterProvider) GenerateCodeChallenge(verifier string) string {
	// 简化的base64编码（实际应用中应该使用SHA256哈希）
	return verifier
}

// GenerateState 生成随机状态码
func (t *TwitterProvider) GenerateState() (string, error) {
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}
	return base64.URLEncoding.EncodeToString(b), nil
}

// GetAuthURL 获取Twitter授权URL (OAuth 2.0 with PKCE)
func (t *TwitterProvider) GetAuthURL() (*TwitterAuthURLResponse, error) {
	verifier, err := t.GenerateCodeVerifier()
	if err != nil {
		return nil, fmt.Errorf("generate code verifier failed: %w", err)
	}

	challenge := t.GenerateCodeChallenge(verifier)

	state, err := t.GenerateState()
	if err != nil {
		return nil, fmt.Errorf("generate state failed: %w", err)
	}

	authURL := fmt.Sprintf(
		"https://twitter.com/i/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&scope=tweet.read%%20users.read%%20offline.access&state=%s&code_challenge=%s&code_challenge_method=plain",
		t.ClientID,
		url.QueryEscape(t.RedirectURI),
		state,
		challenge,
	)

	return &TwitterAuthURLResponse{
		URL:          authURL,
		CodeVerifier: verifier,
		State:        state,
		Redirect:     t.RedirectURI,
	}, nil
}

// ExchangeCode 用授权码换取访问令牌
func (t *TwitterProvider) ExchangeCode(ctx context.Context, code, codeVerifier string) (*TwitterTokenResponse, error) {
	tokenURL := "https://api.twitter.com/2/oauth2/token"

	data := url.Values{}
	data.Set("code", code)
	data.Set("grant_type", "authorization_code")
	data.Set("client_id", t.ClientID)
	data.Set("redirect_uri", t.RedirectURI)
	data.Set("code_verifier", codeVerifier)

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := postFormWithContext(ctx, client, tokenURL, data)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	body, err := readOAuthResponseBody(resp)
	if err != nil {
		return nil, fmt.Errorf("read response failed: %w", err)
	}

	// 检查错误响应
	var errResp TwitterErrorResponse
	if err := json.Unmarshal(body, &errResp); err == nil && errResp.Detail != "" {
		return nil, fmt.Errorf("twitter api error: %s - %s", errResp.Title, errResp.Detail)
	}

	var tokenResp TwitterTokenResponse
	if err := json.Unmarshal(body, &tokenResp); err != nil {
		return nil, fmt.Errorf("parse token response failed: %w", err)
	}

	return &tokenResp, nil
}

// GetUserInfo 获取Twitter用户信息
func (t *TwitterProvider) GetUserInfo(ctx context.Context, accessToken string) (*TwitterUserInfo, error) {
	userInfoURL := "https://api.twitter.com/2/users/me?user.fields=created_at,description,public_metrics,profile_image_url"

	req, err := http.NewRequestWithContext(ctx, "GET", userInfoURL, nil)
	if err != nil {
		return nil, fmt.Errorf("create request failed: %w", err)
	}
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	body, err := readOAuthResponseBody(resp)
	if err != nil {
		return nil, fmt.Errorf("read response failed: %w", err)
	}

	// 检查错误响应
	var errResp TwitterErrorResponse
	if err := json.Unmarshal(body, &errResp); err == nil && errResp.Detail != "" {
		return nil, fmt.Errorf("twitter api error: %s - %s", errResp.Title, errResp.Detail)
	}

	var userInfo TwitterUserInfo
	if err := json.Unmarshal(body, &userInfo); err != nil {
		return nil, fmt.Errorf("parse user info failed: %w", err)
	}

	return &userInfo, nil
}

// RefreshToken 刷新访问令牌
func (t *TwitterProvider) RefreshToken(ctx context.Context, refreshToken string) (*TwitterTokenResponse, error) {
	tokenURL := "https://api.twitter.com/2/oauth2/token"

	data := url.Values{}
	data.Set("refresh_token", refreshToken)
	data.Set("grant_type", "refresh_token")
	data.Set("client_id", t.ClientID)

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := postFormWithContext(ctx, client, tokenURL, data)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	body, err := readOAuthResponseBody(resp)
	if err != nil {
		return nil, fmt.Errorf("read response failed: %w", err)
	}

	var errResp TwitterErrorResponse
	if err := json.Unmarshal(body, &errResp); err == nil && errResp.Detail != "" {
		return nil, fmt.Errorf("twitter api error: %s - %s", errResp.Title, errResp.Detail)
	}

	var tokenResp TwitterTokenResponse
	if err := json.Unmarshal(body, &tokenResp); err != nil {
		return nil, fmt.Errorf("parse token response failed: %w", err)
	}

	return &tokenResp, nil
}

// ValidateToken 验证访问令牌是否有效
func (t *TwitterProvider) ValidateToken(ctx context.Context, accessToken string) (bool, error) {
	userInfo, err := t.GetUserInfo(ctx, accessToken)
	if err != nil {
		return false, err
	}
	return userInfo != nil && userInfo.Data.ID != "", nil
}

// RevokeToken 撤销访问令牌
func (t *TwitterProvider) RevokeToken(ctx context.Context, accessToken string) error {
	revokeURL := "https://api.twitter.com/2/oauth2/revoke"

	data := url.Values{}
	data.Set("token", accessToken)
	data.Set("client_id", t.ClientID)
	data.Set("token_type_hint", "access_token")

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := postFormWithContext(ctx, client, revokeURL, data)
	if err != nil {
		return fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	if _, err := readOAuthResponseBody(resp); err != nil {
		return fmt.Errorf("revoke token failed: %w", err)
	}

	return nil
}
