package controllers

import (
	"crypto/tls"
	"github.com/astaxie/beego"
	"github.com/coreos/go-oidc"
	netcontext "golang.org/x/net/context"
	"golang.org/x/oauth2"
	"k8s-console/dto"
	"k8s-console/models"
	"k8s-console/utils"
	"log"
	"net/http"
)

// DeploymentController operations for harborImage
type OidcController struct {
	beego.Controller
}

// URLMapping ...
func (c *OidcController) URLMapping() {
	c.Mapping("authCode", c.AuthCode)
	c.Mapping("getUserPermission", c.GetUserPermission)
}

// Get ...
// @Title AuthCode
// @Description 判断AuthCode是否是有效的
// @Param	lang		query 	string	true	"api result language type"
// @Param	body		body 	deployment.GetDeploymentListRequestDto	true	""
// @Success 200
// @Failure 300 {object} dto.BaseResponseDto
// @router /authCode [get]
func (c *OidcController) AuthCode() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var resultResponseDto = dto.UserInfoDto{300, "", "", utils.GetI18nLang(lang, "sysError"), ""}
	var notNullCode = utils.GetI18nLang(lang, "authCode_notNullCode")
	var invalidCode = utils.GetI18nLang(lang, "authCode_invalidCode")
	authCode := c.Input().Get("code")
	if authCode == "" {
		errorLogger.Println(notNullCode)
		resultResponseDto.Message = invalidCode
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}

	//获取泛域名
	_, _, appExtensiveDomain, err := models.GetHarborIngressAndPwd("harbor", true)
	if err != nil {
		errorLogger.Println("获取集群泛域名失败:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}

	//连接oidc服务器
	ctx := netcontext.Background()
	http.DefaultClient.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	issuerURL := beego.AppConfig.String("dexUrl") + "." + appExtensiveDomain
	provider, err := oidc.NewProvider(ctx, issuerURL)
	if err != nil {
		errorLogger.Println("连接oidc服务器失败:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}
	oidcConfig := &oidc.Config{
		ClientID: beego.AppConfig.String("clientID"),
	}

	verifier := provider.Verifier(oidcConfig)
	//redirectURL := "http://console." + appExtensiveDomain
	redirectURL := "http://localhost:9524"
	config := oauth2.Config{
		ClientID:     beego.AppConfig.String("clientID"),
		ClientSecret: beego.AppConfig.String("clientSecret"),
		Endpoint:     provider.Endpoint(),
		RedirectURL:  redirectURL,
		Scopes:       []string{oidc.ScopeOpenID, "profile", "email", "groups", "offline_access"},
	}

	oauth2Token, err := config.Exchange(ctx, authCode)
	if err != nil {
		errorLogger.Println("无效的code:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}
	// Extract the ID Token from OAuth2 token.
	rawIDToken, ok := oauth2Token.Extra("id_token").(string)
	if !ok {
		errorLogger.Println("无效的token")
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}

	// Parse and verify ID Token payload.
	idToken, err := verifier.Verify(ctx, rawIDToken)
	if err != nil {
		errorLogger.Println("无效的token:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
	}

	// Extract custom claims.
	var claims struct {
		Email string `json:"email"`
		Name  string `json:"name"`
	}

	if err = idToken.Claims(&claims); err != nil {
		errorLogger.Println("无效的token:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
	}

	//封装返回token、用户名称、权限数据
	resultResponseDto.Status = 200
	resultResponseDto.Message = utils.GetI18nLang(lang, "success")
	resultResponseDto.Username = claims.Name
	resultResponseDto.Oauth2Token = oauth2Token.AccessToken
	resultResponseDto.Token = rawIDToken

	log.Println("解析code返回的数据：", &resultResponseDto)
	c.Data["json"] = &resultResponseDto
	c.ServeJSON()
}

// Get ...
// @Title GetUserPermission
// @Description 获取用户权限数据
// @Param	oauth2Token		query 	string	true	"api result language type"
// @Success 200
// @Failure 300 {object} dto.BaseResponseDto
// @router /getUserPermission [get]
func (c *OidcController) GetUserPermission() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var resultResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	var notNullCode = utils.GetI18nLang(lang, "authToken_notNullCode")
	oauth2Token := c.Input().Get("oauth2Token")
	if oauth2Token == "" {
		errorLogger.Println(notNullCode)
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}

	//获取泛域名
	_, _, appExtensiveDomain, err := models.GetHarborIngressAndPwd("harbor", true)
	if err != nil {
		errorLogger.Println("获取集群泛域名失败:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}

	//连接oidc服务器
	ctx := netcontext.Background()
	http.DefaultClient.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	issuerURL := beego.AppConfig.String("dexUrl") + "." + appExtensiveDomain
	provider, err := oidc.NewProvider(ctx, issuerURL)
	if err != nil {
		errorLogger.Println("连接oidc服务器失败:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}

	tokenInfo := oauth2.Token{AccessToken: oauth2Token, TokenType: "bearer"}
	userInfo, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(&tokenInfo))
	if err != nil {
		errorLogger.Println("调用获取用户信息接口失败:", err.Error())
		c.Data["json"] = resultResponseDto
		c.ServeJSON()
		return
	}

	var dat map[string]interface{}
	userInfo.Claims(&dat)

	//封装返回token、用户名称、权限数据
	resultResponseDto.Status = 200
	resultResponseDto.Message = dat["permission"].(string)

	c.Data["json"] = &resultResponseDto
	c.ServeJSON()
}
