package api

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

type AgentGroupCreateArgs struct {
	Uuid        UUID           `json:"uuid,omitempty"`
	ProjectUuid UUID           `json:"project_uuid"`
	Name        string         `json:"name"`
	Settings    map[string]any `json:"settings,omitempty"`
}

func EventAgentGroupCreate(args AgentGroupCreateArgs) (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.AgentGroup},
		daction.Create,
		meta,
	), nil
}

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

type AgentGroupUpdateArgs struct {
	Uuid     UUID           `json:"uuid"`
	Name     string         `json:"name,omitempty"`
	Settings map[string]any `json:"settings,omitempty"`
}

func EventAgentGroupUpdate(args AgentGroupUpdateArgs) (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.AgentGroup},
		daction.Update,
		meta,
	), nil
}

type AgentGroupGetArgs struct {
	Uuid        UUID   `json:"uuid,omitempty"`
	ProjectUuid UUID   `json:"project_uuid,omitempty"`
	Name        string `json:"group_name,omitempty"`
	Raw         *bool  `json:"raw,omitempty"`
}

func EventAgentGroupGet(args AgentGroupGetArgs) (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.AgentGroup},
		daction.Get,
		meta,
	), nil
}

type AgentGroupListArgs struct {
	Kind   string                   `json:"kind"`
	Filter AgentGroupListFilterOpts `json:"filter,omitempty"`
	Admin  *bool                    `json:"admin,omitempty"`
	Raw    *bool                    `json:"raw,omitempty"`
}

type AgentGroupListFilterOpts struct {
	ProjectUuid    UUID                      `json:"project_uuid,omitempty"`
	UserGroupUuids []UUID                    `json:"user_group_uuids,omitempty"`
	ClientKeyUuid  UUID                      `json:"client_key_uuid,omitempty"`
	AgentUuids     []UUID                    `json:"agent_uuids,omitempty"`
	Search         string                    `json:"search,omitempty"`
	Exclude        AgentGroupListExcludeOpts `json:"exclude,omitempty"`
}

type AgentGroupListExcludeOpts struct {
	UserGroupUuids []UUID `json:"user_group_uuids,omitempty"`
	ClientKeyUuids []UUID `json:"client_key_uuids,omitempty"`
}

func EventAgentGroupList(args AgentGroupListArgs) (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.AgentGroup},
		daction.List,
		meta,
	), nil
}

type AgentGroupListByProjectAndUserGroupsArgs struct {
	ProjectUuid    UUID
	UserGroupUuids []UUID
	Search         string
	Exclude        *AgentGroupListExcludeOpts
	Raw            *bool
	Admin          *bool
}

func EventAgentGroupListByProjectAndUserGroups(args AgentGroupListByProjectAndUserGroupsArgs) (IEvent, error) {
	args_ := AgentGroupListArgs{
		Kind: "by_project_and_user_groups",
		Filter: AgentGroupListFilterOpts{
			ProjectUuid:    args.ProjectUuid,
			UserGroupUuids: args.UserGroupUuids,
			Search:         args.Search,
		},
		Raw:   args.Raw,
		Admin: args.Admin,
	}
	if args.Exclude != nil {
		args_.Filter.Exclude = *args.Exclude
	}
	return EventAgentGroupList(args_)
}

type AgentGroupListByProjectAndAgentsArgs struct {
	ProjectUuid UUID
	AgentUuids  []UUID
	Search      string
	Exclude     *AgentGroupListExcludeOpts
	Raw         *bool
	Admin       *bool
}

func EventAgentGroupListByProjectAndAgents(args AgentGroupListByProjectAndAgentsArgs) (IEvent, error) {
	args_ := AgentGroupListArgs{
		Kind: "by_project_and_agents",
		Filter: AgentGroupListFilterOpts{
			ProjectUuid: args.ProjectUuid,
			AgentUuids:  args.AgentUuids,
			Search:      args.Search,
		},
		Raw:   args.Raw,
		Admin: args.Admin,
	}
	if args.Exclude != nil {
		args_.Filter.Exclude = *args.Exclude
	}
	return EventAgentGroupList(args_)
}

type AgentGroupListByProjectArgs struct {
	ProjectUuid UUID
	Search      string
	Exclude     *AgentGroupListExcludeOpts
	Raw         *bool
	Admin       *bool
}

func EventAgentGroupListByProject(args AgentGroupListByProjectArgs) (IEvent, error) {
	args_ := AgentGroupListArgs{
		Kind: "by_project",
		Filter: AgentGroupListFilterOpts{
			ProjectUuid: args.ProjectUuid,
			Search:      args.Search,
		},
		Raw:   args.Raw,
		Admin: args.Admin,
	}
	if args.Exclude != nil {
		args_.Filter.Exclude = *args.Exclude
	}
	return EventAgentGroupList(args_)
}

type AgentGroupListByUserGroupsArgs struct {
	UserGroupUuids []UUID
	Search         string
	Exclude        *AgentGroupListExcludeOpts
	Raw            *bool
	Admin          *bool
}

