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, Field, InputType, Int, ObjectType, Query, Resolver } from 'type-graphql';
import { GraphQLJSONObject } from 'graphql-type-json';
import { RunQuery, LogError, LogStatus } from '@memberjunction/core';
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
import { GetReadOnlyProvider } from '../util.js';
import { ResolverBase } from '../generic/ResolverBase.js';
/**
 * GraphQL input type for inline dependency queries.
 * Self-referencing to support recursive dependency trees.
 */
let QueryDependencySpecInput = class QueryDependencySpecInput {
};
__decorate([
    Field(() => String, { description: 'Query name as referenced in the composition token' }),
    __metadata("design:type", String)
], QueryDependencySpecInput.prototype, "Name", void 0);
__decorate([
    Field(() => String, { description: 'Category path as referenced in the composition token (e.g., "/Analytics/Sales/")' }),
    __metadata("design:type", String)
], QueryDependencySpecInput.prototype, "CategoryPath", void 0);
__decorate([
    Field(() => String, { description: 'The raw SQL for this dependency' }),
    __metadata("design:type", String)
], QueryDependencySpecInput.prototype, "SQL", void 0);
__decorate([
    Field(() => Boolean, { nullable: true, description: 'Whether this dependency uses Nunjucks template syntax' }),
    __metadata("design:type", Boolean)
], QueryDependencySpecInput.prototype, "UsesTemplate", void 0);
__decorate([
    Field(() => GraphQLJSONObject, { nullable: true, description: 'Parameters for this dependency\'s Nunjucks templates' }),
    __metadata("design:type", Object)
], QueryDependencySpecInput.prototype, "Parameters", void 0);
__decorate([
    Field(() => [QueryDependencySpecInput], { nullable: true, description: 'Nested dependencies (recursive)' }),
    __metadata("design:type", Array)
], QueryDependencySpecInput.prototype, "Dependencies", void 0);
QueryDependencySpecInput = __decorate([
    InputType()
], QueryDependencySpecInput);
export { QueryDependencySpecInput };
/**
 * GraphQL input type for transient query execution.
 * Accepts the full QueryExecutionSpec shape for testing unsaved queries
 * with composition + Nunjucks template processing.
 */
let TestQuerySQLInput = class TestQuerySQLInput {
};
__decorate([
    Field(() => String, { description: 'The raw SQL — may contain {{query:"..."}} and {{ param }} tokens' }),
    __metadata("design:type", String)
], TestQuerySQLInput.prototype, "SQL", void 0);
__decorate([
    Field(() => GraphQLJSONObject, { nullable: true, description: 'Parameter values for Nunjucks template substitution' }),
    __metadata("design:type", Object)
], TestQuerySQLInput.prototype, "Parameters", void 0);
__decorate([
    Field(() => Boolean, { nullable: true, description: 'Whether this query uses Nunjucks template syntax' }),
    __metadata("design:type", Boolean)
], TestQuerySQLInput.prototype, "UsesTemplate", void 0);
__decorate([
    Field(() => [QueryDependencySpecInput], { nullable: true, description: 'Inline dependency queries for composition resolution' }),
    __metadata("design:type", Array)
], TestQuerySQLInput.prototype, "Dependencies", void 0);
__decorate([
    Field(() => Int, { nullable: true, defaultValue: 100, description: 'Max rows to return (default: 100)' }),
    __metadata("design:type", Number)
], TestQuerySQLInput.prototype, "MaxRows", void 0);
TestQuerySQLInput = __decorate([
    InputType()
], TestQuerySQLInput);
export { TestQuerySQLInput };
/**
 * GraphQL output type for transient query execution results.
 */
