const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');

// --- Configuration ---
// Try multiple possible locations for Pezkuwi-SDK (local dev vs CI)
const possibleSdkPaths = [
    path.join(__dirname, '..', '..', 'Pezkuwi-SDK'),  // Local: /home/user/Pezkuwi-SDK
    path.join(__dirname, '..', 'Pezkuwi-SDK'),        // CI: /home/runner/work/pwap/pwap/Pezkuwi-SDK
];
const pezkuwiSdkRoot = possibleSdkPaths.find(p => fs.existsSync(p)) || possibleSdkPaths[0];
const sdkDocsSourcePath = path.join(pezkuwiSdkRoot, 'docs', 'sdk');
const mainDocsSourcePath = path.join(pezkuwiSdkRoot, 'docs'); // This is where whitepaper.md etc. are
const publicPath = path.join(__dirname, 'public');
const publicDocsPath = path.join(publicPath, 'docs'); // Where markdown/rs files will be copied
const rustdocDestPath = path.join(publicPath, 'sdk_docs'); // Destination for BUILT rustdocs (e.g., public/sdk_docs/pezkuwi_sdk_docs/index.html)
const structureOutputPath = path.join(publicPath, 'docs-structure.json');
const rustdocBuildOutputPath = path.join(pezkuwiSdkRoot, 'target', 'doc'); // Output of cargo doc

// Path to rustup (used to build rustdoc). Resolve dynamically instead of
// hardcoding a per-machine absolute path: prefer $RUSTUP_PATH, then whatever
// is on PATH, then the conventional ~/.cargo/bin/rustup, then bare 'rustup'.
function resolveRustupPath() {
    if (process.env.RUSTUP_PATH) return process.env.RUSTUP_PATH;
    try {
        const which = spawnSync('bash', ['-lc', 'command -v rustup'], { encoding: 'utf8' });
        if (which.status === 0 && which.stdout && which.stdout.trim()) {
            return which.stdout.trim();
        }
    } catch { /* fall through */ }
    const home = process.env.HOME || require('os').homedir();
    const cargoRustup = path.join(home, '.cargo', 'bin', 'rustup');
    if (fs.existsSync(cargoRustup)) return cargoRustup;
    return 'rustup';
}
const rustupPath = resolveRustupPath();

// Path to the rebranding script (now .cjs)
const rebrandScriptPath = path.join(__dirname, 'rebrand-rustdoc.cjs');


// --- Helper Functions ---

function runCommand(command, args, cwd) {
    console.log(`\n> Running command: ${command} ${args.join(' ')} in ${cwd}`);
    const result = spawnSync(command, args, { stdio: 'inherit', cwd });
    if (result.error) {
        console.error(`Error executing command: ${command}`);
        throw result.error;
    }
    if (result.status !== 0) {
        throw new Error(`Command "${command} ${args.join(' ')}" failed with exit code ${result.status}`);
    }
}

function copyRecursive(src, dest) {
    console.log(`↪️ Copying from ${src} to ${dest}...`);
    fs.mkdirSync(dest, { recursive: true });
    fs.cpSync(src, dest, { recursive: true });
}

function removeDir(dir) {
    console.log(`🧹 Clearing directory: ${dir}...`);
    if (fs.existsSync(dir)) {
        fs.rmSync(dir, { recursive: true, force: true });
    }
}

// Files that should be explicitly grouped under "General Docs"
const generalCategoryFileNames = [
    'AUDIT.md',
    'BACKPORT.md',
    'RELEASE.md',
    'runtimes-pallets.md',
    'workflow_rebranding.md'
];

function generateRecursiveStructure(currentDir) {
    const currentStructure = {};
    const items = fs.readdirSync(currentDir);

    items.sort((a, b) => {
        try {
            const aIsDir = fs.statSync(path.join(currentDir, a)).isDirectory();
            const bIsDir = fs.statSync(path.join(currentDir, b)).isDirectory();
            if (aIsDir && !bIsDir) return -1; // Directories first
            if (!aIsDir && bIsDir) return 1;
            return a.localeCompare(b); // Then alphabetical
        } catch (e) {
            return 0;
        }
    });

    for (const item of items) {
        const ignoreList = ['images', 'sdk', 'target', 'Cargo.toml', 'build.rs'];
        if (ignoreList.includes(item) || item.startsWith('.') || item === 'Cargo.lock') {
            continue;
        }

        const fullPath = path.join(currentDir, item);
        const stat = fs.statSync(fullPath);
        let title = item.replace(/\.(md|rs)$/, '');
        title = title.replace(/_/g, ' ').replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
        
        const relativePath = path.relative(mainDocsSourcePath, fullPath).replace(/\\/g, '/');

        if (stat.isDirectory()) {
            const subStructure = generateRecursiveStructure(fullPath);
            if (Object.keys(subStructure).length > 0) {
                currentStructure[title] = subStructure;
            }
        } else if (item.endsWith('.md') || item.endsWith('.rs')) {
            currentStructure[title] = relativePath;
        }
    }
    return currentStructure;
}


// --- Main Execution ---