func EventAgentGroupListByUserGroups(args AgentGroupListByUserGroupsArgs) (IEvent, error) {
	args_ := AgentGroupListArgs{
		Kind: "by_user_groups",
		Filter: AgentGroupListFilterOpts{
			UserGroupUuids: args.UserGroupUuids,
			Search:         args.Search,
		},
		Raw:   args.Raw,
		Admin: args.Admin,
	}
	if args.Exclude != nil {
		args_.Filter.Exclude = *args.Exclude
	}
	return EventAgentGroupList(args_)
}

type AgentGroupListByClientKeyArgs struct {
	ClientKeyUuid UUID
	Search        string
	Exclude       *AgentGroupListExcludeOpts
	Raw           *bool
	Admin         *bool
}

func EventAgentGroupListByClientKey(args AgentGroupListByClientKeyArgs) (IEvent, error) {
	args_ := AgentGroupListArgs{
		Kind: "by_client_key",
		Filter: AgentGroupListFilterOpts{
			ClientKeyUuid: args.ClientKeyUuid,
			Search:        args.Search,
		},
		Raw:   args.Raw,
		Admin: args.Admin,
	}
	if args.Exclude != nil {
		args_.Filter.Exclude = *args.Exclude
	}
	return EventAgentGroupList(args_)
}

type AgentGroupListByAgentsArgs struct {
	AgentUuids []UUID
	Search     string
	Exclude    *AgentGroupListExcludeOpts
	Raw        *bool
	Admin      *bool
}

func EventAgentGroupListByAgents(args AgentGroupListByAgentsArgs) (IEvent, error) {
	args_ := AgentGroupListArgs{
		Kind: "by_agents",
		Filter: AgentGroupListFilterOpts{
			AgentUuids: args.AgentUuids,
			Search:     args.Search,
		},
		Raw:   args.Raw,
		Admin: args.Admin,
	}
	if args.Exclude != nil {
		args_.Filter.Exclude = *args.Exclude
	}
	return EventAgentGroupList(args_)
}

type AgentGroupListAllArgs struct {
	Search  string
	Exclude *AgentGroupListExcludeOpts
	Raw     *bool
	Admin   *bool
}

func EventAgentGroupListAll(args AgentGroupListAllArgs) (IEvent, error) {
	args_ := AgentGroupListArgs{
		Kind: "all",
		Filter: AgentGroupListFilterOpts{
			Search:  args.Search,
			Exclude: AgentGroupListExcludeOpts{},
		},
		Raw:   args.Raw,
		Admin: args.Admin,
	}
	if args.Exclude != nil {
		args_.Filter.Exclude = *args.Exclude
	}
	return EventAgentGroupList(args_)
}

func EventAgentGroupAddAgent(agentGroupUuids []UUID, agentUuids []UUID) (IEvent, error) {
	meta := map[string]any{
		"group_uuid_list": agentGroupUuids,
		"agent_uuid_list": agentUuids,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.AgentGroup, dcategory.Agent},
		daction.Add,
		meta,
	), nil
}

func EventAgentGroupDeleteAgent(agentGroupUuids []UUID, agentUuids []UUID) (IEvent, error) {
	meta := map[string]any{
		"group_uuid_list": agentGroupUuids,
		"agent_uuid_list": agentUuids,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.AgentGroup, dcategory.Agent},
		daction.Delete,
		meta,
	), nil
}

func EventAgentGroupAddUserGroup(agentGroupUuids []UUID, userGroupUuids []UUID) (IEvent, error) {
	meta := map[string]any{
		"agent_group_uuid_list": agentGroupUuids,
		"user_group_uuid_list":  userGroupUuids,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.AgentGroup, dcategory.UserGroup},
		daction.Add,
		meta,
	), nil
}

func EventAgentGroupDeleteUserGroup(agentGroupUuids []UUID, userGroupUuids []UUID) (IEvent, error) {
	meta := map[string]any{
		"agent_group_uuid_list": agentGroupUuids,
		"user_group_uuid_list":  userGroupUuids,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.AgentGroup, dcategory.UserGroup},
		daction.Delete,
		meta,
	), nil
}

func EventAgentGroupAddClientKey(agentGroupUuids []UUID, clientKeyUuids []UUID) (IEvent, error) {
	meta := map[string]any{
		"group_uuid_list": agentGroupUuids,
		"key_uuid_list":   clientKeyUuids,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.AgentGroup, dcategory.Client, dcategory.Key},
		daction.Add,
		meta,
	), nil
}

func EventAgentGroupDeleteClientKey(agentGroupUuids []UUID, clientKeyUuids []UUID) (IEvent, error) {
	meta := map[string]any{
		"group_uuid_list": agentGroupUuids,
		"key_uuid_list":   clientKeyUuids,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Service, dcategory.AgentGroup, dcategory.Client, dcategory.Key},
		daction.Delete,
		meta,
	), nil
}
