package support

import (
	"time"

	"github.com/samber/lo"
	"github.com/spf13/cast"
	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"

	"git.fsdpf.net/go/contracts"
)

type GlobalParams struct {
	user  *contracts.User
	gjson gjson.Result
}

// 获取用户信息
func (this GlobalParams) User() contracts.User {
	return *this.user
}

// 获取指定路径的 value
func (this GlobalParams) Get(key string) contracts.GlobalParams {
	return &GlobalParams{
		user:  this.user,
		gjson: this.gjson.Get(key),
	}
}

//
func (this GlobalParams) Array() []contracts.GlobalParams {
	return lo.Map(this.gjson.Array(), func(item gjson.Result, _ int) contracts.GlobalParams {
		return &GlobalParams{user: this.user, gjson: gjson.Parse(item.Raw)}
	})
}

// 获取golang原始类型
func (this GlobalParams) Value() any {
	return this.gjson.Value()
}

func (this GlobalParams) Raw() string {
	return this.gjson.Raw
}

// 设置json值
func (this *GlobalParams) Set(p string, v any) bool {
	if s, err := sjson.Set(this.Raw(), p, v); err != nil {
		return false
	} else {
		this.gjson = gjson.Parse(s)
	}
	return true
}

// 设置json原始值
func (this *GlobalParams) SetRaw(p, v string) bool {
	if s, err := sjson.SetRaw(this.Raw(), p, v); err != nil {
		return false
	} else {
		this.gjson = gjson.Parse(s)
	}
	return true
}

// 删除路径内容
func (this *GlobalParams) Delete(p string) bool {
	if s, err := sjson.Delete(this.Raw(), p); err != nil {
		return false
	} else {
		this.gjson = gjson.Parse(s)
	}
	return true
}

// 路径包裹
func (this *GlobalParams) Wrapped(p string) contracts.GlobalParams {
	return this.AppendTo("", p)
}

// 包裹内容
func (this *GlobalParams) AppendTo(root, p string) contracts.GlobalParams {
	if root != "" && !gjson.Valid(root) {
		root = ""
	}
	return NewGlobalParam(lo.Must(sjson.SetRaw(root, p, this.Raw())), *this.user)
}

// 判断值是否存在
func (this GlobalParams) Exists() bool {
	return this.gjson.Exists()
}

// to Bool
func (this GlobalParams) Bool() bool {
	return cast.ToBool(this.Value())
}

// to Time
func (this GlobalParams) Time() time.Time {
	return cast.ToTime(this.Value())
}

// to Location Time
func (this GlobalParams) TimeInDefaultLocation(location *time.Location) time.Time {
	return cast.ToTimeInDefaultLocation(this, location)
}

// to float64
func (this GlobalParams) Float64() float64 {
	return cast.ToFloat64(this.Value())
}

// to float32
func (this GlobalParams) Float32() float32 {
	return cast.ToFloat32(this.Value())
}

// to int64
func (this GlobalParams) Int64() int64 {
	return cast.ToInt64(this.Value())
}

// to int32
func (this GlobalParams) Int32() int32 {
	return cast.ToInt32(this.Value())
}

// to int16
func (this GlobalParams) Int16() int16 {
	return cast.ToInt16(this.Value())
}

// to int8
func (this GlobalParams) Int8() int8 {
	return cast.ToInt8(this.Value())
}

// to int
func (this GlobalParams) Int() int {
	return cast.ToInt(this.Value())
}

// to uint
func (this GlobalParams) Uint() uint {
	return cast.ToUint(this.Value())
}

// to uint64
func (this GlobalParams) Uint64() uint64 {
	return cast.ToUint64(this.Value())
}

// to uint32
func (this GlobalParams) Uint32() uint32 {
	return cast.ToUint32(this.Value())
}

// to uint16
func (this GlobalParams) Uint16() uint16 {
	return cast.ToUint16(this.Value())
}

// to uint8
func (this GlobalParams) Uint8() uint8 {
	return cast.ToUint8(this.Value())
}

// to string
func (this GlobalParams) String() string {
	return cast.ToString(this.Value())
}

// to map[string]string
func (this GlobalParams) StringMapString() map[string]string {
	return cast.ToStringMapString(this.Value())
}

// to map[string][]string
func (this GlobalParams) StringMapStringSlice() map[string][]string {
	return cast.ToStringMapStringSlice(this.Value())
}

// to map[string]bool
func (this GlobalParams) StringMapBool() map[string]bool {
	return cast.ToStringMapBool(this.Value())
}

// to map[string]int
func (this GlobalParams) StringMapInt() map[string]int {
	return cast.ToStringMapInt(this.Value())
}

// to map[string]int64
func (this GlobalParams) StringMapInt64() map[string]int64 {
	return cast.ToStringMapInt64(this.Value())
}

// to map[string]any
func (this GlobalParams) StringMap() map[string]any {
	return cast.ToStringMap(this.Value())
}

// to []any
func (this GlobalParams) Slice() []any {
	return cast.ToSlice(this.Value())
}

// to []bool
func (this GlobalParams) BoolSlice() []bool {
	return cast.ToBoolSlice(this.Value())
}

// to []string
func (this GlobalParams) StringSlice() []string {
	return cast.ToStringSlice(this.Value())
}

// to []int
func (this GlobalParams) IntSlice() []int {
	return cast.ToIntSlice(this.Value())
}

func NewGlobalParam(data string, user contracts.User) contracts.GlobalParams {
	return &GlobalParams{user: &user, gjson: gjson.Parse(data)}
}