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); }
};
var SqlLoggingConfigResolver_1;
import { Arg, Ctx, Field, InputType, Mutation, ObjectType, Query, Int, Resolver } from 'type-graphql';
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
import * as path from 'path';
import * as fs from 'fs/promises';
import { loadConfig } from '../config.js';
import { ResolverBase } from '../generic/ResolverBase.js';
import { GetReadOnlyProvider } from '../util.js';
let SqlLoggingOptions = class SqlLoggingOptions {
    formatAsMigration;
    description;
    statementTypes;
    batchSeparator;
    prettyPrint;
    logRecordChangeMetadata;
    retainEmptyLogFiles;
    filterByUserId;
    sessionName;
};
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptions.prototype, "formatAsMigration", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptions.prototype, "description", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptions.prototype, "statementTypes", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptions.prototype, "batchSeparator", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptions.prototype, "prettyPrint", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptions.prototype, "logRecordChangeMetadata", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptions.prototype, "retainEmptyLogFiles", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptions.prototype, "filterByUserId", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptions.prototype, "sessionName", void 0);
SqlLoggingOptions = __decorate([
    ObjectType()
], SqlLoggingOptions);
export { SqlLoggingOptions };
let SqlLoggingSession = class SqlLoggingSession {
    id;
    filePath;
    startTime;
    statementCount;
    options;
    sessionName;
    filterByUserId;
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], SqlLoggingSession.prototype, "id", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], SqlLoggingSession.prototype, "filePath", void 0);
__decorate([
    Field(() => Date),
    __metadata("design:type", Date)
], SqlLoggingSession.prototype, "startTime", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], SqlLoggingSession.prototype, "statementCount", void 0);
__decorate([
    Field(() => SqlLoggingOptions),
    __metadata("design:type", SqlLoggingOptions)
], SqlLoggingSession.prototype, "options", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingSession.prototype, "sessionName", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingSession.prototype, "filterByUserId", void 0);
SqlLoggingSession = __decorate([
    ObjectType()
], SqlLoggingSession);
export { SqlLoggingSession };
let SqlLoggingOptionsInput = class SqlLoggingOptionsInput {
    formatAsMigration;
    description;
    statementTypes;
    batchSeparator;
    prettyPrint;
    logRecordChangeMetadata;
    retainEmptyLogFiles;
    filterByUserId;
    sessionName;
};
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptionsInput.prototype, "formatAsMigration", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptionsInput.prototype, "description", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptionsInput.prototype, "statementTypes", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptionsInput.prototype, "batchSeparator", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptionsInput.prototype, "prettyPrint", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptionsInput.prototype, "logRecordChangeMetadata", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SqlLoggingOptionsInput.prototype, "retainEmptyLogFiles", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptionsInput.prototype, "filterByUserId", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], SqlLoggingOptionsInput.prototype, "sessionName", void 0);
SqlLoggingOptionsInput = __decorate([
    InputType()
], SqlLoggingOptionsInput);
export { SqlLoggingOptionsInput };
let StartSqlLoggingInput = class StartSqlLoggingInput {
    fileName;
    options;
    filterToCurrentUser;
};
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], StartSqlLoggingInput.prototype, "fileName", void 0);
__decorate([
    Field(() => SqlLoggingOptionsInput, { nullable: true }),
    __metadata("design:type", SqlLoggingOptionsInput)
], StartSqlLoggingInput.prototype, "options", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], StartSqlLoggingInput.prototype, "filterToCurrentUser", void 0);
StartSqlLoggingInput = __decorate([
    InputType()
], StartSqlLoggingInput);
export { StartSqlLoggingInput };
let SqlLoggingConfig = class SqlLoggingConfig {
    enabled;
    defaultOptions;
    allowedLogDirectory;
    maxActiveSessions;
    autoCleanupEmptyFiles;
    sessionTimeout;
    activeSessionCount;
};
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], SqlLoggingConfig.prototype, "enabled", void 0);
__decorate([
    Field(() => SqlLoggingOptions),
    __metadata("design:type", SqlLoggingOptions)
], SqlLoggingConfig.prototype, "defaultOptions", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], SqlLoggingConfig.prototype, "allowedLogDirectory", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], SqlLoggingConfig.prototype, "maxActiveSessions", void 0);
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], SqlLoggingConfig.prototype, "autoCleanupEmptyFiles", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], SqlLoggingConfig.prototype, "sessionTimeout", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], SqlLoggingConfig.prototype, "activeSessionCount", void 0);
SqlLoggingConfig = __decorate([
    ObjectType()
], SqlLoggingConfig);
export { SqlLoggingConfig };
let SqlLoggingConfigResolver = class SqlLoggingConfigResolver extends ResolverBase {
    static { SqlLoggingConfigResolver_1 = this; }
    static LOG_FILE_PREFIX = 'sql-log-';
    async checkOwnerAccess(context) {
        const userEmail = context.userPayload?.email;
        if (!userEmail) {
            throw new Error('User not authenticated');
        }
        const users = UserCache.Instance.Users;
        const user = users.find(u => u.Email.toLowerCase() === userEmail.toLowerCase());
        if (!user) {
            throw new Error('User not found');
        }
        console.log('SQL Logging access check:', {
            email: user.Email,
            type: user.Type,
            typeLength: user.Type?.length,
            typeTrimmed: user.Type?.trim(),
            isOwner: user.Type?.trim().toLowerCase() === 'owner'
        });
        if (user.Type?.trim().toLowerCase() !== 'owner') {
            throw new Error('Access denied. This feature requires Owner privileges.');
        }
        return user;
    }
    async sqlLoggingConfig(context) {
        await this.checkOwnerAccess(context);
        const config = await loadConfig();
        const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const activeSessions = provider.GetActiveSqlLoggingSessions();
        return {
            enabled: config.sqlLogging?.enabled ?? false,
            defaultOptions: config.sqlLogging?.defaultOptions ?? {
                formatAsMigration: false,
                statementTypes: 'both',
                batchSeparator: 'GO',
                prettyPrint: true,
                logRecordChangeMetadata: false,
                retainEmptyLogFiles: false
            },
            allowedLogDirectory: config.sqlLogging?.allowedLogDirectory ?? './logs/sql',
            maxActiveSessions: config.sqlLogging?.maxActiveSessions ?? 5,
            autoCleanupEmptyFiles: config.sqlLogging?.autoCleanupEmptyFiles ?? true,
            sessionTimeout: config.sqlLogging?.sessionTimeout ?? 3600000,
            activeSessionCount: activeSessions.length
        };
    }
    async activeSqlLoggingSessions(context) {
        await this.checkOwnerAccess(context);
        const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const sessions = provider.GetActiveSqlLoggingSessions();
        return sessions.map(session => ({
            id: session.id,
            filePath: session.filePath,
            startTime: session.startTime,
            statementCount: session.statementCount,
            options: session.options,
            sessionName: session.options.sessionName,
            filterByUserId: session.options.filterByUserId
        }));
    }
    async startSqlLogging(input, context) {
        await this.checkOwnerAccess(context);
        const config = await loadConfig();
        if (!config.sqlLogging?.enabled) {
            throw new Error('SQL logging is not enabled in the server configuration');
        }
        const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const activeSessions = provider.GetActiveSqlLoggingSessions();
        if (activeSessions.length >= (config.sqlLogging.maxActiveSessions ?? 5)) {
            throw new Error(`Maximum number of active SQL logging sessions (${config.sqlLogging.maxActiveSessions}) reached`);
        }
        const allowedDir = path.resolve(config.sqlLogging.allowedLogDirectory ?? './logs/sql');
        await this.ensureDirectoryExists(allowedDir);
        const fileName = input.fileName || `${SqlLoggingConfigResolver_1.LOG_FILE_PREFIX}${new Date().toISOString().replace(/[:.]/g, '-')}.sql`;
        const filePath = path.join(allowedDir, fileName);
        const resolvedPath = path.resolve(filePath);
        if (!resolvedPath.startsWith(allowedDir)) {
            throw new Error('Invalid file path - must be within allowed log directory');
        }
        const defaultOptions = config.sqlLogging.defaultOptions || {};
        const userInfo = input.filterToCurrentUser ? this.GetUserFromPayload(context.userPayload) : undefined;
        const sessionOptions = {
            ...defaultOptions,
            ...input.options,
            sessionName: input.options?.sessionName || `Session started by ${context.userPayload.email}`,
            filterByUserId: input.filterToCurrentUser ? userInfo?.ID : input.options?.filterByUserId
        };
        const session = await provider.CreateSqlLogger(filePath, sessionOptions);
        if (config.sqlLogging.sessionTimeout > 0) {
            setTimeout(async () => {
                try {
                    await session.dispose();
                }
                catch (e) {
                }
            }, config.sqlLogging.sessionTimeout);
        }
        return {
            id: session.id,
            filePath: session.filePath,
            startTime: session.startTime,
            statementCount: session.statementCount,
            options: session.options,
            sessionName: session.options.sessionName,
            filterByUserId: session.options.filterByUserId
        };
    }
    async stopSqlLogging(sessionId, context) {
        await this.checkOwnerAccess(context);
        const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const sessionMap = provider._sqlLoggingSessions;
        const session = sessionMap.get(sessionId);
        if (!session) {
            throw new Error(`SQL logging session ${sessionId} not found`);
        }
        await session.dispose();
        return true;
    }
    async stopAllSqlLogging(context) {
        await this.checkOwnerAccess(context);
        const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        await provider.DisposeAllSqlLoggingSessions();
        return true;
    }
    async updateSqlLoggingDefaults(options, context) {
        await this.checkOwnerAccess(context);
        const config = await loadConfig();
        if (!config.sqlLogging) {
            throw new Error('SQL logging configuration not found');
        }
        config.sqlLogging.defaultOptions = {
            ...config.sqlLogging.defaultOptions,
            ...options
        };
        return config.sqlLogging.defaultOptions;
    }
    async readSqlLogFile(sessionId, maxLines, context) {
        await this.checkOwnerAccess(context);
        const config = await loadConfig();
        if (!config.sqlLogging?.enabled) {
            throw new Error('SQL logging is not enabled in the server configuration');
        }
        const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const sessions = provider.GetActiveSqlLoggingSessions();
        const session = sessions.find(s => s.id === sessionId);
        if (!session) {
            throw new Error(`SQL logging session ${sessionId} not found`);
        }
        const allowedDir = path.resolve(config.sqlLogging.allowedLogDirectory ?? './logs/sql');
        const resolvedPath = path.resolve(session.filePath);
        if (!resolvedPath.startsWith(allowedDir)) {
            throw new Error('Access denied - file path outside allowed directory');
        }
        try {
            await fs.access(session.filePath);
            const content = await fs.readFile(session.filePath, 'utf-8');
            if (maxLines && maxLines > 0) {
                const lines = content.split('\n');
                if (lines.length > maxLines) {
                    return lines.slice(-maxLines).join('\n');
                }
            }
            return content;
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                return '-- Log file not yet created or is empty --';
            }
            throw new Error(`Failed to read log file: ${error.message}`);
        }
    }
    async debugCurrentUserEmail(context) {
        await this.checkOwnerAccess(context);
        const contextUserEmail = context.userPayload?.email || 'NOT_SET';
        return `Context User Email: "${contextUserEmail}" | Note: Provider no longer stores user email - uses contextUser parameter for SQL logging`;
    }
    async ensureDirectoryExists(dir) {
        try {
            await fs.access(dir);
        }
        catch {
            await fs.mkdir(dir, { recursive: true });
        }
    }
};
__decorate([
    Query(() => SqlLoggingConfig),
    __param(0, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "sqlLoggingConfig", null);
__decorate([
    Query(() => [SqlLoggingSession]),
    __param(0, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "activeSqlLoggingSessions", null);
__decorate([
    Mutation(() => SqlLoggingSession),
    __param(0, Arg('input', () => StartSqlLoggingInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [StartSqlLoggingInput, Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "startSqlLogging", null);
__decorate([
    Mutation(() => Boolean),
    __param(0, Arg('sessionId', () => String)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "stopSqlLogging", null);
__decorate([
    Mutation(() => Boolean),
    __param(0, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "stopAllSqlLogging", null);
__decorate([
    Mutation(() => SqlLoggingOptions),
    __param(0, Arg('options', () => SqlLoggingOptionsInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [SqlLoggingOptionsInput, Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "updateSqlLoggingDefaults", null);
__decorate([
    Query(() => String),
    __param(0, Arg('sessionId', () => String)),
    __param(1, Arg('maxLines', () => Int, { nullable: true })),
    __param(2, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, Number, Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "readSqlLogFile", null);
__decorate([
    Query(() => String),
    __param(0, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SqlLoggingConfigResolver.prototype, "debugCurrentUserEmail", null);
SqlLoggingConfigResolver = SqlLoggingConfigResolver_1 = __decorate([
    Resolver()
], SqlLoggingConfigResolver);
export { SqlLoggingConfigResolver };
//# sourceMappingURL=SqlLoggingConfigResolver.js.map