package security

import (
	"encoding/json"
	"io"
	"net/http"
	"strings"

	"be.ems/lib/config"
	"be.ems/lib/dborm"
	"be.ems/lib/global"
	"be.ems/lib/log"
	"be.ems/lib/oauth"
	"be.ems/lib/services"
)

var (
	UriOauthToken     = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
	UriOauthHandshake = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"

	CustomUriOauthToken     = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
	CustomUriOauthHandshake = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
)

func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
	log.Info("LoginFromOMC processing... ")

	body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
	if err != nil {
		log.Error("Failed to ReadAll:", err)
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}

	// check media type(content type) only support "application/json"
	if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
		log.Debug("Invalid Content-Type")
		services.ResponseUnsupportedMediaType415(w)
		return
	}

	// // check extend uri, response 404
	// if !IsValidOAuthUri(r) {
	// 	log.Debug("Uri is invalid")
	// 	services.ResponseNotFound404UriNotExist(w, r)
	// 	return
	// }

	// Error process ....
	// response 400-7
	if !json.Valid([]byte(body)) {
		log.Error("Invalid Json Format")
		services.ResponseBadRequest400InvalidJson(w)
		return
	}

	var oAuthBody oauth.OAuthBody
	_ = json.Unmarshal(body, &oAuthBody) //转为json
	//log.Debug("body:", string(body), "oAuthBody:", oAuthBody)

	defer r.Body.Close()
	// response 400-5
	if oauth.IsWrongOAuthInfo(oAuthBody) {
		log.Error("Wrong parameter value")
		services.ResponseBadRequest400WrongParamValue(w)
		return
	}
	/*
		if oauth.IsValidOAuthInfo(oAuthBody) {
			plist := config.GetPermissionFromConfig(oAuthBody.UserName, oAuthBody.GrantType)
			log.Debug("Permission list:", plist)

			token := globalSession.NewSession(w, r, plist)
			services.ResponseStatusOK200Login(w, token)
		} else {
			// response 400-4
			log.Debug("Authentication failed, mismatch user or password")

			services.ResponseBadRequest400IncorrectLogin(w)
		}
	*/

	token := oauth.GenRandToken("omc") // Generate new token to session ID
	sourceAddr := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
	affected, err := dborm.XormInsertSession(oAuthBody.UserName, sourceAddr, token,
		config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
	if err != nil {
		log.Error("Failed to XormInsertSession:", err)
		if affected == -1 {
			services.ResponseForbidden403MultiLoginNotAllowed(w)
		} else {
			services.ResponseBadRequest400IncorrectLogin(w)
		}

		return
	}

	services.ResponseBadRequest400IncorrectLogin(w)
}

func LogoutFromOMC(w http.ResponseWriter, r *http.Request) {
	log.Info("LogoutFromOMC processing... ")

	// token, err := services.CheckFrontValidRequest(w, r)
	// if err != nil {
	// 	log.Error("Request error:", err)
	// 	return
	// }
	// // check media type(content type) only support "application/json"
	// if services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) == false {
	// 	log.Error("Invalid Content-Type")
	// 	services.ResponseUnsupportedMediaType415(w)
	// 	return
	// }

	// // check extend uri, response 404
	// if !services.IsValidOAuthUri(r) {
	// 	log.Error("Uri is invalid")
	// 	services.ResponseNotFound404UriNotExist(w, r)
	// 	return
	// }

	// // error processing ...
	// // 401-1 response
	// token, ret := oauth.IsCarriedToken(r)
	// if ret == false {
	// 	log.Error("AccessToken is not carried")
	// 	services.ResponseUnauthorized401AccessTokenNotCarried(w)
	// 	return
	// }

	// se, err := dborm.XormLogoutUpdateSession(token)
	// if err != nil {
	// 	log.Error("Uri is invalid")
	// 	services.ResponseNotFound404UriNotExist(w, r)
	// 	return
	// }
	// 清除缓存用户信息
	// account.ClearLoginUser(se.AccountId)
	services.ResponseStatusOK200Null(w)
}

func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
	log.Info("HandshakeFromOMC processing... ")

	// check media type(content type) only support "application/json"
	if !services.IsVallidContentType(r, config.GetYamlConfig().OMC.CheckContentType) {
		log.Debug("Invalid Content-Type")
		services.ResponseUnsupportedMediaType415(w)
		return
	}

	// check extend uri, response 404
	if !services.IsValidOAuthUri(r) {
		log.Error("Uri is invalid")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}

	// error processing ...
	// 401-1 response
	token, ret := oauth.IsCarriedToken(r)
	if !ret {
		log.Error("AccessToken is not carried")
		services.ResponseUnauthorized401AccessTokenNotCarried(w)
		return
	}

	_, err := dborm.XormUpdateSessionShakeTime(token)
	if err != nil {
		log.Error("Uri is invalid")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	services.ResponseStatusOK200Null(w)
}
