const fs = require('fs');
const https = require('https');
const { URL } = require('url');
const db = require('./db');
const CREDS = JSON.parse(fs.readFileSync('C:/ProgramData/dataforth-uploader/credentials.json', 'utf8'));

function req(method, uri, headers) {
    return new Promise((res, rej) => {
        const u = new URL(uri);
        const r = https.request({
            hostname: u.hostname, port: u.port || 443, path: u.pathname + u.search,
            method, headers, timeout: 20000,
        }, rs => {
            let d = '';
            rs.on('data', c => d += c);
            rs.on('end', () => res({ status: rs.statusCode, body: d }));
        });
        const t = setTimeout(() => { r.destroy(); rej(new Error('timeout')); }, 20000);
        r.on('error', rej);
        r.on('close', () => clearTimeout(t));
        r.end();
    });
}

(async () => {
    const form = 'grant_type=client_credentials&client_id=' + encodeURIComponent(CREDS.CF_CLIENT_ID) +
        '&client_secret=' + encodeURIComponent(CREDS.CF_CLIENT_SECRET) + '&scope=' + encodeURIComponent(CREDS.CF_SCOPE);
    const tokR = await new Promise((r, j) => {
        const u = new URL(CREDS.CF_TOKEN_URL);
        const rq = https.request({
            hostname: u.hostname, port: 443, path: u.pathname, method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(form) },
        }, rs => {
            let d = '';
            rs.on('data', c => d += c);
            rs.on('end', () => r({ status: rs.statusCode, body: d }));
        });
        rq.on('error', j);
        rq.write(form);
        rq.end();
    });
    const token = JSON.parse(tokR.body).access_token;

    async function sample(label, sql, expect) {
        console.log('=== ' + label + ' ===');
        const rows = await db.query(sql);
        let hit = 0, miss = 0, err = 0;
        for (const r of rows) {
            try {
                const rr = await req('GET',
                    CREDS.CF_API_BASE + '/api/v1/TestReportDataFiles/' + encodeURIComponent(r.serial_number),
                    { 'Authorization': 'Bearer ' + token });
                if (rr.status === 200) hit++;
                else if (rr.status === 404) miss++;
                else { err++; console.log('  HTTP ' + rr.status + ' ' + r.serial_number); }
            } catch (e) { err++; console.log('  ERR ' + r.serial_number + ' ' + e.message); }
        }
        console.log('  hit=' + hit + ' miss=' + miss + ' err=' + err + '  (' + expect + ')');
        return { hit, miss, err };
    }

    await sample(
        'Sample 1: 100 random stamped api_uploaded_at IS NOT NULL',
        "SELECT serial_number FROM test_records WHERE api_uploaded_at IS NOT NULL ORDER BY random() LIMIT 100",
        'expect hit=100',
    );
    await sample(
        'Sample 2: 100 random unpushable PASS (NULL api_uploaded_at, PASS)',
        "SELECT serial_number FROM test_records WHERE api_uploaded_at IS NULL AND overall_result='PASS' ORDER BY random() LIMIT 100",
        'expect mostly miss (these are the 10K unpushables)',
    );
    await sample(
        'Sample 3: 50 random FAIL',
        "SELECT serial_number FROM test_records WHERE overall_result='FAIL' ORDER BY random() LIMIT 50",
        'expect miss=50 (FAILs never reach Hoffman)',
    );

    await db.close();
})().catch(e => { console.error('FATAL', e.message); process.exit(1); });
