package api

import (
	"agent/client/events"
	"agent/commons/adata"
	"agent/defines/derrs"
	"context"
	"encoding/json"
	"io"

	"github.com/google/uuid"
)

type ClientSchema struct {
	ProjectUuid UUID   `json:"project_uuid"`
	ProjectName string `json:"project_name"`
	Uuid        UUID   `json:"uuid"`
	Name        string `json:"name"`
	Value       string `json:"value"`
	CreatorUuid UUID   `json:"creator_uuid"`
	Created     int64  `json:"created"`
	Updated     int64  `json:"updated"`
}

func ClientSchemaCreate(ctx context.Context, client IClient,
	args ClientSchemaCreateArgs,
) (res ClientSchema, err error) {
	event, err := EventClientSchemaCreate(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 ClientSchemaDelete(ctx context.Context, client IClient,
	uuid uuid.UUID,
) error {
	event, err := EventClientSchemaDelete(uuid)
	if err != nil {
		return err
	}
	_, err = events.ExecuteAndGetData(ctx, client, event)
	return err
}

func ClientSchemaGetData(ctx context.Context, client IClient,
	args ClientSchemaGetDataArgs,
) (res adata.IData, err error) {
	eventIn, err := EventClientSchemaGetData(args)
	if err != nil {
		return res, nil
	}
	eventOut, err := client.Execute(ctx, eventIn)
	if err != nil {
		return nil, err
	}
	data := eventOut.Data()
	if data == nil {
		return res, derrs.NewDataNotFoundError("data not found in event")
	}
	if size, err := data.Size(); err != nil {
		return nil, err
	} else if size == 0 {
		return res, derrs.NewDataNotFoundError("data not found in event")
	}
	return data, nil
}

func ClientSchemaGet(ctx context.Context, client IClient,
	args ClientSchemaGetArgs,
) (res ClientSchema, err error) {
	args_ := ClientSchemaGetDataArgs{
		Kind:        "raw",
		Uuid:        args.Uuid,
		ProjectUuid: args.ProjectUuid,
		Value:       args.Value,
		Name:        args.Name,
	}
	data, err := ClientSchemaGetData(ctx, client, args_)
	if err != nil {
		return res, err
	}
	size, err := data.Size()
	if err != nil {
		return res, err
	}
	if size == 0 {
		return res, derrs.NewDataNotFoundError("data not found in event")
	}
	buff := make([]byte, size)
	_, err = data.Read(buff)
	if err != nil && err != io.EOF {
		return res, err
	}
	return res, json.Unmarshal(buff, &res)
}

func ClientSchemaGetByUuid(ctx context.Context, client IClient,
	uuid uuid.UUID,
) (res ClientSchema, err error) {
	return ClientSchemaGet(ctx, client, ClientSchemaGetArgs{
		Uuid: uuid,
	})
}

func ClientSchemaGetByName(ctx context.Context, client IClient,
	projectUuid uuid.UUID, name string,
) (res ClientSchema, err error) {
	return ClientSchemaGet(ctx, client, ClientSchemaGetArgs{
		ProjectUuid: projectUuid,
		Name:        name,
	})
}

func ClientSchemaGetByValue(ctx context.Context, client IClient,
	projectUuid uuid.UUID, value string,
) (res ClientSchema, err error) {
	return ClientSchemaGet(ctx, client, ClientSchemaGetArgs{
		ProjectUuid: projectUuid,
		Value:       value,
	})
}

func ClientSchemaUpdate(ctx context.Context, client IClient,
	args ClientSchemaUpdateArgs,
) (res ClientSchema, err error) {
	event, err := EventClientSchemaUpdate(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 ClientSchemaList(ctx context.Context, client IClient,
	args ClientSchemaListArgs,
) (res []ClientSchema, err error) {
	eventIn, err := EventClientSchemaList(args)
	if err != nil {
		return res, nil
	}
	data, err := events.ExecuteAndGetData(ctx, client, eventIn)
	if err != nil {
		return res, err
	}
	return res, json.Unmarshal(data, &res)
}

func ClientSchemaListByProject(ctx context.Context, client IClient,
	args ClientSchemaListByProjectArgs,
) (res []ClientSchema, err error) {
	event, err := EventClientSchemaListByProject(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 ClientSchemaListAll(ctx context.Context, client IClient,
	args ClientSchemaListAllArgs,
) (res []ClientSchema, err error) {
	event, err := EventClientSchemaListAll(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)
}
