package sftp

import (
	"emperror.dev/errors"
	"github.com/apex/log"

	"github.com/Tech-Gamer/nwy-wings/internal/database"
	"github.com/Tech-Gamer/nwy-wings/internal/models"
)

type eventHandler struct {
	ip     string
	user   string
	server string
}

type FileAction struct {
	// Entity is the targeted file or directory (depending on the event) that the action
	// is being performed _against_, such as "/foo/test.txt". This will always be the full
	// path to the element.
	Entity string
	// Target is an optional (often blank) field that only has a value in it when the event
	// is specifically modifying the entity, such as a rename or move event. In that case
	// the Target field will be the final value, such as "/bar/new.txt"
	Target string
}

// Log parses a SFTP specific file activity event and then passes it off to be stored
// in the normal activity database.
func (eh *eventHandler) Log(e models.Event, fa FileAction) error {
	metadata := map[string]interface{}{
		"files": []string{fa.Entity},
	}
	if fa.Target != "" {
		metadata["files"] = []map[string]string{
			{"from": fa.Entity, "to": fa.Target},
		}
	}

	a := models.Activity{
		Server:   eh.server,
		Event:    e,
		Metadata: metadata,
		IP:       eh.ip,
	}

	if tx := database.Instance().Create(a.SetUser(eh.user)); tx.Error != nil {
		return errors.WithStack(tx.Error)
	}
	return nil
}

// MustLog is a wrapper around log that will trigger a fatal error and exit the application
// if an error is encountered during the logging of the event.
func (eh *eventHandler) MustLog(e models.Event, fa FileAction) {
	if err := eh.Log(e, fa); err != nil {
		log.WithField("error", errors.WithStack(err)).WithField("event", e).Error("sftp: failed to log event")
	}
}
