/* eslint-disable @typescript-eslint/require-await */
/**
 * MySQL Database Adapter
 */
import { FeatureFlags } from '../../config/features.js';
import { Logger } from '../../config/logger.js';
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
import { AdaptersEnum } from '../../migrations/enum/index.js';
import { QueryBuilder } from '../QueryBuilder.js';
function createRawQuery(state) {
    return async function rawQuery(sql, parameters) {
        if (!FeatureFlags.isRawQueryEnabled()) {
            throw ErrorFactory.createConfigError('Raw SQL queries are disabled');
        }
        if (!state.connected) {
            throw ErrorFactory.createConnectionError('Database not connected');
        }
        try {
            Logger.warn(`Raw SQL Query executed: ${sql}`, { parameters });
            // Mock implementation for tests
            if (sql.includes('INVALID')) {
                throw ErrorFactory.createDatabaseError('Invalid SQL syntax');
            }
            return [];
        }
        catch (error) {
            throw ErrorFactory.createTryCatchError(`Raw SQL query failed: ${sql}`, error);
        }
    };
}
function createMySQLAdapterInstance(config, state) {
    return {
        async connect() {
            if (config.host === 'error') {
                throw ErrorFactory.createConnectionError('Failed to connect to MySQL: Error: Connection failed');
            }
            state.connected = true;
            Logger.info(`✓ MySQL connected (${config.host}:${config.port})`);
        },
        async disconnect() {
            state.connected = false;
            Logger.info('✓ MySQL disconnected');
        },
        async query(_sql, _parameters) {
            if (!state.connected)
                throw ErrorFactory.createConnectionError('Database not connected');
            // Mock implementation
            return { rows: [], rowCount: 0 };
        },
        async queryOne(sql, parameters) {
            const result = await this.query(sql, parameters);
            return result.rows[0] ?? null;
        },
        async ping() {
            await this.query(QueryBuilder.create('').select('1').toSQL(), []);
        },
        async transaction(callback) {
            if (!state.connected)
                throw ErrorFactory.createConnectionError('Database not connected');
            try {
                await this.query('START TRANSACTION', []);
                const result = await callback(this);
                await this.query('COMMIT', []);
                return result;
            }
            catch (error) {
                await this.query('ROLLBACK', []);
                throw ErrorFactory.createTryCatchError('MySQL transaction failed', error);
            }
        },
        getType() {
            return AdaptersEnum.mysql;
        },
        isConnected() {
            return state.connected;
        },
        rawQuery: createRawQuery(state),
        getPlaceholder(_index) {
            return '?';
        },
        async ensureMigrationsTable() {
            await this.query(`CREATE TABLE IF NOT EXISTS migrations (
            id INTEGER PRIMARY KEY AUTO_INCREMENT,
            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 DATETIME NULL,
            created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            UNIQUE(name, scope, service)
          )`, []);
        },
    };
}
/**
 * MySQL adapter implementation
 * Sealed namespace for immutability
 */
export const MySQLAdapter = Object.freeze({
    /**
     * Create a new MySQL adapter instance
     */
    create(config) {
        const state = { connected: false };
        return createMySQLAdapterInstance(config, state);
    },
});
export default MySQLAdapter;
