"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 __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); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisSessionRepository = void 0;
const common_1 = require("@nestjs/common");
const base_session_repository_1 = require("./base-session.repository");
const uuid_1 = require("uuid");
let Redis;
let InjectRedis;
try {
    Redis = require('ioredis').default || require('ioredis');
    const ioredisModule = require('@nestjs-modules/ioredis');
    InjectRedis = ioredisModule.InjectRedis;
}
catch (e) {
}
let RedisSessionRepository = class RedisSessionRepository extends base_session_repository_1.BaseSessionRepository {
    prefix = 'nest-auth:session:';
    userSessionsPrefix = 'nest-auth:user-sessions:';
    redis;
    constructor(redisClient) {
        super();
        if (!redisClient) {
            throw new Error('RedisSessionRepository requires ioredis and @nestjs-modules/ioredis packages. ' +
                'Install them with: npm install ioredis @nestjs-modules/ioredis');
        }
        this.redis = redisClient;
    }
    getSessionKey(sessionId) {
        return `${this.prefix}${sessionId}`;
    }
    getUserSessionsKey(userId) {
        return `${this.userSessionsPrefix}${userId}`;
    }
    async create(session) {
        const sessionId = session.id || (0, uuid_1.v4)();
        const sessionKey = this.getSessionKey(sessionId);
        const userSessionsKey = this.getUserSessionsKey(session.userId);
        const sessionData = {
            id: sessionId,
            userId: session.userId,
            refreshToken: session.refreshToken,
            data: session.data,
            expiresAt: session.expiresAt,
            userAgent: session.userAgent,
            deviceName: session.deviceName,
            ipAddress: session.ipAddress,
            lastActive: session.lastActive || new Date(),
        };
        const serialized = this.serializeSession(sessionData);
        await this.redis.hmset(sessionKey, serialized);
        await this.redis.sadd(userSessionsKey, sessionId);
        const ttl = Math.floor((session.expiresAt.getTime() - Date.now()) / 1000);
        if (ttl > 0) {
            await this.redis.expire(sessionKey, ttl);
        }
        return sessionData;
    }
    async findById(sessionId) {
        const sessionKey = this.getSessionKey(sessionId);
        const data = await this.redis.hgetall(sessionKey);
        if (!data || Object.keys(data).length === 0) {
            return null;
        }
        return this.deserializeSession(data);
    }
    async findByUserId(userId) {
        const userSessionsKey = this.getUserSessionsKey(userId);
        const sessionIds = await this.redis.smembers(userSessionsKey);
        const sessions = [];
        for (const sessionId of sessionIds) {
            const session = await this.findById(sessionId);
            if (session) {
                sessions.push(session);
            }
        }
        return sessions;
    }
    async findActiveByUserId(userId) {
        const allSessions = await this.findByUserId(userId);
        return this.filterActive(allSessions);
    }
    async update(sessionId, updates) {
        const sessionKey = this.getSessionKey(sessionId);
        const serialized = this.serializeSession(updates);
        await this.redis.hmset(sessionKey, serialized);
        return await this.findById(sessionId);
    }
    async delete(sessionId) {
        const session = await this.findById(sessionId);
        if (!session)
            return;
        const sessionKey = this.getSessionKey(sessionId);
        const userSessionsKey = this.getUserSessionsKey(session.userId);
        await this.redis.del(sessionKey);
        await this.redis.srem(userSessionsKey, sessionId);
    }
    async deleteByUserId(userId) {
        const userSessionsKey = this.getUserSessionsKey(userId);
        const sessionIds = await this.redis.smembers(userSessionsKey);
        const pipeline = this.redis.pipeline();
        for (const sessionId of sessionIds) {
            pipeline.del(this.getSessionKey(sessionId));
        }
        pipeline.del(userSessionsKey);
        await pipeline.exec();
    }
    async deleteExpired() {
        return 0;
    }
    async countActiveByUserId(userId) {
        const activeSessions = await this.findActiveByUserId(userId);
        return activeSessions.length;
    }
    async updateLastActive(sessionId) {
        await this.update(sessionId, {
            lastActive: new Date(),
        });
    }
};
exports.RedisSessionRepository = RedisSessionRepository;
exports.RedisSessionRepository = RedisSessionRepository = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, common_1.Optional)()),
    __param(0, (0, common_1.Inject)('REDIS_CLIENT')),
    __metadata("design:paramtypes", [Object])
], RedisSessionRepository);
//# sourceMappingURL=redis-session.repository.js.map