package api

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

func EventLfsReset(agentUuid UUID) (IEvent, error) {
	meta := map[string]any{
		"agent_uuid": agentUuid,
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs},
		daction.Reset,
		meta,
		events.NewEventOpts{},
	), nil
}

type LfsCreateFileArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	Path      string `json:"path"`
	Rewrite   bool   `json:"rewrite"`
	DirCreate bool   `json:"dir_create"`

	Data adata.IData `json:"-"`
	// При указании переопределит стандартные опции запроса и ответа
	RequestOpts  *EventRequestOpts  `json:"-"`
	ResponseOpts *EventResponseOpts `json:"-"`
}

func EventLfsCreateFile(args LfsCreateFileArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	opts := events.NewEventOpts{}
	if args.Data != nil {
		opts.Data = args.Data

		size, err := args.Data.Size()
		if err != nil {
			return nil, err
		}

		if size > 0 && size > 4*1024 {
			opts.DataMaxSize = size
			opts.Request = &EventRequestOpts{
				Handler: dhandlers.OctetStream,
				Binary:  utils.PointerTo(true),
			}
			opts.Response = &EventResponseOpts{
				Handler: `application/octet-stream`,
				Type:    `application/octet-stream`,
			}
		}
	}

	if args.RequestOpts != nil {
		opts.Request = args.RequestOpts
	}
	if args.ResponseOpts != nil {
		opts.Response = args.ResponseOpts
	}

	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.File},
		daction.Create,
		meta,
		opts,
	), nil
}

type LfsGetFileArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	Path      string `json:"path"`
	Uuid      UUID   `json:"uuid"`
}

func EventLfsGetFile(args LfsGetFileArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.File},
		daction.Get,
		meta,
	), nil
}

type LfsCreateFolderArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	Path      string `json:"path"`
}

func EventLfsCreateFolder(args LfsCreateFolderArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.Folder},
		daction.Create,
		meta,
	), nil
}

type LfsListFolderArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	Path      string `json:"path"`
	Uuid      UUID   `json:"uuid"`
	Deep      int    `json:"deep"`
}

func EventLfsListFolder(args LfsListFolderArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.Folder},
		daction.List,
		meta,
	), nil
}

type LfsDeleteItemArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	Path      string `json:"path"`
	Uuid      UUID   `json:"uuid"`
}

func EventLfsDeleteItem(args LfsDeleteItemArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.Item},
		daction.Delete,
		meta,
	), nil
}

type LfsGetItemInfoArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	Path      string `json:"path"`
	Uuid      UUID   `json:"uuid"`
}

func EventLfsGetItemInfo(args LfsGetItemInfoArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.Item, dcategory.Info},
		daction.Get,
		meta,
	), nil
}

type LfsGetItemPathArgs struct {
	AgentUuid UUID `json:"agent_uuid"`
	Uuid      UUID `json:"uuid"`
}

func EventLfsGetItemPath(args LfsGetItemPathArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.Item, dcategory.Path},
		daction.Get,
		meta,
	), nil
}

type LfsMoveItemArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	FromPath  string `json:"from_path"`
	ToPath    string `json:"to_path"`
}

func EventLfsMoveItem(args LfsMoveItemArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.Item},
		daction.Move,
		meta,
	), nil
}

type LfsRenameItemArgs struct {
	AgentUuid UUID   `json:"agent_uuid"`
	FromPath  string `json:"from_path"`
	ToPath    string `json:"to_path"`
}

func EventLfsRenameItem(args LfsRenameItemArgs) (IEvent, error) {
	meta, err := utils.ConvertTo[map[string]any](args)
	if err != nil {
		return nil, err
	}
	return events.NewEvent(
		dkind.UserToService,
		[]Category{dcategory.Agent, dcategory.Lfs, dcategory.Item},
		daction.Rename,
		meta,
	), nil
}
