package loggers

import (
	"fmt"

	"github.com/haydenhargreaves/Potion/internal/infrastructure/logging"
	"github.com/jmoiron/sqlx"
)

type DatabaseLogger struct {
	db     *sqlx.DB
	table  string
	filter logging.LogLevel
}

var _ logging.Logger = (*DatabaseLogger)(nil)

func NewDatabaseLogger(conn *sqlx.DB, table string, filter logging.LogLevel) (logging.Logger, error) {
	if conn == nil {
		return &DatabaseLogger{}, fmt.Errorf("Connection is nil, something is very wrong.")
	}
	// Ensure the DB is open
	if err := conn.Ping(); err != nil {
		return &DatabaseLogger{}, err
	}

	// Ensure the table exists
	exists, err := tableExists(conn, table)
	if err != nil {
		return &DatabaseLogger{}, err
	}

	if !exists {
		return &DatabaseLogger{}, fmt.Errorf("Database table '%s' does not exist on provided connection.", table)
	}

	logger := &DatabaseLogger{
		db:     conn,
		table:  table,
		filter: filter,
	}

	return logger, nil
}

// tableExists queries a database connection and returns whether the table name provided
// exists on the table.
func tableExists(conn *sqlx.DB, tableName string) (bool, error) {
	var exists bool
	err := conn.QueryRow(`
		SELECT EXISTS (
			SELECT FROM information_schema.tables 
			WHERE table_schema = 'public' 
			AND table_name = $1
		)`,
		tableName).Scan(&exists)
	return exists, err
}

// Log implements the interface.
func (l *DatabaseLogger) Log(level logging.LogLevel, format string, v ...any) {
	// level is too low, do not log
	if !l.filter.MatchFilter(level) {
		return
	}

	message := fmt.Sprintf(format, v...)
	query := "INSERT INTO logs (level, message) VALUES ($1, $2);"

	// Ignoring result and error, cuz what the hell would we do with them lol
	_, err := l.db.Exec(query, level, message)

	// TODO: Remove
	if err != nil {
		println(err)
	}
}
