/**
 * modules/users/changeCredentials.js — Cambiar contraseña, PIN, patrón, registrar huella.
 */
(function (g) {
    g.modules = g.modules || {};
    g.modules.users = g.modules.users || {};

    var crypto = g.modules.core.crypto;
    var store = g.modules.users.userStore;

    async function rehash(field, plain, user, saltKey, hashKey) {
        var salt = crypto.randomSaltB64();
        var hash = await crypto.hashSecret(String(plain || ''), salt);
        user[saltKey] = salt;
        user[hashKey] = hash;
    }

    g.modules.users.changeCredentials = {
        changePassword: async function (userId, newPassword) {
            var u = await store.findById(userId);
            if (!u) throw new Error('not_found');
            await rehash('pw', newPassword, u, 'passwordSalt', 'passwordHash');
            await store.upsert(u);
            return u;
        },

        changePin: async function (userId, newPin) {
            var u = await store.findById(userId);
            if (!u) throw new Error('not_found');
            await rehash('pin', newPin, u, 'pinSalt', 'pinHash');
            await store.upsert(u);
            return u;
        },

        changePattern: async function (userId, patternSeq) {
            var u = await store.findById(userId);
            if (!u) throw new Error('not_found');
            var salt = crypto.randomSaltB64();
            u.patternSalt = salt;
            u.patternHash = await crypto.hashSecret(String(patternSeq || ''), salt);
            await store.upsert(u);
            return u;
        },

        setRecoveryCode: async function (userId, code) {
            var u = await store.findById(userId);
            if (!u) throw new Error('not_found');
            var salt = crypto.randomSaltB64();
            u.recoverySalt = salt;
            u.recoveryHash = code ? await crypto.hashSecret(String(code), salt) : '';
            await store.upsert(u);
            return u;
        },

        verifyRecoveryCode: async function (userId, code) {
            var u = await store.findById(userId);
            if (!u || !u.recoveryHash) return false;
            var h = await crypto.hashSecret(String(code || ''), u.recoverySalt);
            return crypto.timingSafeEqualB64(h, u.recoveryHash);
        },

        addWebAuthnCredential: async function (userId, cred) {
            var u = await store.findById(userId);
            if (!u) throw new Error('not_found');
            u.webauthnCredentials = u.webauthnCredentials || [];
            var id = cred.credentialIdB64 || cred.id;
            u.webauthnCredentials = u.webauthnCredentials.filter(function (c) {
                return (c.credentialIdB64 || c.id) !== id;
            });
            u.webauthnCredentials.push({
                credentialIdB64: cred.credentialIdB64 || '',
                rawIdB64: cred.rawIdB64 || '',
                transports: cred.transports || [],
            });
            await store.upsert(u);
            return u;
        },

        removeWebAuthnCredentials: async function (userId) {
            var u = await store.findById(userId);
            if (!u) throw new Error('not_found');
            u.webauthnCredentials = [];
            await store.upsert(u);
            return u;
        },
    };
})(typeof window !== 'undefined' ? window : this);
