package db

import (
	"database/sql"
	"fmt"
	"os"

	_ "modernc.org/sqlite"
)

// Store wraps a SQLite database connection for mc-proxy persistence.
type Store struct {
	db *sql.DB
}

// Open opens (or creates) the SQLite database at path with WAL mode,
// foreign keys, and a busy timeout. The file is created with 0600 permissions.
func Open(path string) (*Store, error) {
	// Ensure the file has restrictive permissions if it doesn't exist.
	if _, err := os.Stat(path); os.IsNotExist(err) {
		f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0600)
		if err != nil {
			return nil, fmt.Errorf("creating database file: %w", err)
		}
		f.Close()
	}

	db, err := sql.Open("sqlite", path)
	if err != nil {
		return nil, fmt.Errorf("opening database: %w", err)
	}

	// Apply connection pragmas.
	pragmas := []string{
		"PRAGMA journal_mode = WAL",
		"PRAGMA foreign_keys = ON",
		"PRAGMA busy_timeout = 5000",
	}
	for _, p := range pragmas {
		if _, err := db.Exec(p); err != nil {
			db.Close()
			return nil, fmt.Errorf("setting pragma %q: %w", p, err)
		}
	}

	return &Store{db: db}, nil
}

// Close closes the database connection.
func (s *Store) Close() error {
	return s.db.Close()
}

// IsEmpty returns true if the listeners table has no rows.
// Used to determine if the database needs seeding from config.
func (s *Store) IsEmpty() (bool, error) {
	var count int
	err := s.db.QueryRow("SELECT COUNT(*) FROM listeners").Scan(&count)
	if err != nil {
		return false, err
	}
	return count == 0, nil
}
