package validate

import (
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"olympus/oncall/backend/db"
	"olympus/oncall/backend/pkg/log"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
)

type Validate struct {
}

func New(g *gin.RouterGroup) (*Validate, error) {
	v := &Validate{}
	g.Any("/", v.validateHandler())
	return nil, nil
}

func (v *Validate) validateHandler() func(g *gin.Context) {
	return func(g *gin.Context) {
		idToken := g.Query("id_token")

		validateUrl := viper.GetString("authing.url") + "/api/v2/oidc/validate_token?"
		postData := url.Values{}
		postData.Add("id_token", idToken)
		req, _ := http.NewRequest("GET", validateUrl+postData.Encode(), nil)
		req.Header.Set("User-Agent", "curl")

		client := http.Client{
			Timeout: 600 * time.Second,
		}
		res, err := client.Do(req)
		if err != nil {
			log.Error("msg", "error: handling validate response", "error info", err)
		}

		defer res.Body.Close() //修改信息
		resBody, _ := io.ReadAll(res.Body)

		resFrontend := &ResValidate{}
		var validateFailStruct ValidateFail
		err = json.Unmarshal(resBody, &validateFailStruct)
		if err != nil {
			log.Error("msg", "error: unmarshal validate fail response", "error info", err)
		}
		if validateFailStruct.Code == 400 {
			// validation fail.
			resFrontend.Login = false
		} else {
			var validateSuccessStruct ValidateSuccess
			err = json.Unmarshal(resBody, &validateSuccessStruct)
			if err != nil {
				log.Error("msg", "error: unmarshal validate success response", "error info", err)
			}
			if !validateEmail(validateSuccessStruct.Email) {
				resFrontend.Login = false
			} else {
				resFrontend.Login = true
				log.Info("msg", "log in successfully", "user", validateSuccessStruct.Email)
				// successfully validate the login.
				// get the auth information for leaders.
				categoriesId, categoriesWithName, err := db.GetAuth(validateSuccessStruct.Email)
				if err != nil {
					log.Error("msg", "error: get auth", "error info", err)
				}
				readCategories, err := db.GetCategoriesByEmail(validateSuccessStruct.Email)
				if err != nil {
					log.Error("msg", "error: get categories by email", "error info", err)
				}
				allcategories := mergeArr(categoriesId, readCategories)
				uniqueAllCategories := uniqueArr(allcategories)
				resFrontend.Auth = categoriesId
				resFrontend.Read = uniqueAllCategories
				resFrontend.Cate_inf = categoriesWithName
			}
		}
		jsonString, _ := json.Marshal(resFrontend)
		g.Writer.Write(jsonString)
	}
}

func validateEmail(email string) bool {
	return strings.HasSuffix(email, viper.GetString("email_suffix"))
}

func mergeArr(a, b []int) []int {
	var arr []int
	arr = append(arr, a...)
	arr = append(arr, b...)
	return arr
}

func uniqueArr(m []int) []int {
	d := make([]int, 0)
	tempMap := make(map[int]bool, len(m))
	for _, v := range m { // 以值作为键名
		if !tempMap[v] {
			tempMap[v] = true
			d = append(d, v)
		}
	}
	return d
}
