package logic

import (
	"fmt"
	"fusenapi/utils/auth"
	"fusenapi/utils/basic"
	"log"
	"net/http"
	"net/url"
	"time"

	"context"

	"fusenapi/server/home-user-auth/internal/svc"
	"fusenapi/server/home-user-auth/internal/types"

	"github.com/474420502/requests"
	"github.com/zeromicro/go-zero/core/logx"
	"golang.org/x/net/proxy"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"gorm.io/gorm"
)

type UserGoogleLoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext

	token string // 登录 token

	isRegistered  bool   // 是否注册
	registerToken string // 注册邮箱的token
}

func NewUserGoogleLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserGoogleLoginLogic {
	return &UserGoogleLoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// func (l *UserGoogleLoginLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// 	log.Println(r, w)
// }

func (l *UserGoogleLoginLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {

	rurl := fmt.Sprintf(
		l.svcCtx.Config.MainAddress+"/oauth?token=%s&is_registered=%t&register_token=%s",
		l.token,
		l.isRegistered,
		l.registerToken,
	)

	html := fmt.Sprintf(`
	<!DOCTYPE html>
	<html>
	<head>
		<title>Redirect</title>
		<script type="text/javascript">
			window.onload = function() {
				window.location = "%s";
			}
		</script>
	</head>
	<body>
	</body>
	</html>
	`, rurl)
	fmt.Fprintln(w, html)
}

func (l *UserGoogleLoginLogic) UserGoogleLogin(req *types.RequestGoogleLogin, userinfo *auth.UserInfo) (resp *basic.Response) {
	// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
	// userinfo 传入值时, 一定不为null

	dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, proxy.Direct)
	if err != nil {
		log.Fatal(err)
	}

	customClient := &http.Client{
		Transport: &http.Transport{
			Dial: dialer.Dial,
		},
	}

	ctx := context.WithValue(context.Background(), oauth2.HTTPClient, customClient)

	var googleOauthConfig = &oauth2.Config{
		RedirectURL:  "http://localhost:9900/api/user/oauth2/login/google",
		ClientID:     l.svcCtx.Config.OAuth.Google.Appid,
		ClientSecret: l.svcCtx.Config.OAuth.Google.Secret,
		Scopes:       []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"},
		Endpoint:     google.Endpoint,
	}

	token, err := googleOauthConfig.Exchange(ctx, req.Code)
	if err != nil {
		logx.Error(err)
		resp.SetStatus(basic.CodeApiErr)
	}
	ses := requests.NewSession()
	ses.Config().SetProxy("socks5://127.0.0.1:1080") // 代理 为了测试功能

	r, err := ses.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken).Execute()
	if err != nil {
		logx.Error(err)
		return resp.SetStatus(basic.CodeOAuthGoogleApiErr)
	}

	log.Println(r.Json())

	googleId := r.Json().Get("id").Int()

	// l.redirectUrl = "http://localhost:9900/oauth?token=21321123&is_registered"
	// return resp.Set(304, "21321321")
	user, err := l.svcCtx.AllModels.FsUser.FindUserByGoogleId(context.TODO(), googleId)
	log.Println(user)
	if err != nil {
		if err != gorm.ErrRecordNotFound {
			logx.Error(err)
			return resp.SetStatus(basic.CodeDbSqlErr)
		}

		if req.Email == "" {
			return resp.SetStatus(basic.CodeOK)
		}

		// 如果密码匹配,则生成 JWT Token。
		nowSec := time.Now().Unix()
		jwtToken, err := auth.GenerateJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, 0, 0)

		// 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。
		if err != nil {
			logx.Error(err)
			return resp.SetStatus(basic.CodeServiceErr)
		}

		return resp.SetRewriteHandler(func(w http.ResponseWriter, r *http.Request) {
			http.Redirect(w, r, "http://localhost:9900?token="+url.QueryEscape(jwtToken), http.StatusFound)
		})

	}

	return resp.SetStatus(basic.CodeOK)
}