package url

import (
	"git.nspix.com/golang/micro/helper/tokenize"
	"net/url"
	"os"
	"time"
)

const (
	TokenFormLabel  = "access_token"
	MethodFormLabel = "auth_method"
	AuthGateway     = "Sugo"

	DomainNameEnvVariable = "DOMAIN_NAME"
)

type (
	Options struct {
		Schema      string
		Host        string
		Path        string // encoded query values, without '?'
		Fragment    string // fragment for references, without '#'
		Params      map[string]string
		EnableAuth  bool   //enable auth
		AuthName    string //auth app name
		AuthUserID  string
		AuthExpired time.Duration
	}
	Option func(o *Options)
)

func newOptions() *Options {
	return &Options{
		Schema: "https",
		Host:   os.Getenv(DomainNameEnvVariable),
		Params: make(map[string]string),
	}
}

func WithSchema(schema string) Option {
	return func(o *Options) {
		o.Schema = schema
	}
}

func WithAuth(app string, uid string, expired time.Duration) Option {
	return func(o *Options) {
		o.EnableAuth = true
		o.AuthName = app
		o.AuthUserID = uid
		o.AuthExpired = expired
	}
}

func WithFragment(fragment string) Option {
	return func(o *Options) {
		o.Fragment = fragment
	}
}

func WithHost(host string) Option {
	return func(o *Options) {
		o.Host = host
	}
}

func WithPath(path string) Option {
	return func(o *Options) {
		o.Path = path
	}
}

func WithParams(ps map[string]string) Option {
	return func(o *Options) {
		o.Params = ps
	}
}

func Build(opts ...Option) *url.URL {
	o := newOptions()
	for _, cb := range opts {
		cb(o)
	}
	qs := url.Values{}
	for k, v := range o.Params {
		qs.Set(k, v)
	}
	if o.EnableAuth {
		if token, err := tokenize.Encode(o.AuthName, o.AuthUserID, time.Now().Add(o.AuthExpired)); err == nil {
			qs.Set(TokenFormLabel, token)
			qs.Set(MethodFormLabel, AuthGateway)
		}
	}
	return &url.URL{
		Scheme:   o.Schema,
		Host:     o.Host,
		Path:     o.Path,
		RawQuery: qs.Encode(),
	}
}

func Create(opts ...Option) string {
	return Build(opts...).String()
}
