"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const crypto_1 = __importDefault(require("crypto"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
// @group Configuration : Path to the stored auth config file
const AUTH_FILE = path_1.default.join(__dirname, '../config/auth.json');
// @group Utilities : Load auth config — returns null when no password is set
function loadAuthConfig() {
    try {
        if (!fs_1.default.existsSync(AUTH_FILE))
            return null;
        const raw = fs_1.default.readFileSync(AUTH_FILE, 'utf8').trim();
        if (!raw)
            return null;
        return JSON.parse(raw);
    }
    catch {
        return null;
    }
}
// @group Utilities : Persist auth config to disk
function saveAuthConfig(config) {
    const dir = path_1.default.dirname(AUTH_FILE);
    if (!fs_1.default.existsSync(dir))
        fs_1.default.mkdirSync(dir, { recursive: true });
    fs_1.default.writeFileSync(AUTH_FILE, JSON.stringify(config), 'utf8');
}
// @group Utilities : Hash a plaintext password with PBKDF2 + salt
function hashPassword(password, salt) {
    return crypto_1.default.pbkdf2Sync(password, salt, 100000, 64, 'sha512').toString('hex');
}
// @group Router : Express router for password-protection endpoints
const router = express_1.default.Router();
// @group Endpoints : GET /api/auth/status — is a password/PIN configured?
router.get('/status', (_req, res) => {
    var _a;
    const config = loadAuthConfig();
    res.json({
        passwordSet: config !== null,
        pinSet: !!(config === null || config === void 0 ? void 0 : config.pinHash),
        autoLockMinutes: (_a = config === null || config === void 0 ? void 0 : config.autoLockMinutes) !== null && _a !== void 0 ? _a : 0,
    });
});
// @group Endpoints : PATCH /api/auth/settings — update non-password settings (e.g. autoLockMinutes)
router.patch('/settings', (req, res) => {
    var _a;
    const { autoLockMinutes } = req.body;
    const config = loadAuthConfig();
    if (!config) {
        return res.status(400).json({ success: false, error: 'No password set — configure a password first' });
    }
    const minutes = typeof autoLockMinutes === 'number' && autoLockMinutes >= 0 ? Math.floor(autoLockMinutes) : (_a = config.autoLockMinutes) !== null && _a !== void 0 ? _a : 0;
    saveAuthConfig({ ...config, autoLockMinutes: minutes });
    res.json({ success: true, autoLockMinutes: minutes });
});
// @group Endpoints : POST /api/auth/set — set or change the password
router.post('/set', (req, res) => {
    var _a;
    const { password, currentPassword } = req.body;
    if (!password || typeof password !== 'string' || password.length < 4) {
        return res.status(400).json({ success: false, error: 'Password must be at least 4 characters' });
    }
    const existing = loadAuthConfig();
    // If a password is already set, require the current one before changing
    if (existing) {
        if (!currentPassword) {
            return res.status(401).json({ success: false, error: 'Current password required to change password' });
        }
        const currentHash = hashPassword(currentPassword, existing.salt);
        if (!crypto_1.default.timingSafeEqual(Buffer.from(currentHash, 'hex'), Buffer.from(existing.hash, 'hex'))) {
            return res.status(401).json({ success: false, error: 'Current password is incorrect' });
        }
    }
    const salt = crypto_1.default.randomBytes(32).toString('hex');
    const hash = hashPassword(password, salt);
    // Preserve PIN and autoLock settings when changing password
    saveAuthConfig({
        hash,
        salt,
        autoLockMinutes: (_a = existing === null || existing === void 0 ? void 0 : existing.autoLockMinutes) !== null && _a !== void 0 ? _a : 0,
        ...((existing === null || existing === void 0 ? void 0 : existing.pinHash) ? { pinHash: existing.pinHash, pinSalt: existing.pinSalt } : {}),
    });
    res.json({ success: true });
});
// @group Endpoints : POST /api/auth/verify — verify a password attempt
router.post('/verify', (req, res) => {
    const { password } = req.body;
    if (!password || typeof password !== 'string') {
        return res.status(400).json({ success: false, error: 'Password is required' });
    }
    const config = loadAuthConfig();
    if (!config) {
        // No password set — treat as unlocked
        return res.json({ success: true, token: crypto_1.default.randomBytes(32).toString('hex') });
    }
    const hash = hashPassword(password, config.salt);
    const match = crypto_1.default.timingSafeEqual(Buffer.from(hash, 'hex'), Buffer.from(config.hash, 'hex'));
    if (!match) {
        return res.status(401).json({ success: false, error: 'Incorrect password' });
    }
    res.json({ success: true, token: crypto_1.default.randomBytes(32).toString('hex') });
});
// @group Endpoints : DELETE /api/auth/remove — remove the password (requires current password)
router.delete('/remove', (req, res) => {
    const { password } = req.body;
    const config = loadAuthConfig();
    if (!config) {
        return res.json({ success: true }); // nothing to remove
    }
    if (!password || typeof password !== 'string') {
        return res.status(400).json({ success: false, error: 'Current password required' });
    }
    const hash = hashPassword(password, config.salt);
    const match = crypto_1.default.timingSafeEqual(Buffer.from(hash, 'hex'), Buffer.from(config.hash, 'hex'));
    if (!match) {
        return res.status(401).json({ success: false, error: 'Incorrect password' });
    }
    fs_1.default.unlinkSync(AUTH_FILE);
    res.json({ success: true });
});
// @group Endpoints : POST /api/auth/pin/set — set or change the PIN (4-digit)
router.post('/pin/set', (req, res) => {
    const { pin } = req.body;
    if (!pin || !/^\d{4}$/.test(pin)) {
        return res.status(400).json({ success: false, error: 'PIN must be exactly 4 digits' });
    }
    const config = loadAuthConfig();
    if (!config) {
        return res.status(400).json({ success: false, error: 'Set a password first before adding a PIN' });
    }
    const pinSalt = crypto_1.default.randomBytes(32).toString('hex');
    const pinHash = hashPassword(pin, pinSalt);
    saveAuthConfig({ ...config, pinHash, pinSalt });
    res.json({ success: true });
});
// @group Endpoints : POST /api/auth/pin/verify — verify a PIN attempt
router.post('/pin/verify', (req, res) => {
    const { pin } = req.body;
    if (!pin || typeof pin !== 'string') {
        return res.status(400).json({ success: false, error: 'PIN is required' });
    }
    const config = loadAuthConfig();
    if (!(config === null || config === void 0 ? void 0 : config.pinHash) || !(config === null || config === void 0 ? void 0 : config.pinSalt)) {
        return res.status(400).json({ success: false, error: 'No PIN configured' });
    }
    const hash = hashPassword(pin, config.pinSalt);
    const match = crypto_1.default.timingSafeEqual(Buffer.from(hash, 'hex'), Buffer.from(config.pinHash, 'hex'));
    if (!match) {
        return res.status(401).json({ success: false, error: 'Incorrect PIN' });
    }
    res.json({ success: true, token: crypto_1.default.randomBytes(32).toString('hex') });
});
// @group Endpoints : DELETE /api/auth/pin/remove — remove PIN (requires current password)
router.delete('/pin/remove', (req, res) => {
    const { password } = req.body;
    const config = loadAuthConfig();
    if (!config) {
        return res.json({ success: true }); // nothing to remove
    }
    if (!password || typeof password !== 'string') {
        return res.status(400).json({ success: false, error: 'Current password required to remove PIN' });
    }
    const hash = hashPassword(password, config.salt);
    const match = crypto_1.default.timingSafeEqual(Buffer.from(hash, 'hex'), Buffer.from(config.hash, 'hex'));
    if (!match) {
        return res.status(401).json({ success: false, error: 'Incorrect password' });
    }
    const { pinHash: _ph, pinSalt: _ps, ...rest } = config;
    saveAuthConfig(rest);
    res.json({ success: true });
});
exports.default = router;