function main() {
    try {
        console.log('--- Documentation Automation ---');
        console.log(`Pezkuwi-SDK Root: ${pezkuwiSdkRoot}`);
        console.log(`SDK Docs Source: ${sdkDocsSourcePath}`);
        console.log(`Main Docs Source: ${mainDocsSourcePath}`);

        // 1. Build the Rust SDK documentation (if tools available)
        console.log('\n--- Step 1: Building SDK Documentation (Attempting) ---');
        let rustdocBuiltSuccessfully = false;
        try {
            runCommand(rustupPath, ['run', 'stable', 'cargo', 'doc', '--no-deps'], sdkDocsSourcePath);
            console.log('✅ SDK documentation built successfully.');
            rustdocBuiltSuccessfully = true;
        } catch (e) {
            console.warn(`⚠️ Warning: Could not build SDK documentation. Error: ${e.message}`);
            console.warn('           This might be due to missing Rust toolchain or environment issues. Proceeding without building rustdoc.');
        }

        // 2. Perform Rebranding on the Built Rustdoc (if built)
        if (rustdocBuiltSuccessfully && fs.existsSync(rustdocBuildOutputPath)) {
            console.log('\n--- Step 2: Rebranding Built SDK Documentation ---');
            runCommand('node', [rebrandScriptPath, rustdocBuildOutputPath], __dirname); // Run rebranding script
            console.log('✅ Built SDK docs rebranded successfully.');
        }


        // 3. Clean up old public documentation artifacts
        console.log('\n--- Step 3: Cleaning Public Directories ---');
        removeDir(publicDocsPath);
        removeDir(rustdocDestPath);
        
        // 4. Copy main Markdown/RS files from Pezkuwi-SDK/docs to public/docs
        console.log('\n--- Step 4: Copying Main Documentation Files ---');
        if (fs.existsSync(mainDocsSourcePath)) {
            copyRecursive(mainDocsSourcePath, publicDocsPath);
            console.log('✅ Main documentation files copied successfully.');
        } else {
            console.warn(`⚠️ Warning: SDK docs source not found at ${mainDocsSourcePath}. Skipping docs copy.`);
            console.warn('           This is expected in CI environments without Pezkuwi-SDK.');
            // Create empty docs directory to prevent build errors
            fs.mkdirSync(publicDocsPath, { recursive: true });
        }

        // 5. Copy the BUILT and Rebranded Rustdoc site (if built successfully)
        if (rustdocBuiltSuccessfully && fs.existsSync(rustdocBuildOutputPath)) {
            console.log('\n--- Step 5: Copying Built and Rebranded SDK Documentation ---');
            copyRecursive(rustdocBuildOutputPath, rustdocDestPath);
            console.log('✅ Built and rebranded SDK docs copied successfully.');
        } else {
            console.warn('\n⚠️ Warning: Rustdoc build output not found or build failed. Skipping copy of built SDK docs.');
        }


        // 6. Generate the final navigation structure
        console.log('\n--- Step 6: Generating Navigation Structure ---');
        const rawStructure = fs.existsSync(mainDocsSourcePath) ? generateRecursiveStructure(mainDocsSourcePath) : {};
        
        const finalStructure = {};
        const generalDocs = {};

        // Add "Getting Started" as the first category
        finalStructure['Getting Started'] = {
            'Introduction': 'introduction.md',
            'Whitepaper': 'whitepaper/whitepaper.md'
        };

        // Items to skip (already handled in Getting Started or SDK Reference)
        const skipItems = ['Introduction', 'Whitepaper', 'Mermaid'];

        // Iterate through the raw structure to categorize
        for (const key in rawStructure) {
            // Skip items already handled
            if (skipItems.includes(key)) {
                continue;
            }
            // Check if the item is a string (a file) and if its base name is in the generalCategoryFileNames list
            if (typeof rawStructure[key] === 'string' && generalCategoryFileNames.includes(path.basename(rawStructure[key]))) {
                generalDocs[key] = rawStructure[key];
            } else {
                finalStructure[key] = rawStructure[key]; // Keep as is (folder or other direct file)
            }
        }

        // Add SDK Reference section (always visible)
        finalStructure['SDK Reference'] = {
            '📚 Rust SDK Docs': 'sdk://open',
            'Runtimes & Pallets': 'runtimes-pallets.md'
        };

        // Remove items that are moved to other categories
        if (generalDocs['Genesis Engineering Plan']) {
            delete generalDocs['Genesis Engineering Plan'];
        }
        if (generalDocs['Runtimes Pallets']) {
            delete generalDocs['Runtimes Pallets'];
        }

        // Add "General Docs" as a top-level category
        if (Object.keys(generalDocs).length > 0) {
            finalStructure['General Docs'] = generalDocs;
        }
        
        // Sort the top-level keys for consistent sidebar order
        const sortedKeys = Object.keys(finalStructure).sort((a, b) => {
            // Priority order: Getting Started, SDK Reference, General Docs, Contributor, Whitepaper, then alphabetical for others
            const order = ['Getting Started', 'SDK Reference', 'General Docs', 'Contributor', 'Whitepaper'];
            const indexA = order.indexOf(a);
            const indexB = order.indexOf(b);

            if (indexA === -1 && indexB === -1) { // Both not in priority list
                return a.localeCompare(b);
            }
            if (indexA === -1) return 1; // A not in list, B is, so B comes first
            if (indexB === -1) return -1; // B not in list, A is, so A comes first
            return indexA - indexB; // Sort by priority index
        });

        const finalSortedStructure = {};
        for (const key of sortedKeys) {
            finalSortedStructure[key] = finalStructure[key];
        }

        fs.writeFileSync(structureOutputPath, JSON.stringify(finalSortedStructure, null, 2));
        console.log(`✅ Successfully generated docs structure at ${structureOutputPath}`);

        console.log('\n🚀 Documentation automation complete!');

    } catch (error) {
        console.error('\n❌ FATAL ERROR during documentation automation:');
        console.error(error);
        process.exit(1);
    }
}

main();