"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.SessionRepository = void 0;
const common_1 = require("@nestjs/common");
const kysely_1 = require("kysely");
const postgres_1 = require("kysely/helpers/postgres");
const luxon_1 = require("luxon");
const nestjs_kysely_1 = require("nestjs-kysely");
const database_1 = require("../database");
const decorators_1 = require("../decorators");
const database_2 = require("../utils/database");
let SessionRepository = class SessionRepository {
    db;
    constructor(db) {
        this.db = db;
    }
    cleanup() {
        return this.db
            .deleteFrom('session')
            .where((eb) => eb.or([
            eb('updatedAt', '<=', luxon_1.DateTime.now().minus({ days: 90 }).toJSDate()),
            eb.and([eb('expiresAt', 'is not', null), eb('expiresAt', '<=', luxon_1.DateTime.now().toJSDate())]),
        ]))
            .returning(['id', 'deviceOS', 'deviceType'])
            .execute();
    }
    get(id) {
        return this.db
            .selectFrom('session')
            .select(['id', 'expiresAt', 'pinExpiresAt'])
            .where('id', '=', id)
            .executeTakeFirst();
    }
    async isPendingSyncReset(id) {
        const result = await this.db
            .selectFrom('session')
            .select(['isPendingSyncReset'])
            .where('id', '=', id)
            .executeTakeFirst();
        return result?.isPendingSyncReset ?? false;
    }
    getByToken(token) {
        return this.db
            .selectFrom('session')
            .select((eb) => [
            ...database_1.columns.authSession,
            (0, postgres_1.jsonObjectFrom)(eb
                .selectFrom('user')
                .select(database_1.columns.authUser)
                .whereRef('user.id', '=', 'session.userId')
                .where('user.deletedAt', 'is', null)).as('user'),
        ])
            .where('session.token', '=', token)
            .where((eb) => eb.or([eb('session.expiresAt', 'is', null), eb('session.expiresAt', '>', luxon_1.DateTime.now().toJSDate())]))
            .executeTakeFirst();
    }
    getByUserId(userId) {
        return this.db
            .selectFrom('session')
            .innerJoin('user', (join) => join.onRef('user.id', '=', 'session.userId').on('user.deletedAt', 'is', null))
            .selectAll('session')
            .where('session.userId', '=', userId)
            .where((eb) => eb.or([eb('session.expiresAt', 'is', null), eb('session.expiresAt', '>', luxon_1.DateTime.now().toJSDate())]))
            .orderBy('session.updatedAt', 'desc')
            .orderBy('session.createdAt', 'desc')
            .execute();
    }
    create(dto) {
        return this.db.insertInto('session').values(dto).returningAll().executeTakeFirstOrThrow();
    }
    update(id, dto) {
        return this.db
            .updateTable('session')
            .set(dto)
            .where('session.id', '=', (0, database_2.asUuid)(id))
            .returningAll()
            .executeTakeFirstOrThrow();
    }
    async delete(id) {
        await this.db.deleteFrom('session').where('id', '=', (0, database_2.asUuid)(id)).execute();
    }
    async invalidateAll({ userId, excludeId }) {
        await this.db
            .deleteFrom('session')
            .where('userId', '=', userId)
            .$if(!!excludeId, (qb) => qb.where('id', '!=', excludeId))
            .execute();
    }
    async invalidateOAuth({ oauthSid, oauthId }) {
        let query = this.db.deleteFrom('session').returning('session.id');
        if (oauthSid && oauthId) {
            query = query
                .using('user')
                .whereRef('user.id', '=', 'session.userId')
                .where('session.oauthSid', '=', oauthSid)
                .where('user.oauthId', '=', oauthId);
        }
        else if (!oauthSid && oauthId) {
            query = query.using('user').whereRef('user.id', '=', 'session.userId').where('user.oauthId', '=', oauthId);
        }
        else if (oauthSid && !oauthId) {
            query = query.where('session.oauthSid', '=', oauthSid);
        }
        else {
            throw new Error('Invalid arguments: at least one of oauthSid or oauthId must be present');
        }
        const deletedRows = await query.execute();
        return deletedRows.map((row) => row.id);
    }
    async lockAll(userId) {
        await this.db.updateTable('session').set({ pinExpiresAt: null }).where('userId', '=', userId).execute();
    }
    async resetSyncProgress(sessionId) {
        await this.db.transaction().execute((tx) => {
            return Promise.all([
                tx.updateTable('session').set({ isPendingSyncReset: false }).where('id', '=', sessionId).execute(),
                tx.deleteFrom('session_sync_checkpoint').where('sessionId', '=', sessionId).execute(),
            ]);
        });
    }
};
exports.SessionRepository = SessionRepository;
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.UUID] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], SessionRepository.prototype, "get", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.UUID] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], SessionRepository.prototype, "isPendingSyncReset", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.STRING] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Buffer]),
    __metadata("design:returntype", void 0)
], SessionRepository.prototype, "getByToken", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.UUID] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], SessionRepository.prototype, "getByUserId", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.UUID] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], SessionRepository.prototype, "delete", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [{ userId: decorators_1.DummyValue.UUID, excludeId: decorators_1.DummyValue.UUID }] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SessionRepository.prototype, "invalidateAll", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.STRING, decorators_1.DummyValue.STRING] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SessionRepository.prototype, "invalidateOAuth", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.UUID] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], SessionRepository.prototype, "lockAll", null);
__decorate([
    (0, decorators_1.GenerateSql)({ params: [decorators_1.DummyValue.UUID] }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], SessionRepository.prototype, "resetSyncProgress", null);
exports.SessionRepository = SessionRepository = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, nestjs_kysely_1.InjectKysely)()),
    __metadata("design:paramtypes", [kysely_1.Kysely])
], SessionRepository);
//# sourceMappingURL=session.repository.js.map