package main

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

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

var pathPattern2ResourceMap = map[string]string{
	"/api/v1/orgs/(\\d+)/poc-applications":      "/orgs/{org_id}/owner",
	"/api/v1/orgs/(\\d+)/projects/(\\d+)/users": "/orgs/{org_id}/projects/{project_id}/list",
	"/api/v1/orgs/verification-email":           "/orgs/verification-email",
	"/test":                                     "/test/owner",
	"/test34":                                   "/test/owner",
	"/api/v1/orgs/(\\d+)/projects/(\\d+)/get":   "orgs/{org_id}/projects/{project_id}/get",
}

var pathWhitelist = []string{
	"/health_check",
	"/ping",
	"/local_test",
}

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	// mock identity has permission (optional), if not set, the checker will call remote rbac-server， otherwise it will return err when local run
	helperimpl.DefaultCachedPermissionHelper = &identityHasPermissionHelper{}
	// biz customized the logic where permission check complete, if not set, the checker will run the default logic
	useadapter.DefaultAccessDecideCompleteExecFunc = customizedAccessDecideCompleteExecFunc
}

// biz define exec logic
func customizedAccessDecideCompleteExecFunc(w http.ResponseWriter, r *http.Request, result *common.AccessResult, err error) (continueRun bool) {
	log.Println(fmt.Sprintf("permission check result: [%+v], err: [%+v]", result, err))
	if err != nil || result.Code != common.RSP_CODE_RELEASE {
		w.WriteHeader(http.StatusForbidden)
		w.Write([]byte("access denied, please apply for permission"))
		return false
	}
	return true
}

// mock identity has permission
type identityHasPermissionHelper struct {
}

func (d *identityHasPermissionHelper) SetEndpoint(endpoint string) {
}

func (d *identityHasPermissionHelper) SetReadTimeout(timeout time.Duration) {
}

func (d *identityHasPermissionHelper) SetUseCache(useCache bool) {
}

func (d *identityHasPermissionHelper) SetCacheExpiration(expiration time.Duration) {
}

func (d *identityHasPermissionHelper) HasPermission(ctx context.Context, identity, resource string) (bool, error) {
	return true, nil
}

// mock identity has no permission
type identityHasNoPermissionHelper struct {
	identityHasPermissionHelper
}

func (d *identityHasNoPermissionHelper) HasPermission(ctx context.Context, identity, resource string) (bool, error) {
	return false, nil
}