let TestQuerySQLResult = class TestQuerySQLResult {
};
__decorate([
    Field(() => Boolean, { description: 'Whether the query executed successfully' }),
    __metadata("design:type", Boolean)
], TestQuerySQLResult.prototype, "Success", void 0);
__decorate([
    Field(() => String, { nullable: true, description: 'JSON-stringified result rows' }),
    __metadata("design:type", String)
], TestQuerySQLResult.prototype, "Results", void 0);
__decorate([
    Field(() => Int, { description: 'Number of rows returned' }),
    __metadata("design:type", Number)
], TestQuerySQLResult.prototype, "RowCount", void 0);
__decorate([
    Field(() => Int, { description: 'Execution time in milliseconds' }),
    __metadata("design:type", Number)
], TestQuerySQLResult.prototype, "ExecutionTime", void 0);
__decorate([
    Field(() => String, { nullable: true, description: 'Error message if execution failed' }),
    __metadata("design:type", String)
], TestQuerySQLResult.prototype, "ErrorMessage", void 0);
__decorate([
    Field(() => String, { nullable: true, description: 'JSON-stringified applied parameters including defaults' }),
    __metadata("design:type", String)
], TestQuerySQLResult.prototype, "AppliedParameters", void 0);
TestQuerySQLResult = __decorate([
    ObjectType()
], TestQuerySQLResult);
export { TestQuerySQLResult };
/**
 * Resolver for testing transient (unsaved) query SQL with full composition + Nunjucks template processing.
 *
 * This resolver exposes the lower-layer spec-based execution pipeline via GraphQL,
 * enabling external systems (e.g., Skip-Brain) to test query SQL before saving to the database.
 *
 * Security:
 * - Requires system user authentication (@RequireSystemUser)
 * - Uses read-only database connection (no mutation possible)
 * - Enforces MaxRows limit (default 100) to prevent unbounded queries
 *
 * @see https://github.com/MemberJunction/MJ/issues/2172
 */
let TestQuerySQLResolver = class TestQuerySQLResolver extends ResolverBase {
    async TestQuerySQL(input, context) {
        try {
            // Use read-only provider for security — no mutation possible
            const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: false });
            if (!provider) {
                return {
                    Success: false,
                    RowCount: 0,
                    ExecutionTime: 0,
                    ErrorMessage: 'Read-only data source is not available. TestQuerySQL requires a read-only connection for security.',
                };
            }
            const rq = new RunQuery(provider);
            const spec = {
                SQL: input.SQL,
                Parameters: input.Parameters,
                UsesTemplate: input.UsesTemplate,
                Dependencies: input.Dependencies,
                MaxRows: input.MaxRows ?? 100,
            };
            LogStatus(`TestQuerySQL: Executing transient query (MaxRows=${spec.MaxRows}, UsesTemplate=${spec.UsesTemplate ?? false}, Dependencies=${spec.Dependencies?.length ?? 0})`);
            const result = await rq.ExecuteFromSpec(spec, context.userPayload.userRecord);
            return {
                Success: result.Success,
                Results: result.Results ? JSON.stringify(result.Results) : undefined,
                RowCount: result.RowCount,
                ExecutionTime: result.ExecutionTime,
                ErrorMessage: result.ErrorMessage || undefined,
                AppliedParameters: result.AppliedParameters ? JSON.stringify(result.AppliedParameters) : undefined,
            };
        }
        catch (err) {
            LogError(err);
            const errorMessage = err instanceof Error ? err.message : String(err);
            return {
                Success: false,
                RowCount: 0,
                ExecutionTime: 0,
                ErrorMessage: `TestQuerySQL failed: ${errorMessage}`,
            };
        }
    }
};
__decorate([
    RequireSystemUser(),
    Query(() => TestQuerySQLResult, {
        description: 'Test transient SQL with full composition + Nunjucks template processing without requiring a saved query'
    }),
    __param(0, Arg('input', () => TestQuerySQLInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [TestQuerySQLInput, Object]),
    __metadata("design:returntype", Promise)
], TestQuerySQLResolver.prototype, "TestQuerySQL", null);
TestQuerySQLResolver = __decorate([
    Resolver()
], TestQuerySQLResolver);
export { TestQuerySQLResolver };
//# sourceMappingURL=TestQuerySQLResolver.js.map