"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 AuthConfigService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthConfigService = void 0;
const common_1 = require("@nestjs/common");
const session_options_interface_1 = require("../interfaces/session-options.interface");
const nest_auth_contracts_1 = require("@ackplus/nest-auth-contracts");
const auth_constants_1 = require("../../auth.constants");
const otp_1 = require("../../utils/otp");
let AuthConfigService = class AuthConfigService {
    static { AuthConfigService_1 = this; }
    static defaultOptions = {
        isGlobal: true,
        appName: 'Nest Auth',
        session: {
            accessTokenType: null,
            storageType: session_options_interface_1.SessionStorageType.DATABASE,
            accessTokenValidity: '1h',
            refreshTokenValidity: '30d',
            slidingExpiration: false,
            jwt: {
                secret: 'secret',
            },
            cookieOptions: {
                httpOnly: true,
                secure: false,
            },
        },
        emailAuth: {
            enabled: true,
        },
        phoneAuth: {
            enabled: false,
        },
        mfa: {
            enabled: false,
            methods: [nest_auth_contracts_1.NestAuthMFAMethodEnum.EMAIL, nest_auth_contracts_1.NestAuthMFAMethodEnum.TOTP],
            allowUserToggle: true,
            allowMethodSelection: true,
            required: false,
            trustDeviceStorageName: auth_constants_1.NEST_AUTH_TRUST_DEVICE_KEY,
            trustedDeviceDuration: '7d',
        },
        tenant: {
            enabled: false,
            mode: nest_auth_contracts_1.TenantModeEnum.ISOLATED,
        },
        roleGuards: [auth_constants_1.DEFAULT_GUARD_NAME],
        adminConsole: {
            enabled: true,
            basePath: '/api/auth/admin',
            sessionCookieName: 'nest_auth_admin',
            sessionDuration: '2h',
            allowAdminManagement: true,
            cookie: {
                httpOnly: true,
                secure: false,
                sameSite: 'lax',
            },
        },
        debug: {
            enabled: false,
            level: 'verbose',
            prefix: '[NestAuth]',
            includeTimestamp: true,
            includeContext: true
        },
        otp: {
            codeExpiresIn: '30m',
            length: 6,
            format: 'numeric',
            generate: otp_1.generateOtp,
        },
        passwordless: {
            enabled: false,
            allowSignUp: false,
        },
        password: {
            passwordResetTokenExpiresIn: '1h',
        },
        platformAccess: {
            enabled: false,
            validate: (request) => {
                return true;
            },
        },
    };
    static options;
    static instance;
    constructor() {
        if (!AuthConfigService_1.instance) {
            AuthConfigService_1.instance = this;
        }
    }
    static getOptions() {
        return this.options || this.defaultOptions;
    }
    static getDefaultOptions() {
        return this.defaultOptions;
    }
    static getInstance() {
        if (!AuthConfigService_1.instance) {
            AuthConfigService_1.instance = new AuthConfigService_1();
        }
        return AuthConfigService_1.instance;
    }
    static setOptions(options) {
        const deepmerge = require('deepmerge');
        const mergedOptions = deepmerge(this.defaultOptions, options, { clone: false });
        if (mergedOptions.mfa?.methods) {
            mergedOptions.mfa.methods = [...new Set(mergedOptions.mfa.methods)];
        }
        if (!mergedOptions.roleGuards || mergedOptions.roleGuards.length === 0) {
            mergedOptions.roleGuards = [auth_constants_1.DEFAULT_GUARD_NAME];
        }
        else {
            mergedOptions.roleGuards = [...new Set(mergedOptions.roleGuards)];
        }
        if (!mergedOptions.adminConsole) {
            mergedOptions.adminConsole = {};
        }
        if (!mergedOptions.adminConsole.secretKey) {
            console.warn('Admin console secret key not configured. Please configure adminConsole.secretKey in AuthModuleOptions to enable admin console.');
            mergedOptions.adminConsole.enabled = false;
        }
        this.options = mergedOptions;
        this.validateSessionOptions(this.options);
        this.validateAdminConsoleOptions(this.options);
    }
    static validateAdminConsoleOptions(options) {
        if (options.adminConsole?.enabled !== false && options.adminConsole?.secretKey) {
            const secretKey = options.adminConsole.secretKey;
            const weakSecrets = ['change-me-admin-secret', 'default', 'secret', ''];
            if (weakSecrets.includes(secretKey)) {
                throw new Error('Admin console requires a secure secretKey. ' +
                    'Please set adminConsole.secretKey in your AuthModuleOptions (e.g., secretKey: process.env.ADMIN_CONSOLE_SESSION_SECRET) ' +
                    'with a 32+ byte random value. Store it securely in environment variables or a secrets manager. ' +
                    'Weak or default values are not allowed for security reasons. Rotate keys regularly.');
            }
        }
    }
    static validateSessionOptions(options) {
        const store = options.session?.storageType;
        if (store) {
            const normalized = String(store).toLowerCase();
            const allowedStores = Object.values(session_options_interface_1.SessionStorageType);
            if (!allowedStores.includes(normalized)) {
                throw new Error(`Invalid session store "${store}". ` +
                    `Allowed values: ${allowedStores.join(', ')}`);
            }
        }
        const ttlSeconds = options.session?.redis?.ttlSeconds;
        if (ttlSeconds !== undefined) {
            if (!Number.isFinite(ttlSeconds) || ttlSeconds <= 0) {
                throw new Error('session.redis.ttlSeconds must be a positive number of seconds.');
            }
        }
    }
    getConfig() {
        return AuthConfigService_1.getOptions();
    }
    setConfig(options) {
        AuthConfigService_1.setOptions(options);
    }
    getRoleGuards() {
        const opts = AuthConfigService_1.getOptions();
        const allowed = opts.roleGuards;
        const list = (allowed && allowed.length > 0) ? allowed : [auth_constants_1.DEFAULT_GUARD_NAME];
        return [...new Set(list)];
    }
    isRoleGuardAllowed(guard) {
        return this.getRoleGuards().includes(guard);
    }
};
exports.AuthConfigService = AuthConfigService;
exports.AuthConfigService = AuthConfigService = AuthConfigService_1 = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [])
], AuthConfigService);
//# sourceMappingURL=auth-config.service.js.map