const crypto = require("node:crypto");
const { tokenSecret } = require("./config.cjs");

function nowIso() {
    return new Date().toISOString();
}

function addYears(date, years) {
    const next = new Date(date);
    next.setFullYear(next.getFullYear() + years);
    return next;
}

function addHours(date, hours) {
    return new Date(date.getTime() + Number(hours || 0) * 3600000);
}

function sign(value) {
    return crypto.createHmac("sha256", tokenSecret).update(value).digest("base64url");
}

function createToken(userId) {
    const payload = Buffer.from(JSON.stringify({ userId, issuedAt: Date.now() })).toString("base64url");
    return `${payload}.${sign(payload)}`;
}

function verifyToken(token) {
    if (!token || typeof token !== "string" || !token.includes(".")) return null;
    const [payload, signature] = token.split(".");
    if (!payload || !signature || sign(payload) !== signature) return null;

    try {
        return JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
    } catch {
        return null;
    }
}

function passwordHash(password, salt = crypto.randomBytes(16).toString("hex")) {
    const hash = crypto.pbkdf2Sync(String(password), salt, 120000, 32, "sha256").toString("hex");
    return `${salt}:${hash}`;
}

function checkPassword(password, stored) {
    const [salt] = String(stored || "").split(":");
    if (!salt) return false;
    return passwordHash(password, salt) === stored;
}

function daysRemaining(expiresAt) {
    return Math.max(0, Math.ceil((new Date(expiresAt).getTime() - Date.now()) / 86400000));
}

module.exports = {
    nowIso,
    addYears,
    addHours,
    createToken,
    verifyToken,
    passwordHash,
    checkPassword,
    daysRemaining,
};
