package l4g

import (
	"encoding/json"
)

const (
	LOGGER_TYPE_TERMINAL = "terminal"
	LOGGER_TYPE_FILE     = "file"
	LOGGER_TYPE_DATABASE = "database"
)

var globalLogger Logger

const (
	CATEGORY_SYSTEM int32 = 0 // System-level logging, such as server starting, database connection problems, etc.
	CATEGORY_ADMIN  int32 = 1 // Administrative logging, used for CRM, and any "internal" action taken by an employee
	CATEGORY_USER   int32 = 2 // General category for actions performed by / for a user (E.g. user updates their account)
	CATEGORY_ORG    int32 = 3 // General category for actions performed by / for an organization (E.g. User updates company profile)
	CATEGORY_AUDIT  int32 = 4 // Category for transactional logging (Accept request, decline, modified transaction record)
	CATEGORY_AUTH   int32 = 5 // Authentication / Authorization messages (User logged in, failed login attempts, user failed authorization check, out-of-country IP, etc)
)

const (
	TYPE_DEBUG int32 = 0 // Testing and debugging log. Should not really be used too often since debug logging statements should be cleaned once an issue is resolved.
	TYPE_INFO  int32 = 1 // General log message
	TYPE_WARN  int32 = 2 // "Incorrect" actions taken. Includes failed login attempts, validation issues, etc. Nothing that is a "problem" for us, just malformed user input.
	TYPE_ERROR int32 = 3 // Failed program state/behavior. Used for issues such as database connection failures, web API connection failures, etc.

	TYPE_CREATE int32 = 4 // Resource created  - Does not need to be broken down to each individual row created in a db table, but rather the "logical action" taken by a user.
	TYPE_READ   int32 = 5 // Resource consumed - Does not need to be broken down to each individual row created in a db table, but rather the "logical action" taken by a user.
	TYPE_UPDATE int32 = 6 // Resource updated  - Does not need to be broken down to each individual row created in a db table, but rather the "logical action" taken by a user.
	TYPE_DELETE int32 = 7 // Resource deleted  - Does not need to be broken down to each individual row created in a db table, but rather the "logical action" taken by a user.
)

type Logger interface {
	Write(entry Entry) error
	Fatal(entry Entry) error
}

func Init(loggerType string, logFilePath ...string) error {
	switch loggerType {
	case LOGGER_TYPE_TERMINAL:
		globalLogger = NewTerminalLogger()
	case LOGGER_TYPE_FILE:
		filePath := "./app.log"
		if len(logFilePath) > 0 && logFilePath[0] != "" {
			filePath = logFilePath[0]
		}
		globalLogger = NewFileLogger(filePath)
	case LOGGER_TYPE_DATABASE:
		globalLogger = NewDatabaseLogger()
	default:
		globalLogger = NewTerminalLogger()
	}
	return nil
}

func GetLogger() Logger {
	if globalLogger == nil {
		globalLogger = NewTerminalLogger()
	}
	return globalLogger
}

func Serialize(data any) *string {
	var structuredJSON *string
	if data != nil {
		if jsonBytes, err := json.Marshal(data); err == nil {
			jsonString := string(jsonBytes)
			structuredJSON = &jsonString
		}
	}

	return structuredJSON
}

func Write(entry Entry) error {
	return GetLogger().Write(entry)
}

func Fatal(entry Entry) error {
	return GetLogger().Fatal(entry)
}
