#!/usr/bin/env node
import { spawn } from 'child_process';
import { styleText } from 'node:util';
import dns from 'dns/promises';
import fs from 'fs';
import path from 'path';
import packageJson from '../package.json' with { type: 'json' };

// Configuration - Can be overridden with environment variables
const PI_HOST = process.env.PI_HOST || 'pi4c';  // hostname from ~/.ssh/config, or IP like '192.168.1.100', or 'user@host' if needed
const PI_BUILD_DIR = process.env.PI_BUILD_DIR || '/tmp/msger-native-build';

/**
 * Run SSH command using spawn to avoid quoting issues
 * @param args - Command arguments (e.g., ['pi4c', 'echo Connected'])
 * @param options - Spawn options
 * @returns Promise that resolves on success
 */
function ssh(...args: string[]): Promise<void> {
    return new Promise((resolve, reject) => {
        const proc = spawn('ssh', args, { stdio: 'inherit' });
        proc.on('close', (code) => {
            if (code === 0) {
                resolve();
            } else {
                reject(new Error(`SSH command failed with code ${code}`));
            }
        });
        proc.on('error', reject);
    });
}

/**
 * Run SCP command using spawn to avoid quoting issues
 * @param args - Command arguments (e.g., ['file.txt', 'pi4c:/tmp/'])
 * @param options - Spawn options
 * @returns Promise that resolves on success
 */
function scp(...args: string[]): Promise<void> {
    return new Promise((resolve, reject) => {
        const proc = spawn('scp', args, { stdio: 'inherit' });
        proc.on('close', (code) => {
            if (code === 0) {
                resolve();
            } else {
                reject(new Error(`SCP command failed with code ${code}`));
            }
        });
        proc.on('error', reject);
    });
}

/**
 * Run SSH command and capture output
 * @param args - Command arguments
 * @returns Promise that resolves with stdout
 */
function sshCapture(...args: string[]): Promise<string> {
    return new Promise((resolve, reject) => {
        let stdout = '';
        const proc = spawn('ssh', args, { stdio: ['ignore', 'pipe', 'pipe'] });
        proc.stdout.on('data', (data) => stdout += data.toString());
        proc.on('close', (code) => {
            if (code === 0) {
                resolve(stdout);
            } else {
                reject(new Error(`SSH command failed with code ${code}`));
            }
        });
        proc.on('error', reject);
    });
}

console.log('🦾 Building ARM64 binary via SSH to Raspberry Pi...');
console.log(`📍 Target: ${PI_HOST}`);

// Debug: Test DNS resolution first
console.log('🔍 Testing DNS resolution...');
try {
    const result = await dns.lookup(PI_HOST);
    console.log(`✅ DNS lookup successful: ${PI_HOST} -> ${result.address} (family: IPv${result.family})`);
} catch (error: any) {
    console.log(`⚠️  DNS lookup failed for ${PI_HOST}: ${error.message}`);
    console.log('   Continuing anyway - SSH may have its own resolution...');
}

try {
    // Test SSH connection
    console.log('🔍 Testing SSH connection...');
    await sshCapture(PI_HOST, 'echo Connected');
    console.log('✅ SSH connection successful');
} catch (error) {
    // Yellow/orange banner for warning (not an error)
    console.log(styleText(['yellow', 'bold'], '╔════════════════════════════════════════════════════════════════╗'));
    console.log(styleText(['yellow', 'bold'], '║  ℹ️  RASPBERRY PI NOT AVAILABLE - SKIPPING ARM64 BUILD       ║'));
    console.log(styleText(['yellow', 'bold'], '╚════════════════════════════════════════════════════════════════╝'));
    console.log('');
    console.log(`Cannot connect to Pi: ${PI_HOST}`);
    console.log('To enable Pi builds:');
    console.log(`  1. Ensure Pi is powered on and connected to network`);
    console.log(`  2. Verify SSH access: ssh ${PI_HOST}`);
    console.log(`  3. Set up SSH keys if needed: ssh-copy-id ${PI_HOST}`);
    console.log('');
    console.log('✅ Continuing build without Pi binary...');
    process.exit(0);  // Exit gracefully (not an error)
}

// Create build directory on Pi
console.log('📁 Creating build directory on Pi...');
await ssh(PI_HOST, `mkdir -p ${PI_BUILD_DIR}/src`);

// Check if build is needed (compare source file mtimes with existing binary)
console.log('🔍 Checking if build is needed...');
const destPath = path.join(import.meta.dirname, 'bin', 'msgernative-arm64');
let needsBuild = true;

