package sql

// |@@| C

import (
	"context"
	"database/sql"
	"gardening/src/lib"
	"gardening/src/lib/filesystem"
	"os"
	"os/exec"
	"path/filepath"
)

type SqliteFsSqlIpl struct {
	Filesystem *filesystem.Filesystem
}

func (this *SqliteFsSqlIpl) Kind() string {
	return "sqlite-fs"
}

func (this *SqliteFsSqlIpl) Driver() string {
	return DRIVER_SQLITE3
}

func (this *SqliteFsSqlIpl) DataSourceName(ctx context.Context, rootDir string) string {
	return rootDir + "/data/db.db"
}

func (this *SqliteFsSqlIpl) SchemaPath(ctx context.Context, rootDir string) string {
	return rootDir + "/data/schema.sqlite.sql"
}

func (this *SqliteFsSqlIpl) IsInMemory(ctx context.Context) bool {
	return false
}

func (this *SqliteFsSqlIpl) SetMaxOpenConns(db *sql.DB, n int) {
	db.SetMaxOpenConns(n)
}

func (this *SqliteFsSqlIpl) Exec(db *sql.DB, query string, args ...any) (sql.Result, error) {
	return db.Exec(query, args...)
}

func (this *SqliteFsSqlIpl) BeginTx(ctx context.Context, db *sql.DB, opts *sql.TxOptions) (*sql.Tx, error) {
	return db.BeginTx(ctx, opts)
}

func (this *SqliteFsSqlIpl) Open(dataSourceName string) (*sql.DB, error) {
	db, err := sql.Open("sqlite3", dataSourceName)
	if err != nil {
		return nil, err
	}
	return db, nil
}

func (this *SqliteFsSqlIpl) Query(db *sql.DB, query string, args ...any) (*sql.Rows, error) {
	return db.Query(query, args...)
}

func (this *SqliteFsSqlIpl) QueryRow(db *sql.DB, query string, args ...any) *sql.Row {
	return db.QueryRow(query, args...)
}

func (this *SqliteFsSqlIpl) Prepare(db *sql.DB, query string) (*sql.Stmt, error) {
	return db.Prepare(query)
}

func (this *SqliteFsSqlIpl) Create(ctx context.Context, dataSourceName string) {
	cmd := exec.Command("sqlite3", "db.db", "VACUUM;")
	cmd.Dir = filepath.Dir(dataSourceName)

	// If debug needed
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	lib.Poe(err)
	//this.Logger.PrintLnWarn(ctx, "Db generated")
}

func (this *SqliteFsSqlIpl) Destroy(ctx context.Context, dataSourceName string) {
	if !this.Filesystem.IsExist(ctx, dataSourceName) {
		return
	}
	err := os.Remove(dataSourceName)
	lib.Poe(err)
}

func (this *SqliteFsSqlIpl) Placeholder(n int) string {
	return "?"
}
