package api

import (
	"agent/client/events"
	"agent/commons/utils"
	"context"
	"encoding/json"
)

func AgentEventGetInfo(ctx context.Context, client IClient,
	args AgentEventGetInfoArgs,
) (res map[string]any, err error) {
	event, err := EventAgentEventGetInfo(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

type AgentLoginResult struct {
	Config map[string]any `json:"config"`

	Token struct {
		Value string `json:"value"`
	} `json:"token"`

	SrvTime int64 `json:"srv_time"`

	Debug struct {
		Uuid UUID `json:"uuid"`
		New  bool `json:"new"`
	} `json:"debug,omitempty"`
}

func AgentLogin(ctx context.Context, client IClient, startupInfo map[string]any) (res AgentLoginResult, err error) {
	event, err := EventAgentLogin(startupInfo)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

type AgentPingResult struct {
	Utime int64 `json:"utime"`
}

func AgentPing(ctx context.Context, client IClient,
	utime int64,
) (res AgentPingResult, err error) {
	event := EventAgentPing(utime)
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentConfig(ctx context.Context, client IClient) (res map[string]any, err error) {
	event := EventAgentConfig()
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

type AgentRaw struct {
	Uuid           UUID       `json:"uuid"`
	Name           string     `json:"name"`
	Tags           []AgentTag `json:"tags"`
	ProjectUuids   []UUID     `json:"project_uuids"`
	Os             string     `json:"os"`
	OsShortName    string     `json:"os_short_name"`
	Arch           string     `json:"arch"`
	LastCommand    int64      `json:"last_command"`
	LastIpAddrHash string     `json:"last_ip_addr_hash"`
	LastIpAddrList []string   `json:"last_ip_addr_list"`
	LastLogin      int64      `json:"last_login"`
	LastPing       int64      `json:"last_ping"`
	ShortNote      string     `json:"short_note"`
	Created        int64      `json:"created"`
	Updated        int64      `json:"updated"`
}

func AgentGetRaw(ctx context.Context, client IClient,
	uuid UUID,
) (res AgentRaw, err error) {
	args := AgentGetArgs{
		Uuid: uuid,
		Raw:  utils.PointerTo(true),
	}
	event, err := EventAgentGet(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

type Agent struct {
	Arch           string         `json:"arch"`
	Created        int64          `json:"created"`
	LastCommand    int64          `json:"last_command"`
	LastIpAddrHash string         `json:"last_ip_addr_hash"`
	LastIpAddrList []string       `json:"last_ip_addr_list"`
	LastLogin      int64          `json:"last_login"`
	LastPing       int64          `json:"last_ping"`
	Name           string         `json:"name"`
	Os             string         `json:"os"`
	OsShortName    string         `json:"os_short_name"`
	ProjectUuids   []UUID         `json:"project_uuids"`
	ShortNote      string         `json:"short_note"`
	Tags           []AgentTag     `json:"tags"`
	Uuid           UUID           `json:"uuid"`
	Updated        int64          `json:"updated"`
	Settings       map[string]any `json:"settings"`
	Plugin         map[string]any `json:"plugin"`
}

func AgentGet(ctx context.Context, client IClient,
	uuid UUID,
) (res Agent, err error) {
	args := AgentGetArgs{
		Uuid: uuid,
		Raw:  utils.PointerTo(false),
	}
	event, err := EventAgentGet(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentCreateDebug(ctx context.Context, client IClient,
	startupInfo map[string]any,
) (res AgentLoginResult, err error) {
	event, err := EventAgentCreateDebug(startupInfo)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentUpdate(ctx context.Context, client IClient,
	args AgentUpdateArgs,
) (res Agent, err error) {
	event, err := EventAgentUpdate(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentDelete(ctx context.Context, client IClient,
	projectUuid UUID, agentUuid UUID,
) error {
	event, err := EventAgentDelete(projectUuid, agentUuid)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}

type AgentListResult struct {
	NextPage struct {
		Offset int64 `json:"offset"`
		Limit  int64 `json:"limit"`
		Exist  bool  `json:"exist"`
	} `json:"next_page,omitempty"`

	Items []Agent `json:"items"`
}

func AgentList(ctx context.Context, client IClient,
	args AgentListArgs,
) (res AgentListResult, err error) {
	event, err := EventAgentList(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentListByProjectAndUserGroups(ctx context.Context, client IClient,
	args AgentListByProjectAndUserGroupsArgs,
) (res AgentListResult, err error) {
	event, err := EventAgentListByProjectAndUserGroups(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentListByProjectAndAgentGroups(ctx context.Context, client IClient,
	args AgentListByProjectAndAgentGroupsArgs,
) (res AgentListResult, err error) {
	event, err := EventAgentListByProjectAndAgentGroups(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentListByProject(ctx context.Context, client IClient,
	args AgentListByProjectArgs,
) (res AgentListResult, err error) {
	event, err := EventAgentListByProject(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentListByUserGroups(ctx context.Context, client IClient,
	args AgentListByUserGroupsArgs,
) (res AgentListResult, err error) {
	event, err := EventAgentListByUserGroups(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentListByAgentGroups(ctx context.Context, client IClient,
	args AgentListByAgentGroupsArgs,
) (res AgentListResult, err error) {
	event, err := EventAgentListByAgentGroups(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentListAll(ctx context.Context, client IClient,
	args AgentListAllArgs,
) (res AgentListResult, err error) {
	event, err := EventAgentListAll(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentGetNote(ctx context.Context, client IClient,
	uuid UUID,
) (res string, err error) {
	event, err := EventAgentGetNote(uuid)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, event)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func AgentSetNote(ctx context.Context, client IClient,
	uuid UUID, note string,
) error {
	event, err := EventAgentSetNote(uuid, note)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}
