var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { Arg, Ctx, Query, Resolver, Field, Int, InputType } from 'type-graphql';
import { LogError } from '@memberjunction/core';
import { SQLExpressionValidator } from '@memberjunction/global';
import { GetReadOnlyDataSource } from '../util.js';
import { ResolverBase } from '../generic/ResolverBase.js';
import { RunQueryResultType } from './QueryResolver.js';
import sql from 'mssql';
/**
 * Input type for executing ad-hoc SQL queries directly.
 * The SQL is validated server-side to ensure it's a safe SELECT/WITH statement.
 */
let AdhocQueryInput = class AdhocQueryInput {
};
__decorate([
    Field(() => String, { description: 'SQL query to execute. Must be a SELECT or WITH (CTE) statement.' }),
    __metadata("design:type", String)
], AdhocQueryInput.prototype, "SQL", void 0);
__decorate([
    Field(() => Int, { nullable: true, description: 'Query timeout in seconds. Defaults to 30.' }),
    __metadata("design:type", Number)
], AdhocQueryInput.prototype, "TimeoutSeconds", void 0);
AdhocQueryInput = __decorate([
    InputType()
], AdhocQueryInput);
/**
 * Resolver for executing ad-hoc (unsaved) SQL queries.
 *
 * Security:
 * - SQL validated via SQLExpressionValidator (full_query context) — blocks mutations, dangerous operations
 * - Executes on read-only connection pool only (no fallback to read-write)
 * - Configurable timeout (default 30s)
 * - Requires authenticated user (standard GraphQL auth, no @RequireSystemUser)
 *
 * Auto-discovered by MJServer's dynamic resolver import.
 */
let AdhocQueryResolver = class AdhocQueryResolver extends ResolverBase {
    async ExecuteAdhocQuery(input, context) {
        const startTime = Date.now();
        try {
            // 1. Security: validate SQL using SQLExpressionValidator
            const validator = SQLExpressionValidator.Instance;
            const validation = validator.validateFullQuery(input.SQL);
            if (!validation.valid) {
                return this.buildErrorResult(validation.error || 'SQL validation failed');
            }
            // 2. Get READ-ONLY data source (no fallback to read-write)
            let readOnlyDS;
            try {
                readOnlyDS = GetReadOnlyDataSource(context.dataSources, { allowFallbackToReadWrite: false });
            }
            catch {
                return this.buildErrorResult('No read-only data source available for ad-hoc query execution');
            }
            // 3. Execute with timeout
            const timeoutMs = (input.TimeoutSeconds ?? 30) * 1000;
            const request = new sql.Request(readOnlyDS);
            const result = await Promise.race([
                request.query(input.SQL),
                new Promise((_, reject) => setTimeout(() => reject(new Error('Query timeout exceeded')), timeoutMs))
            ]);
            const executionTimeMs = Date.now() - startTime;
            // 4. Return as RunQueryResultType
            return {
                QueryID: '',
                QueryName: 'Ad-Hoc Query',
                Success: true,
                Results: JSON.stringify(result.recordset ?? []),
                RowCount: result.recordset?.length ?? 0,
                TotalRowCount: result.recordset?.length ?? 0,
                PageNumber: undefined,
                PageSize: undefined,
                ExecutionTime: executionTimeMs,
                ErrorMessage: ''
            };
        }
        catch (err) {
            const executionTimeMs = Date.now() - startTime;
            const errorMessage = err instanceof Error ? err.message : String(err);
            // Handle timeout
            if (errorMessage.includes('timeout') || errorMessage.includes('Timeout')) {
                return {
                    QueryID: '',
                    QueryName: 'Ad-Hoc Query',
                    Success: false,
                    Results: '[]',
                    RowCount: 0,
                    TotalRowCount: 0,
                    PageNumber: undefined,
                    PageSize: undefined,
                    ExecutionTime: executionTimeMs,
                    ErrorMessage: `Query execution exceeded ${input.TimeoutSeconds ?? 30} second timeout`
                };
            }
            LogError(`Ad-hoc query execution failed: ${errorMessage}`);
            return {
                QueryID: '',
                QueryName: 'Ad-Hoc Query',
                Success: false,
                Results: '[]',
                RowCount: 0,
                TotalRowCount: 0,
                PageNumber: undefined,
                PageSize: undefined,
                ExecutionTime: executionTimeMs,
                ErrorMessage: `Query execution failed: ${errorMessage}`
            };
        }
    }
    buildErrorResult(errorMessage) {
        return {
            QueryID: '',
            QueryName: 'Ad-Hoc Query',
            Success: false,
            Results: '[]',
            RowCount: 0,
            TotalRowCount: 0,
            PageNumber: undefined,
            PageSize: undefined,
            ExecutionTime: 0,
            ErrorMessage: errorMessage
        };
    }
};
__decorate([
    Query(() => RunQueryResultType),
    __param(0, Arg('input', () => AdhocQueryInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [AdhocQueryInput, Object]),
    __metadata("design:returntype", Promise)
], AdhocQueryResolver.prototype, "ExecuteAdhocQuery", null);
AdhocQueryResolver = __decorate([
    Resolver()
], AdhocQueryResolver);
export { AdhocQueryResolver };
//# sourceMappingURL=AdhocQueryResolver.js.map