let _Database = null;
async function loadDatabase() {
    if (!_Database) {
        const pkg = 'better-sqlite' + '3';
        const mod = await import(/* webpackIgnore: true */ pkg);
        _Database = mod.default;
    }
    return _Database;
}
import { resolve, dirname } from 'path';
import { mkdirSync, existsSync } from 'fs';
import { AbstractSqlDialect } from './abstract-sql.dialect.js';
// ============================================================
// Type Mapping — DAL FieldType → SQLite column type
// ============================================================
const SQLITE_TYPE_MAP = {
    string: 'TEXT',
    text: 'TEXT',
    number: 'REAL',
    boolean: 'INTEGER',
    date: 'TEXT',
    json: 'TEXT',
    array: 'TEXT',
};
// ============================================================
// SQLiteDialect — normalizer sync → async
// ============================================================
class SQLiteDialect extends AbstractSqlDialect {
    dialectType = 'sqlite';
    /** Exposed for raw access in tests (same pattern as before refactoring) */
    db = null;
    // --- Abstract implementations ---
    quoteIdentifier(name) {
        return `"${name}"`;
    }
    getPlaceholder(_index) {
        return '?';
    }
    fieldToSqlType(field) {
        return SQLITE_TYPE_MAP[field.type] || 'TEXT';
    }
    getIdColumnType() {
        return 'TEXT';
    }
    getTableListQuery() {
        return "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'";
    }
    /** SQLite uses `PRAGMA table_info(name)` — the result column is `name`. */
    async getExistingColumns(tableName) {
        try {
            const rows = await this.executeQuery(`PRAGMA table_info(${this.quoteIdentifier(tableName)})`, []);
            return new Set(rows.map(r => r.name).filter(Boolean));
        }
        catch {
            return new Set();
        }
    }
    // --- Hooks ---
    supportsIfNotExists() { return true; }
    supportsReturning() { return false; }
    serializeBoolean(v) { return v ? 1 : 0; }
    deserializeBoolean(v) { return v === 1 || v === true || v === '1'; }
    // --- Connection lifecycle (sync → async normalizer) ---
    async doConnect(config) {
        const Db = await loadDatabase();
        if (config.uri !== ':memory:') {
            const dbPath = resolve(config.uri);
            const dbDir = dirname(dbPath);
            if (!existsSync(dbDir)) {
                mkdirSync(dbDir, { recursive: true });
            }
            this.db = new Db(dbPath);
        }
        else {
            this.db = new Db(':memory:');
        }
        // WAL mode for better concurrency + referential integrity
        this.db.pragma('journal_mode = WAL');
        this.db.pragma('foreign_keys = ON');
    }
    async doDisconnect() {
        if (this.db) {
            this.db.close();
            this.db = null;
        }
    }
    async doTestConnection() {
        if (!this.db)
            return false;
        try {
            this.db.prepare('SELECT 1').get();
            return true;
        }
        catch {
            return false;
        }
    }
    // --- Query execution (sync → async normalizer) ---
    async doExecuteQuery(sql, params) {
        if (!this.db)
            throw new Error('SQLite not connected. Call connect() first.');
        return this.db.prepare(sql).all(...params);
    }
    async doExecuteRun(sql, params) {
        if (!this.db)
            throw new Error('SQLite not connected. Call connect() first.');
        const result = this.db.prepare(sql).run(...params);
        return { changes: result.changes };
    }
    // --- dropAllTables override (needs foreign_keys OFF for SQLite) ---
    async dropAllTables() {
        if (!this.db)
            return;
        const tables = this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all();
        this.db.pragma('foreign_keys = OFF');
        for (const t of tables) {
            this.db.exec(`DROP TABLE IF EXISTS "${t.name}"`);
        }
        this.db.pragma('foreign_keys = ON');
    }
}
// ============================================================
// Factory export
// ============================================================
export function createDialect() {
    return new SQLiteDialect();
}
