package api

import (
	"agent/client/events"
	"agent/commons/adata"
	"agent/commons/utils"
	"agent/defines/devent/daction"
	"agent/defines/devent/dcategory"
	"agent/defines/devent/dkind"
)

type ClientSchemaCreateArgs struct {
	ProjectUuid UUID   `json:"project_uuid"`
	Uuid        UUID   `json:"uuid,omitempty"`
	Name        string `json:"name"`
	Value       string `json:"value,omitempty"`
	Data        []byte `json:"-"`
}

func EventClientSchemaCreate(args ClientSchemaCreateArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	var opts []NewEventOpts
	if len(args.Data) > 0 {
		opts = append(opts, NewEventOpts{
			Data: adata.NewDataFromMem(args.Data),
		})
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.Client, dcategory.Schema},
		daction.Create,
		meta,
		opts...,
	), nil
}

func EventClientSchemaDelete(uuid UUID) (IEvent, error) {
	meta := map[string]any{
		"uuid": uuid,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.Client, dcategory.Schema},
		daction.Delete,
		meta,
	), nil
}

type ClientSchemaGetArgs struct {
	Uuid        UUID   `json:"uuid,omitempty"`
	ProjectUuid UUID   `json:"project_uuid,omitempty"`
	Value       string `json:"value,omitempty"`
	Name        string `json:"name,omitempty"`
}

type ClientSchemaGetDataArgs struct {
	Kind        string `json:"kind"`
	Uuid        UUID   `json:"uuid,omitempty"`
	ProjectUuid UUID   `json:"project_uuid,omitempty"`
	Value       string `json:"value,omitempty"`
	Name        string `json:"name,omitempty"`
}

func EventClientSchemaGetData(args ClientSchemaGetDataArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.Client, dcategory.Schema},
		daction.Get,
		meta,
	), nil
}

type ClientSchemaUpdateArgs struct {
	Uuid  UUID   `json:"uuid"`
	Name  string `json:"name,omitempty"`
	Value string `json:"value,omitempty"`
}

func EventClientSchemaUpdate(args ClientSchemaUpdateArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.Client, dcategory.Schema},
		daction.Update,
		meta,
	), nil
}

type ClientSchemaListArgs struct {
	Kind    string                     `json:"kind"`
	Filter  ClientSchemaListFilterOpts `json:"filter,omitempty"`
	Offset  int64                      `json:"offset,omitempty"`
	Limit   int64                      `json:"limit,omitempty"`
	Reverse *bool                      `json:"reverse,omitempty"`
}

type ClientSchemaListFilterOpts struct {
	ProjectUuid UUID   `json:"project_uuid,omitempty"`
	Search      string `json:"search,omitempty"`
}

func EventClientSchemaList(args ClientSchemaListArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.Client, dcategory.Schema},
		daction.List,
		meta,
	), nil
}

type ClientSchemaListByProjectArgs struct {
	ProjectUuid UUID   `json:"project_uuid"`
	Search      string `json:"search,omitempty"`
	Offset      int64  `json:"offset,omitempty"`
	Limit       int64  `json:"limit,omitempty"`
	Reverse     *bool  `json:"reverse,omitempty"`
}

func EventClientSchemaListByProject(args ClientSchemaListByProjectArgs) (IEvent, error) {
	args_ := ClientSchemaListArgs{
		Kind: "by_project",
		Filter: ClientSchemaListFilterOpts{
			ProjectUuid: args.ProjectUuid,
			Search:      args.Search,
		},
		Offset:  args.Offset,
		Limit:   args.Limit,
		Reverse: args.Reverse,
	}
	return EventClientSchemaList(args_)
}

type ClientSchemaListAllArgs struct {
	Search  string `json:"search,omitempty"`
	Offset  int64  `json:"offset,omitempty"`
	Limit   int64  `json:"limit,omitempty"`
	Reverse *bool  `json:"reverse,omitempty"`
}

func EventClientSchemaListAll(args ...ClientSchemaListAllArgs) (IEvent, error) {
	args_ := ClientSchemaListArgs{
		Kind: "all",
	}
	if len(args) > 0 {
		a := args[0]
		args_.Filter = ClientSchemaListFilterOpts{
			Search: a.Search,
		}
		args_.Offset = a.Offset
		args_.Limit = a.Limit
		args_.Reverse = a.Reverse
	}
	return EventClientSchemaList(args_)
}
