"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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenResponseInterceptor = void 0;
const common_1 = require("@nestjs/common");
const operators_1 = require("rxjs/operators");
const auth_config_service_1 = require("../../core/services/auth-config.service");
const auth_constants_1 = require("../../auth.constants");
const ms_1 = __importDefault(require("ms"));
const lodash_1 = require("lodash");
const cookie_helper_1 = require("../../utils/cookie.helper");
const debug_logger_service_1 = require("../../core/services/debug-logger.service");
let TokenResponseInterceptor = class TokenResponseInterceptor {
    debugLogger;
    options;
    constructor(debugLogger) {
        this.debugLogger = debugLogger;
        this.options = auth_config_service_1.AuthConfigService.getOptions();
    }
    isUsingCookies(req) {
        const headerTokenType = req.headers['x-access-token-type'];
        const accessTokenType = this.options.session?.accessTokenType ?? null;
        if (!accessTokenType && headerTokenType === 'cookie') {
            this.debugLogger.debug('Using cookies mode (from x-access-token-type header)', 'TokenResponseInterceptor', { headerTokenType });
            return true;
        }
        else if (accessTokenType === 'cookie') {
            this.debugLogger.debug('Using cookies mode (from config)', 'TokenResponseInterceptor', { configTokenType: accessTokenType });
            return true;
        }
        this.debugLogger.debug('Using header mode for tokens', 'TokenResponseInterceptor', { configTokenType: accessTokenType, headerTokenType });
        return false;
    }
    async intercept(context, next) {
        const ctx = context.switchToHttp();
        const req = ctx.getRequest();
        const res = ctx.getResponse();
        const isUsingCookies = await this.isUsingCookies(req);
        this.debugLogger.logFunctionEntry('intercept', 'TokenResponseInterceptor', {
            method: req.method,
            url: req.url,
            isUsingCookies
        });
        return next.handle().pipe((0, operators_1.map)(data => {
            if (!data) {
                this.debugLogger.debug('No data to process', 'TokenResponseInterceptor');
                return data;
            }
            if (isUsingCookies) {
                this.setTokens(res, data, this.resolvePersistent(req));
                return (0, lodash_1.omit)(data, ['accessToken', 'refreshToken', 'trustToken']);
            }
            this.debugLogger.debug('Returning tokens in response body (header mode)', 'TokenResponseInterceptor', {
                hasAccessToken: !!data.accessToken,
                hasRefreshToken: !!data.refreshToken
            });
            return data;
        }));
    }
    resolvePersistent(req) {
        const body = req.body;
        if (body && typeof body.rememberMe === 'boolean') {
            return body.rememberMe;
        }
        return cookie_helper_1.CookieHelper.get(req, auth_constants_1.REMEMBER_COOKIE_NAME) !== '0';
    }
    setTokens(response, tokens, persistent = true) {
        const accessDuration = this.options.session?.accessTokenValidity;
        const refreshDuration = this.options.session?.refreshTokenValidity;
        const accessMaxAge = persistent ? (0, ms_1.default)(accessDuration) : undefined;
        const refreshMaxAge = persistent ? (0, ms_1.default)(refreshDuration) : undefined;
        const multiAccount = this.options.session?.allowMultipleAccounts === true;
        const accountKey = multiAccount
            ? (0, auth_constants_1.userIdFromJwt)(tokens.accessToken || tokens.refreshToken || '')
            : undefined;
        const accessName = accountKey ? (0, auth_constants_1.accountAccessCookieName)(accountKey) : auth_constants_1.ACCESS_TOKEN_COOKIE_NAME;
        const refreshName = accountKey ? (0, auth_constants_1.accountRefreshCookieName)(accountKey) : auth_constants_1.REFRESH_TOKEN_COOKIE_NAME;
        if (tokens.accessToken) {
            this.setCookie(response, accessName, tokens.accessToken, {
                maxAge: accessMaxAge,
            });
        }
        if (tokens.refreshToken) {
            this.setCookie(response, refreshName, tokens.refreshToken, {
                maxAge: refreshMaxAge,
            });
        }
        if (accountKey) {
            this.setCookie(response, auth_constants_1.ACTIVE_ACCOUNT_COOKIE_NAME, accountKey, {
                httpOnly: false,
                maxAge: refreshMaxAge,
            });
        }
        if (tokens.trustToken) {
            const trustCookieName = auth_config_service_1.AuthConfigService.getOptions().mfa?.trustDeviceStorageName || auth_constants_1.NEST_AUTH_TRUST_DEVICE_KEY;
            const duration = auth_config_service_1.AuthConfigService.getOptions().mfa?.trustedDeviceDuration || '30d';
            this.setCookie(response, trustCookieName, tokens.trustToken, {
                maxAge: (0, ms_1.default)(duration),
            });
        }
        if (persistent) {
            cookie_helper_1.CookieHelper.delete(response, auth_constants_1.REMEMBER_COOKIE_NAME, { path: '/' });
        }
        else {
            this.setCookie(response, auth_constants_1.REMEMBER_COOKIE_NAME, '0', { maxAge: undefined });
        }
        this.debugLogger.debug('Setting tokens in cookies', 'TokenResponseInterceptor', {
            hasAccessToken: !!tokens.accessToken,
            hasRefreshToken: !!tokens.refreshToken,
            accessDuration,
            refreshDuration,
        });
    }
    setCookie(response, name, token, options) {
        const cookieOptions = {
            httpOnly: true,
            path: '/',
            secure: this.options.session?.cookieOptions?.secure ?? true,
            ...this.options.session?.cookieOptions?.domain ? { domain: this.options.session?.cookieOptions?.domain } : {},
            sameSite: (this.options.session?.cookieOptions?.sameSite ?? 'lax'),
            maxAge: (0, ms_1.default)(this.options.session?.accessTokenValidity || '7d'),
            ...options,
        };
        this.debugLogger.verbose(`Setting cookie: ${name}`, 'TokenResponseInterceptor', {
            cookieName: name,
            ...cookieOptions
        });
        cookie_helper_1.CookieHelper.set(response, name, token, cookieOptions);
    }
};
exports.TokenResponseInterceptor = TokenResponseInterceptor;
exports.TokenResponseInterceptor = TokenResponseInterceptor = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [debug_logger_service_1.DebugLoggerService])
], TokenResponseInterceptor);
//# sourceMappingURL=token-response.interceptor.js.map