package main

import (
	"context"
	"log"
	"net/http"

	"github.com/tidbcloud/tiinf/sdk/rbac/common"
	"github.com/tidbcloud/tiinf/sdk/rbac/helperimpl"
	"github.com/tidbcloud/tiinf/sdk/rbac/useadapter"
)

// Example_Use_CustomizedHttpHandlerFunc example for use CustomizedHttpHandlerFunc in raw http framework
func Example_Use_CustomizedHttpHandlerFunc() {
	// permission check handler
	pf := useadapter.CustomizedHttpHandlerFunc(
		httpBizLogic,
		// use default helper to get identity from context, so the biz need set identity to context with the specified key
		helperimpl.NewContextStoreGetIdentityFunc(httpCtxIdentityKey),
		pathPattern2ResourceMap,
		pathWhitelist...,
	)
	// extract user handler
	uf := httpHandlerExtractIdentityFunc(pf)
	http.HandleFunc("/test", uf)
	http.Handle("/tst1", uf)
	http.ListenAndServe(":8080", nil)
}

var httpCtxIdentityKey = "example_gin_identity_key"

func httpHandlerExtractIdentityFunc(f http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		header := r.Header
		// mock extract userid
		hs := header["Authorization"]
		if hs == nil || len(hs) == 0 {
			panic("not found Authorization")
		}
		userID := hs[0]
		// ---- importance start --------
		// biz need set userID to the context with the specified key and transfer the new req
		ctx := context.WithValue(r.Context(), httpCtxIdentityKey, userID)
		req := r.WithContext(ctx)
		f(w, req)
		// ---- importance end --------
	}
}

func httpBizLogic(w http.ResponseWriter, r *http.Request) {
	log.Println("### example http ###, receive req: ", r.RequestURI)
}

// Example_Use_CustomizedHttpServeMux example for use CustomizedHttpServeMux in raw http framework
func Example_Use_CustomizedHttpServeMux() {
	// new mux with the identity key in context (mux will get identity from context with the identity key)
	mux := useadapter.NewCustomizedHttpServeMux(http.DefaultServeMux, httpCtxIdentityKey)
	// add extract user interceptor
	mux.Use(&serveMuxExtractIdentityInterceptor{})
	// add permission check interceptor
	mux.Use(useadapter.ServeMuxPermissionCheckInterceptor(
		httpCtxIdentityKey,
		pathPattern2ResourceMap,
		pathWhitelist...),
	)
	mux.Handle("/test", http.HandlerFunc(httpBizLogic))
	mux.HandleFunc("/test1", httpBizLogic)

	http.ListenAndServe(":8080", mux)
}

type serveMuxExtractIdentityInterceptor struct {
}

func (c *serveMuxExtractIdentityInterceptor) Handle(ctx context.Context, param *common.AccessParam) (*common.AccessResult, error) {
	r := param.Req.(*http.Request)
	header := r.Header
	// mock extract userid
	hs := header["Authorization"]
	if hs == nil || len(hs) == 0 {
		panic("not found Authorization")
	}
	userID := hs[0]
	// importance: biz need set userID to Data and return Release, serve mux will get userID from data and set userID to context
	result := common.AccessResult{
		Code: common.RSP_CODE_RELEASE,
		Msg:  "pass",
		Data: userID,
	}
	return &result, nil
}

// Example_Use_CustomizedServeMux example for use CustomizedServeMux in raw http framework
func Example_Use_CustomizedServeMux() {
	http.HandleFunc("/test", httpBizLogic)
	http.HandleFunc("/test1", httpBizLogic)
	mux := useadapter.NewCustomizedServeMux(http.DefaultServeMux, httpCtxIdentityKey)
	// add extract user interceptor
	mux.Use(&serveMuxExtractIdentityInterceptor{})
	// permission check
	mux.Use(useadapter.ServeMuxPermissionCheckInterceptor(
		httpCtxIdentityKey,
		pathPattern2ResourceMap,
		pathWhitelist...),
	)
	http.ListenAndServe(":8080", mux)
}
