const noCookiesFileName = '/var/lib/njs/cookies.txt';
const blockedHoursMS = 1 * 1000 * 60 * 60;
const noCookieIPs = loadFile(noCookiesFileName);

function updateFile(file: string, dataArray: string[]): void {
    try {
        fs.writeFileSync(file, dataArray.join('\n'));
    } catch (e) {
        // unable to write file
    }
}

function verifyJSCookie(r: NginxHTTPRequest): boolean {
    const cookies = r.headersIn.Cookie;
    const njsCookie =
        cookies &&
        cookies
            .split(';')
            .map((v) => v.split('='))
            .find((x) => x[0] === 'njs');

    try {
        if (!njsCookie || njsCookie.length < 2) {
            // no njs cookie or wrong cookie array length
            const foundIP = noCookieIPs.find((ip: string) => ip.match(r.remoteAddress));
            if (foundIP && Date.now() - parseInt(foundIP.split(':')[1]) <= blockedHoursMS) {
                return false;
            } else {
                const ipIndex = noCookieIPs.findIndex((item: string) => item === foundIP);
                if (ipIndex) {
                    noCookieIPs.splice(ipIndex, 1);
                    updateFile(noCookiesFileName, noCookieIPs);
                }
                return true;
            }
        }
        // njs cookie found, validate it
        const cookieValue = njsCookie && njsCookie[1];
        if (cookieValue) {
            const [cookieTimestamp, cookiePayload] = cookieValue.split(':');
            const requestSignature = `${r.headersIn['User-Agent']}${r.remoteAddress}${cookieTimestamp}`;
            const requestSignatureHmac = crypto.createHmac('sha256', topSecretKey);
            const requestSignatureHex = requestSignatureHmac.update(requestSignature).digest('hex');
            return requestSignatureHex === cookiePayload;
        }

        return false; // if all fails - block the request
    } catch (e) {
        // something went wrong - fail open
        return true;
    }
}