/**
 * DFWDS-equivalent in Node — moves test datasheets from staging to For_Web,
 * decodes any DOS A-J prefix on filenames, quarantines invalid files.
 *
 * Mirrors the validation logic from the original VB6 DFWDS.bas:
 *   - filename must be .txt
 *   - must contain a dash
 *   - work-order portion (left of dash) must be all-numeric and not start with 0
 *   - OR the first char is A-J (DOS-encoded), which decodes to 10-19 and renames
 *
 * Defaults match the original DFWDS_NAMES.txt:
 *   --in    \\ad2\webshare\Test_Datasheets
 *   --bad   \\ad2\webshare\Bad_Datasheets
 *   --out   \\ad2\webshare\For_Web
 *   --log   \\ad2\webshare\Datasheets_Log
 *
 * Use --dry-run to see what would happen without moving anything.
 */
const fs = require('fs');
const path = require('path');

const args = process.argv.slice(2);
const arg = (n, d) => { const i = args.indexOf(n); return i >= 0 ? args[i+1] : d; };
const flag = (n) => args.includes(n);

const IN_DIR  = arg('--in',  String.raw`C:\Shares\webshare\Test_Datasheets`);
const BAD_DIR = arg('--bad', String.raw`C:\Shares\webshare\Bad_Datasheets`);
const OUT_DIR = arg('--out', String.raw`C:\Shares\webshare\For_Web`);
const LOG_DIR = arg('--log', String.raw`C:\Shares\webshare\Datasheets_Log`);
const DRY = flag('--dry-run');
const LIMIT = parseInt(arg('--limit', '0'), 10);

// Per VB funcDecodeWOchar: A-J map to 10..19 (one char -> two digits)
const PREFIX_DECODE = {
    A: '10', B: '11', C: '12', D: '13', E: '14',
    F: '15', G: '16', H: '17', I: '18', J: '19',
};

function classify(filename) {
    // Returns: {action: 'valid'|'rename'|'bad', newName?: string, reason?: string}
    if (!filename.toLowerCase().endsWith('.txt')) {
        return {action:'bad', reason:'not .txt'};
    }
    const stem = filename.slice(0, -4);  // strip .txt
    const dash = stem.indexOf('-');
    if (dash <= 0) return {action:'bad', reason:'no dash or dash at start'};

    const wo = stem.slice(0, dash).toUpperCase();
    const tail = stem.slice(dash); // includes leading '-'

    if (/^\d+$/.test(wo)) {
        if (wo.startsWith('0')) return {action:'bad', reason:'WO starts with 0'};
        return {action:'valid'};
    }

    // Check DOS-encoded: first char A-J, rest all numeric
    const first = wo[0];
    if (PREFIX_DECODE[first] && /^\d+$/.test(wo.slice(1))) {
        const newWo = PREFIX_DECODE[first] + wo.slice(1);
        return {action:'rename', newName: newWo + tail + '.txt'};
    }

    return {action:'bad', reason:`WO "${wo}" not numeric and not A-J prefixed`};
}

function ensureDir(d) { fs.mkdirSync(d, {recursive: true}); }

function moveFile(src, dst) {
    ensureDir(path.dirname(dst));
    if (fs.existsSync(dst)) {
        // overwrite by removing first; rename in same dir is fine but cross-dir on Win sometimes errors if exists
        fs.unlinkSync(dst);
    }
    fs.renameSync(src, dst);
}

function main() {
    if (!fs.existsSync(IN_DIR)) {
        console.error(`[FAIL] input dir not found: ${IN_DIR}`);
        process.exit(1);
    }
    ensureDir(BAD_DIR); ensureDir(OUT_DIR); ensureDir(LOG_DIR);

    // Log filename matches DFWDS pattern: DFWDS_YYYY_MM_DD.log
    const now = new Date();
    const ymd = `${now.getFullYear()}_${String(now.getMonth()+1).padStart(2,'0')}_${String(now.getDate()).padStart(2,'0')}`;
    const logPath = path.join(LOG_DIR, `DFWDS_${ymd}.log`);
    const logFh = fs.openSync(logPath, 'a');
    function log(msg) {
        const line = `[${new Date().toISOString()}] ${msg}\n`;
        process.stdout.write(line);
        fs.writeSync(logFh, line);
    }

    log(`=== DFWDS-process start (Node port) ===`);
    log(`  in:  ${IN_DIR}`);
    log(`  out: ${OUT_DIR}`);
    log(`  bad: ${BAD_DIR}`);
    log(`  dry: ${DRY}, limit: ${LIMIT||'all'}`);

    const all = fs.readdirSync(IN_DIR).filter(n => fs.statSync(path.join(IN_DIR, n)).isFile());
    const queue = LIMIT ? all.slice(0, LIMIT) : all;
    log(`  queued: ${queue.length} files (of ${all.length} in dir)`);

    const stats = {valid:0, renamed:0, bad:0, errors:0};
    for (const name of queue) {
        const src = path.join(IN_DIR, name);
        const cls = classify(name);
        try {
            if (cls.action === 'valid') {
                const dst = path.join(OUT_DIR, name);
                if (DRY) log(`  [DRY VALID] ${name} -> ${dst}`);
                else { moveFile(src, dst); log(`  VALID ${name}`); }
                stats.valid++;
            } else if (cls.action === 'rename') {
                const dst = path.join(OUT_DIR, cls.newName);
                if (DRY) log(`  [DRY RENAME] ${name} -> ${cls.newName} -> ${dst}`);
                else { moveFile(src, dst); log(`  RENAMED ${name} -> ${cls.newName}`); }
                stats.renamed++;
            } else {
                const dst = path.join(BAD_DIR, name);
                if (DRY) log(`  [DRY BAD] ${name} (${cls.reason}) -> ${dst}`);
                else { moveFile(src, dst); log(`  BAD ${name} (${cls.reason})`); }
                stats.bad++;
            }
        } catch (e) {
            log(`  ERR ${name}: ${e.message}`);
            stats.errors++;
        }
    }
    log(`=== summary: valid=${stats.valid} renamed=${stats.renamed} bad=${stats.bad} errors=${stats.errors}`);
    fs.closeSync(logFh);
    console.log(`\n[INFO] log: ${logPath}`);
}

main();
