#!/usr/bin/env node

import { execSync } from 'child_process';
import { platform, arch } from 'os';
import { existsSync, mkdirSync, copyFileSync, readFileSync, statSync, chmodSync, readdirSync } from 'fs';
import { join } from 'path';

function isWSL() {
    try {
        const release = readFileSync('/proc/version', 'utf8');
        return release.toLowerCase().includes('microsoft');
    } catch {
        return false;
    }
}

function isWindows() {
    return platform() === 'win32' && !isWSL();
}

function runCommand(cmd: string, description: string, customEnv?: Record<string, string>) {
    console.log(`\n📦 ${description}...`);
    try {
        const env = customEnv ? { ...process.env, ...customEnv } : process.env;
        execSync(cmd, { stdio: 'inherit', env });
        console.log(`✅ ${description} completed`);
        return true;
    } catch (error: any) {
        console.error(`❌ ${description} failed:`, error.message);
        return false;
    }
}

function getCleanPathForWindows(): string {
    // Remove Git's /usr/bin from PATH to avoid link.exe conflict with VS linker
    const currentPath = process.env.PATH || '';
    const pathParts = currentPath.split(';');
    const filteredParts = pathParts.filter(part => {
        const lower = part.toLowerCase();
        return !lower.includes('git\\usr\\bin') && !lower.includes('git/usr/bin');
    });
    return filteredParts.join(';');
}

function needsRebuild(binaryPath: string, sourceDirs: string[]): boolean {
    // If binary doesn't exist, we need to build
    if (!existsSync(binaryPath)) {
        return true;
    }

    const binaryTime = statSync(binaryPath).mtime.getTime();

    // Helper to recursively check directory
    function checkDir(dirPath: string): boolean {
        const entries = readdirSync(dirPath, { withFileTypes: true });
        for (const entry of entries) {
            const fullPath = join(dirPath, entry.name);
            if (entry.isFile()) {
                const fileTime = statSync(fullPath).mtime.getTime();
                if (fileTime > binaryTime) {
                    console.log(`📝 Source file changed: ${entry.name}`);
                    return true;
                }
            } else if (entry.isDirectory()) {
                if (checkDir(fullPath)) {
                    return true;
                }
            }
        }
        return false;
    }

    // Check if any source file is newer than the binary
    for (const path of sourceDirs) {
        if (!existsSync(path)) continue;
        
        const stats = statSync(path);
        if (stats.isFile()) {
            // For files (like Cargo.toml, build.rs)
            const fileTime = stats.mtime.getTime();
            if (fileTime > binaryTime) {
                console.log(`📝 Source file changed: ${path}`);
                return true;
            }
        } else if (stats.isDirectory()) {
            // For directories (like ./src)
            if (checkDir(path)) {
                return true;
            }
        }
    }

    return false;
}

function main() {
    console.log('🚀 Building msger (Rust)...');

    if (isWindows()) {
        console.log('📍 Running on Windows');

        const destPath = `./bin/msgernative.exe`;
        
        // Check if rebuild is needed
        if (!needsRebuild(destPath, ['./src', './Cargo.toml', './build.rs'])) {
            console.log('✅ Binary is up to date, skipping build');
            console.log(`   Binary: ${destPath}`);
            const stats = statSync(destPath);
            const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
            console.log(`   Size: ${sizeMB} MB`);
        } else {
            // Try building with cargo directly first
            // Cargo should find the VS linker if available
            // Fix PATH to remove Git's link.exe which conflicts with VS linker
            const cleanPath = getCleanPathForWindows();
            console.log('🔧 Fixing PATH to use VS linker instead of Git link.exe');
            const success = runCommand('cargo build --release', 'Building Windows x64 binary (release)', { PATH: cleanPath });

            if (success) {
                // Copy binary to bin directory
                const srcPath = `./target/release/msgernative.exe`;

                if (existsSync(srcPath)) {
                    // Ensure bin directory exists
                    if (!existsSync('./bin')) {
                        mkdirSync('./bin', { recursive: true });
                    }
                    
                    copyFileSync(srcPath, destPath);
                    console.log(`\n✅ Binary copied to: ${destPath}`);

                    // Show file size
                    const stats = statSync(destPath);
                    const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
                    console.log(`📊 Binary size: ${sizeMB} MB`);
                }
            } else {
                console.log('\n⚠️  Build failed. You may need to:');
                console.log('   1. Open "x64 Native Tools Command Prompt for VS 2022"');
                console.log('   2. Run: cd Y:\\dev\\utils\\msger && cargo build --release');
                console.log('   3. Or install Visual Studio Build Tools with C++ workload');
                process.exit(1);
            }
        }

    } else if (isWSL()) {
        console.log('📍 Running on WSL');
        console.log('🐧 Building Linux x64 binary...');

        const success = runCommand('cargo build --release', 'Building Linux x64 binary');

        if (success) {
            const srcPath = `./target/release/msgernative`;
            const destPath = `./bin/msgernative`;

            if (existsSync(srcPath)) {
                // Ensure bin directory exists
                if (!existsSync('./bin')) {
                    mkdirSync('./bin', { recursive: true });
                }

                copyFileSync(srcPath, destPath);
                // Make executable
                chmodSync(destPath, 0o755);
                console.log(`\n✅ Binary copied to: ${destPath}`);

                // Show file size
                const stats = statSync(destPath);
                const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
                console.log(`📊 Binary size: ${sizeMB} MB`);

                // Also copy to root for compatibility (old location)
                const rootDestPath = `../msgernative-linux-x64`;
                copyFileSync(srcPath, rootDestPath);
                chmodSync(rootDestPath, 0o755);
                console.log(`📋 Also copied to: ${rootDestPath} (for compatibility)`);
            }
        }
    } else {
        console.log('📍 Running on Linux/macOS');
        const success = runCommand('cargo build --release', 'Building native binary');

        if (success) {
            const srcPath = `./target/release/msgernative`;
            const destPath = `./bin/msgernative`;

            if (existsSync(srcPath)) {
                // Ensure bin directory exists
                if (!existsSync('./bin')) {
                    mkdirSync('./bin', { recursive: true });
                }

                copyFileSync(srcPath, destPath);
                // Make executable
                chmodSync(destPath, 0o755);
                console.log(`\n✅ Binary copied to: ${destPath}`);

                // Show file size
                const stats = statSync(destPath);
                const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
                console.log(`📊 Binary size: ${sizeMB} MB`);

                // Also copy to root for compatibility (old location)
                const rootDestPath = `../msgernative-linux-x64`;
                copyFileSync(srcPath, rootDestPath);
                chmodSync(rootDestPath, 0o755);
                console.log(`📋 Also copied to: ${rootDestPath} (for compatibility)`);
            }
        }
    }

    console.log('\n🎉 Build process completed!');

    // Check if ARM64 binary exists
    // const arm64BinaryPath = `./bin/msgernative-arm64`;
    // if (!existsSync(arm64BinaryPath)) {
    //     // Reminder about ARM64/Pi build
    //     console.log('\n\x1b[30m\x1b[41m                                                      \x1b[0m');
    //     console.log('\x1b[30m\x1b[41m  ⚠️  REMINDER: ARM64/Pi binary not built             \x1b[0m');
    //     console.log('\x1b[30m\x1b[41m      Run: .\\build-pi.ps1 to build for Raspberry Pi  \x1b[0m');
    //     console.log('\x1b[30m\x1b[41m                                                      \x1b[0m\n');
    // }
}

main();
