#!/usr/bin/env node

/**
 * Build script for ba-interactive.html
 *
 * Assembles the HTML template from split source files:
 * - src/template.html (shell with PARTIAL placeholders)
 * - src/partials/*.html (section content files)
 * - src/styles/*.css (concatenated in alphabetical order)
 * - src/scripts/*.js (concatenated in alphabetical order)
 *
 * Output: ba-interactive.html (single file, compatible with file:// protocol)
 *
 * Preserves template placeholders: {{FEATURE_DATA}}, {{EMBEDDED_ARTIFACTS}}, {{PROJECT_NAME}}
 * Backward compat: {{APPLICATION_NAME}} and {{APPLICATION_ID}} are also preserved if present
 */

const fs = require('fs');
const path = require('path');

const SRC_DIR = path.join(__dirname, 'src');
const PARTIALS_DIR = path.join(SRC_DIR, 'partials');
const STYLES_DIR = path.join(SRC_DIR, 'styles');
const SCRIPTS_DIR = path.join(SRC_DIR, 'scripts');
const TEMPLATE_FILE = path.join(SRC_DIR, 'template.html');
const OUTPUT_FILE = path.join(__dirname, 'ba-interactive.html');

function readSortedFiles(dir, extension) {
    if (!fs.existsSync(dir)) return [];
    const files = fs.readdirSync(dir)
        .filter(f => f.endsWith(extension))
        .sort();

    return files.map(f => {
        const content = fs.readFileSync(path.join(dir, f), 'utf8');
        return { name: f, content };
    });
}

function resolvePartials(template) {
    const partialRegex = /<!-- PARTIAL:(\S+) -->/g;
    let resolved = template;
    let match;
    const matches = [];

    while ((match = partialRegex.exec(template)) !== null) {
        matches.push({ placeholder: match[0], name: match[1] });
    }

    for (const m of matches) {
        const partialFile = path.join(PARTIALS_DIR, m.name + '.html');
        if (fs.existsSync(partialFile)) {
            const partialContent = fs.readFileSync(partialFile, 'utf8');
            resolved = resolved.replace(m.placeholder, partialContent);
        } else {
            console.warn(`[build-html] WARNING: Partial not found: ${m.name}.html`);
        }
    }

    return resolved;
}

function minifyCss(css) {
    return css
        .replace(/\/\*[\s\S]*?\*\//g, '')   // remove comments
        .replace(/\s*([{}:;,>~+])\s*/g, '$1') // remove whitespace around symbols
        .replace(/\s+/g, ' ')                // collapse whitespace
        .replace(/;\s*}/g, '}')              // remove trailing semicolons
        .trim();
}

function minifyJs(js) {
    // Light minification — remove comments and collapse whitespace (no AST transform)
    return js
        .replace(/\/\*[\s\S]*?\*\//g, '')    // remove block comments
        .replace(/\/\/.*$/gm, '')             // remove line comments
        .replace(/^\s*\n/gm, '')              // remove empty lines
        .replace(/\n\s+/g, '\n')              // reduce leading whitespace
        .trim();
}

function build() {
    const doMinify = process.argv.includes('--minify');
    console.log('[build-html] Starting build...' + (doMinify ? ' (minified)' : ''));

    // Read template
    if (!fs.existsSync(TEMPLATE_FILE)) {
        console.error('[build-html] ERROR: Template not found at', TEMPLATE_FILE);
        process.exit(1);
    }
    let template = fs.readFileSync(TEMPLATE_FILE, 'utf8');

    // Resolve partials
    if (fs.existsSync(PARTIALS_DIR)) {
        const partialFiles = fs.readdirSync(PARTIALS_DIR).filter(f => f.endsWith('.html'));
        console.log(`[build-html] Partials: ${partialFiles.length} files`);
        template = resolvePartials(template);
    }

    // Read and concatenate CSS files
    const cssFiles = readSortedFiles(STYLES_DIR, '.css');
    console.log(`[build-html] CSS files: ${cssFiles.map(f => f.name).join(', ')}`);
    let css = cssFiles.map(f => `/* --- ${f.name} --- */\n${f.content}`).join('\n\n');
    if (doMinify) css = minifyCss(css);

    // Read and concatenate JS files
    const jsFiles = readSortedFiles(SCRIPTS_DIR, '.js');
    console.log(`[build-html] JS files: ${jsFiles.map(f => f.name).join(', ')}`);
    let js = jsFiles.map(f => `/* --- ${f.name} --- */\n${f.content}`).join('\n\n');
    if (doMinify) js = minifyJs(js);

    // Inject into template
    template = template.replace('<!-- CSS_PLACEHOLDER -->', css);
    template = template.replace('<!-- JS_PLACEHOLDER -->', js);

    // Verify placeholders are preserved
    const requiredPlaceholders = ['{{FEATURE_DATA}}', '{{EMBEDDED_ARTIFACTS}}'];
    // Accept either {{PROJECT_NAME}} or {{APPLICATION_NAME}}
    const hasProjectName = template.includes('{{PROJECT_NAME}}') || template.includes('{{APPLICATION_NAME}}');
    const missing = requiredPlaceholders.filter(p => !template.includes(p));
    if (!hasProjectName) missing.push('{{PROJECT_NAME}} or {{APPLICATION_NAME}}');

    if (missing.length > 0) {
        console.error('[build-html] ERROR: Missing placeholders:', missing.join(', '));
        process.exit(1);
    }

    // Write output
    fs.writeFileSync(OUTPUT_FILE, template, 'utf8');

    const sizeKB = Math.round(fs.statSync(OUTPUT_FILE).size / 1024);
    console.log(`[build-html] Output: ${OUTPUT_FILE} (${sizeKB} KB)`);
    console.log(`[build-html] CSS: ${cssFiles.length} files, JS: ${jsFiles.length} files`);
    console.log('[build-html] Build complete.');
}

build();