if (fs.existsSync(destPath)) {
    const binaryMtime = fs.statSync(destPath).mtimeMs;

    // Check if any source files are newer than the binary
    const sourceFiles = [
        path.join(import.meta.dirname, 'Cargo.toml'),
        ...fs.readdirSync(path.join(import.meta.dirname, 'src'))
            .map(f => path.join(import.meta.dirname, 'src', f))
    ];

    const newerFiles = sourceFiles.filter(f => {
        try {
            return fs.statSync(f).mtimeMs > binaryMtime;
        } catch {
            return false;
        }
    });

    if (newerFiles.length === 0) {
        console.log('✅ Binary is up-to-date, skipping build');
        console.log(`📁 Existing binary: ${destPath}`);
        const stats = fs.statSync(destPath);
        const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
        console.log(`📊 Binary size: ${sizeMB} MB`);
        process.exit(0);
    }

    console.log(`📝 ${newerFiles.length} source file(s) newer than binary, build needed`);
    needsBuild = true;
}

// Copy source files to Pi
console.log('📤 Copying source files to Pi...');
const origDir = process.cwd();
process.chdir(import.meta.dirname);
await scp('Cargo.toml', `${PI_HOST}:${PI_BUILD_DIR}/`);
await scp('-r', 'src/*', `${PI_HOST}:${PI_BUILD_DIR}/src/`);
process.chdir(origDir);

// Check for C compiler (gcc/cc) on Pi
console.log('🔍 Checking for C compiler on Pi...');
try {
    await sshCapture(PI_HOST, 'command -v gcc');
    console.log('✅ C compiler found');
} catch {
    console.log('⚠️  C compiler not found - build will likely fail');
    console.log('   To fix: ssh pi4c "sudo apt-get install -y build-essential"');
}

// Check for Rust on Pi
console.log('🔍 Checking for Rust/Cargo on Pi...');
try {
    await sshCapture(PI_HOST, 'source ~/.cargo/env 2>/dev/null; command -v cargo');
    console.log('✅ Rust/Cargo found');
} catch {
    console.log('⚠️  Rust not found - build will fail');
    console.log('   To fix: ssh pi4c "curl --proto \'=https\' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"');
    process.exit(0);
}

// Ensure pkg-config is installed first (required to check for other dependencies)
console.log('🔧 Ensuring pkg-config is installed on Pi...');
try {
    await sshCapture(PI_HOST, 'command -v pkg-config');
    console.log('✅ pkg-config found');
} catch {
    console.log('⚠️  pkg-config not found - build will likely fail');
    console.log('   To fix: ssh pi4c "sudo apt-get install -y pkg-config"');
}

// Check for build dependencies on Pi
console.log('🔍 Checking for build dependencies on Pi...');
try {
    // Check for all required libraries: glib, gobject, gio, gtk, webkit
    await sshCapture(PI_HOST, 'pkg-config --exists glib-2.0 gobject-2.0 gio-2.0 gtk+-3.0 && (pkg-config --exists webkit2gtk-4.1 || pkg-config --exists webkit2gtk-4.0)');
    console.log('✅ Build dependencies found');
} catch {
    console.log('⚠️  Build dependencies not found - build will likely fail');
    console.log('   To fix: ssh pi4c "sudo apt-get install -y libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev"');
}

// Get NPM version from imported package.json
const npmVersion = packageJson.version;
console.log(`📋 Package version: ${npmVersion}`);

// Copy package.json to Pi (needed for version)
console.log('📤 Copying package.json to Pi...');
process.chdir(import.meta.dirname);
await scp('package.json', `${PI_HOST}:${PI_BUILD_DIR}/`);
process.chdir(origDir);

// Build on Pi
console.log('\n📦 Building ARM64 binary on Pi...');
try {
    // Source cargo env and build (ensures cargo can find all its dependencies including cc)
    // Export NPM_VERSION for Rust build
    await ssh(PI_HOST, `cd ${PI_BUILD_DIR} && source ~/.cargo/env && export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig && export NPM_VERSION=${npmVersion} && cargo build --release`);
    console.log('✅ ARM64 build completed');
} catch (error: any) {
    console.error('❌ Pi build failed:');
    console.error('⚠️  Continuing without Pi binary...');
    process.exit(0);  // Exit gracefully to not break overall build
}

// Copy binary back
console.log('📥 Copying binary back from Pi...');
const destDir = path.join(import.meta.dirname, 'bin');
if (!fs.existsSync(destDir)) {
    fs.mkdirSync(destDir, { recursive: true });
}

await scp(`${PI_HOST}:${PI_BUILD_DIR}/target/release/msgernative`, destPath);

// Set execute permissions
fs.chmodSync(destPath, 0o755);

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

// Cleanup on Pi
console.log('🧹 Cleaning up on Pi...');
await ssh(PI_HOST, `rm -rf ${PI_BUILD_DIR}`);

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