// Microsoft SQL Server Dialect — extends AbstractSqlDialect
// Equivalent to org.hibernate.dialect.SQLServerDialect (Hibernate ORM 6.4)
// Driver: npm install mssql
// Author: Dr Hamid MADANI drmdh@msn.com
import { AbstractSqlDialect } from './abstract-sql.dialect.js';
// ============================================================
// Type Mapping — DAL FieldType → SQL Server column type
// ============================================================
const MSSQL_TYPE_MAP = {
    string: 'NVARCHAR(MAX)',
    number: 'FLOAT',
    boolean: 'BIT',
    date: 'DATETIME2',
    json: 'NVARCHAR(MAX)',
    array: 'NVARCHAR(MAX)',
};
// ============================================================
// MSSQLDialect
// ============================================================
export class MSSQLDialect extends AbstractSqlDialect {
    dialectType = 'mssql';
    pool = null;
    // --- Abstract implementations ---
    quoteIdentifier(name) {
        return `[${name}]`;
    }
    getPlaceholder(index) {
        return `@p${index}`;
    }
    fieldToSqlType(field) {
        return MSSQL_TYPE_MAP[field.type] || 'NVARCHAR(MAX)';
    }
    getIdColumnType() {
        return 'NVARCHAR(36)';
    }
    getTableListQuery() {
        return "SELECT name FROM sys.tables WHERE type = 'U'";
    }
    // --- Hooks ---
    supportsIfNotExists() { return false; }
    // SQL Server supports OUTPUT clause (similar to RETURNING)
    supportsReturning() { return true; }
    // SQL Server BIT: 1 = true, 0 = false
    serializeBoolean(v) { return v ? 1 : 0; }
    deserializeBoolean(v) {
        return v === 1 || v === true || v === '1';
    }
    // SQL Server uses OFFSET/FETCH instead of LIMIT/OFFSET
    buildLimitOffset(options) {
        if (!options?.limit && !options?.skip)
            return '';
        // SQL Server requires ORDER BY for OFFSET/FETCH
        // If no ORDER BY was specified, use (SELECT NULL) as a workaround
        const offset = options.skip ?? 0;
        const limit = options.limit;
        let sql = ` OFFSET ${offset} ROWS`;
        if (limit)
            sql += ` FETCH NEXT ${limit} ROWS ONLY`;
        return sql;
    }
    // Override: SQL Server needs ORDER BY before OFFSET/FETCH
    getCreateTablePrefix(tableName) {
        const q = this.quoteIdentifier(tableName);
        // SQL Server 2016+ supports IF NOT EXISTS via a different pattern
        return `IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = '${tableName}') CREATE TABLE ${q}`;
    }
    getCreateIndexPrefix(indexName, unique) {
        const u = unique ? 'UNIQUE ' : '';
        const q = this.quoteIdentifier(indexName);
        // SQL Server: check if index exists before creating
        return `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = '${indexName}') CREATE ${u}INDEX ${q}`;
    }
    // --- Connection ---
    async doConnect(config) {
        try {
            const mssql = await import(/* webpackIgnore: true */ 'mssql');
            const connect = mssql.default?.connect || mssql.connect;
            this.pool = await connect(config.uri);
        }
        catch (e) {
            throw new Error(`SQL Server driver not found. Install it: npm install mssql\n` +
                `Original error: ${e instanceof Error ? e.message : String(e)}`);
        }
    }
    async doDisconnect() {
        if (this.pool) {
            await this.pool.close();
            this.pool = null;
        }
    }
    async doTestConnection() {
        if (!this.pool)
            return false;
        const request = this.pool.request();
        await request.query('SELECT 1');
        return true;
    }
    // --- Query execution ---
    async doExecuteQuery(sql, params) {
        if (!this.pool)
            throw new Error('SQL Server not connected. Call connect() first.');
        const request = this.pool.request();
        // Bind named parameters @p1, @p2, ...
        for (let i = 0; i < params.length; i++) {
            request.input(`p${i + 1}`, params[i]);
        }
        const result = await request.query(sql);
        return result.recordset;
    }
    async doExecuteRun(sql, params) {
        if (!this.pool)
            throw new Error('SQL Server not connected. Call connect() first.');
        const request = this.pool.request();
        for (let i = 0; i < params.length; i++) {
            request.input(`p${i + 1}`, params[i]);
        }
        const result = await request.query(sql);
        return { changes: result.rowsAffected?.[0] ?? 0 };
    }
    getDialectLabel() { return 'MSSQL'; }
}
// ============================================================
// Factory export
// ============================================================
export function createDialect() {
    return new MSSQLDialect();
}
