"use strict";
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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var SessionModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionModule = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const session_entity_1 = require("./entities/session.entity");
const session_manager_service_1 = require("./services/session-manager.service");
const typeorm_session_repository_1 = require("./repositories/typeorm-session.repository");
const memory_session_repository_1 = require("./repositories/memory-session.repository");
const database_session_store_1 = require("./stores/database-session.store");
const redis_session_repository_1 = require("./repositories/redis-session.repository");
const core_module_1 = require("../core/core.module");
const session_options_interface_1 = require("../core/interfaces/session-options.interface");
const auth_config_service_1 = require("../core/services/auth-config.service");
const ms_1 = __importDefault(require("ms"));
let SessionModule = SessionModule_1 = class SessionModule {
    static createRedisStore(session) {
        let RedisClient;
        let redisClient;
        try {
            RedisClient = require('ioredis').default || require('ioredis');
            const redisOptions = SessionModule_1.resolveRedisOptions(session);
            const clientOptions = SessionModule_1.buildRedisClientOptions(redisOptions);
            redisClient = redisOptions.url
                ? new RedisClient(redisOptions.url, clientOptions)
                : new RedisClient(clientOptions);
            const storeOptions = {
                keyPrefix: redisOptions.keyPrefix,
                ttlSeconds: redisOptions.ttlSeconds ?? SessionModule_1.resolveDefaultTtlSeconds(session),
            };
            return new redis_session_repository_1.RedisSessionStore(redisClient, storeOptions);
        }
        catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            if (errorMessage.includes('Cannot find module')) {
                throw new Error('Redis session store selected but redis client dependency not installed. ' +
                    'Install: npm install ioredis');
            }
            throw new Error(`Failed to initialize Redis session storage: ${errorMessage}\n` +
                '   Make sure Redis server is running and accessible.');
        }
    }
    static resolveStorageType(session) {
        const store = session?.storageType ?? session_options_interface_1.SessionStorageType.DATABASE;
        const normalized = String(store).toLowerCase();
        if (normalized === session_options_interface_1.SessionStorageType.REDIS) {
            return session_options_interface_1.SessionStorageType.REDIS;
        }
        if (normalized === session_options_interface_1.SessionStorageType.MEMORY) {
            return session_options_interface_1.SessionStorageType.MEMORY;
        }
        return session_options_interface_1.SessionStorageType.DATABASE;
    }
    static resolveRedisOptions(session) {
        const redis = {
            ...(session?.redis || {}),
        };
        if (!redis.url && session?.redisUrl) {
            redis.url = session.redisUrl;
        }
        return redis;
    }
    static resolveDefaultTtlSeconds(session) {
        const expiry = session?.sessionExpiry;
        if (typeof expiry === 'string') {
            const msValue = (0, ms_1.default)(expiry);
            if (typeof msValue === 'number' && msValue > 0) {
                return Math.floor(msValue / 1000);
            }
        }
        if (typeof expiry === 'number' && expiry > 0) {
            return Math.floor(expiry);
        }
        return 7 * 24 * 60 * 60;
    }
    static buildRedisClientOptions(redis) {
        const options = {
            enableOfflineQueue: redis.enableOfflineQueue ?? true,
            maxRetriesPerRequest: redis.maxRetriesPerRequest ?? null,
            retryStrategy: redis.retryStrategy ||
                ((times) => Math.min(times * 50, 2000)),
            reconnectOnError: redis.reconnectOnError ||
                ((error) => error?.message?.includes('READONLY') ? 2 : false),
        };
        if (redis.host)
            options.host = redis.host;
        if (redis.port !== undefined)
            options.port = redis.port;
        if (redis.password)
            options.password = redis.password;
        if (redis.db !== undefined)
            options.db = redis.db;
        if (redis.tls)
            options.tls = redis.tls;
        return options;
    }
};
exports.SessionModule = SessionModule;
exports.SessionModule = SessionModule = SessionModule_1 = __decorate([
    (0, common_1.Module)({
        imports: [
            typeorm_1.TypeOrmModule.forFeature([session_entity_1.NestAuthSession]),
            (0, common_1.forwardRef)(() => core_module_1.CoreModule),
        ],
        providers: [
            typeorm_session_repository_1.TypeORMSessionRepository,
            memory_session_repository_1.MemorySessionRepository,
            database_session_store_1.DatabaseSessionStore,
            {
                provide: session_manager_service_1.SESSION_STORE,
                useFactory: (databaseStore, memoryStore) => {
                    const config = auth_config_service_1.AuthConfigService.getOptions();
                    const storageType = SessionModule.resolveStorageType(config.session);
                    if (storageType === session_options_interface_1.SessionStorageType.REDIS) {
                        return SessionModule.createRedisStore(config.session);
                    }
                    if (storageType === session_options_interface_1.SessionStorageType.MEMORY) {
                        return memoryStore;
                    }
                    return databaseStore;
                },
                inject: [database_session_store_1.DatabaseSessionStore, memory_session_repository_1.MemorySessionRepository],
            },
            {
                provide: session_manager_service_1.SESSION_REPOSITORY,
                useExisting: session_manager_service_1.SESSION_STORE,
            },
            session_manager_service_1.SessionManagerService,
        ],
        exports: [
            session_manager_service_1.SESSION_STORE,
            session_manager_service_1.SESSION_REPOSITORY,
            session_manager_service_1.SessionManagerService,
            typeorm_session_repository_1.TypeORMSessionRepository,
            memory_session_repository_1.MemorySessionRepository,
            database_session_store_1.DatabaseSessionStore,
        ],
    })
], SessionModule);
//# sourceMappingURL=session.module.js.map