/* eslint-disable @typescript-eslint/require-await */
/**
 * PostgreSQL Database Adapter
 */
import { FeatureFlags } from '../../config/features.js';
import { Logger } from '../../config/logger.js';
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
import { QueryBuilder } from '../QueryBuilder.js';
function assertConnected(state) {
    if (!state.connected)
        throw ErrorFactory.createConnectionError('Database not connected');
}
async function pgConnect(config, state) {
    if (config.host === 'error') {
        throw ErrorFactory.createConnectionError('Failed to connect to PostgreSQL: Connection failed');
    }
    state.connected = true;
    Logger.info(`✓ PostgreSQL connected (${config.host}:${config.port})`);
}
async function pgDisconnect(state) {
    state.connected = false;
    Logger.info('✓ PostgreSQL disconnected');
}
async function pgQuery(state, _sql, _parameters) {
    assertConnected(state);
    // Mock implementation
    return { rows: [], rowCount: 0 };
}
async function pgQueryOne(adapter, sql, parameters) {
    const result = await adapter.query(sql, parameters);
    return result.rows[0] ?? null;
}
async function pgPing(adapter) {
    await adapter.query(QueryBuilder.create('').select('1').toSQL(), []);
}
async function pgTransaction(state, adapter, callback) {
    assertConnected(state);
    try {
        await adapter.query('BEGIN', []);
        const result = await callback(adapter);
        await adapter.query('COMMIT', []);
        return result;
    }
    catch (error) {
        await adapter.query('ROLLBACK', []);
        throw ErrorFactory.createTryCatchError('PostgreSQL transaction failed', error);
    }
}
async function pgRawQuery(state, sql, parameters) {
    if (!FeatureFlags.isRawQueryEnabled()) {
        throw ErrorFactory.createConfigError('Raw SQL queries are disabled. Set USE_RAW_QRY=true environment variable to enable.');
    }
    assertConnected(state);
    Logger.warn(`Raw SQL Query executed: ${sql}`, { parameters });
    try {
        if (sql.toUpperCase().includes('INVALID')) {
            throw ErrorFactory.createDatabaseError('Invalid SQL syntax');
        }
        // Mock implementation
        return [];
    }
    catch (error) {
        throw ErrorFactory.createTryCatchError('Raw SQL Query failed', error);
    }
}
async function pgEnsureMigrationsTable(adapter) {
    await adapter.query(`CREATE TABLE IF NOT EXISTS migrations (
            id SERIAL PRIMARY KEY,
            name VARCHAR(255) NOT NULL,
            scope VARCHAR(255) NOT NULL DEFAULT 'global',
            service VARCHAR(255) NOT NULL DEFAULT '',
            batch INTEGER NOT NULL,
            status VARCHAR(255) NOT NULL,
            applied_at TIMESTAMP NULL,
            created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE(name, scope, service)
          )`, []);
}
function createAdapter(config, state) {
    const adapter = {
        connect: async () => pgConnect(config, state),
        disconnect: async () => pgDisconnect(state),
        query: async (sql, parameters) => pgQuery(state, sql, parameters),
        queryOne: async (sql, parameters) => pgQueryOne(adapter, sql, parameters),
        ping: async () => pgPing(adapter),
        transaction: async (callback) => pgTransaction(state, adapter, callback),
        getType: () => 'postgresql',
        isConnected: () => state.connected,
        rawQuery: async (sql, parameters) => pgRawQuery(state, sql, parameters),
        getPlaceholder: (index) => `$${index}`,
        ensureMigrationsTable: async () => pgEnsureMigrationsTable(adapter),
    };
    return adapter;
}
/**
 * PostgreSQL adapter implementation
 * Sealed namespace for immutability
 */
export const PostgreSQLAdapter = Object.freeze({
    /**
     * Create a new PostgreSQL adapter instance
     */
    create(config) {
        const state = { connected: false };
        return createAdapter(config, state);
    },
});
export default PostgreSQLAdapter;
