/**
 * OTA Deployment Script
 * Uploads www.bin or universal.bundle to the ESP32 device.
 */

import { readFileSync, readdirSync, existsSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import http from 'http';

const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = resolve(__dirname, '..');
const binDir = resolve(projectRoot, 'bin');
const bundleDir = resolve(projectRoot, 'bundles');

/**
 * Simple .env parser to load VITE_API_BASE
 */
function loadEnv() {
    const envPath = resolve(projectRoot, '.env');
    if (existsSync(envPath)) {
        const content = readFileSync(envPath, 'utf8');
        content.split('\n').forEach(line => {
            const [key, ...valueParts] = line.split('=');
            if (key && valueParts.length > 0) {
                const value = valueParts.join('=').trim().replace(/^["']|["']$/g, '');
                process.env[key.trim()] = value;
            }
        });
    }
}

loadEnv();

const targetIP = process.env.VITE_API_BASE ? process.env.VITE_API_BASE.replace('http://', '').replace(/\/+$/, '') : null;

if (!targetIP) {
    console.error('Error: VITE_API_BASE not found in frontend/.env. Please set it to the target device IP.');
    process.exit(1);
}

const args = process.argv.slice(2);
const isBundle = args.includes('--bundle');
const isFrontend = args.includes('--frontend');

if (!isBundle && !isFrontend) {
    console.error('Error: Specify --frontend or --bundle.');
    process.exit(1);
}

function getLatestFile(dir, pattern) {
    if (!existsSync(dir)) return null;
    const files = readdirSync(dir)
        .filter(f => f.match(pattern))
        .sort((a, b) => {
            const getParts = (s) => {
                const m = s.match(/v(\d+)\.(\d+)\.(\d+)/);
                return m ? m.slice(1).map(Number) : [0, 0, 0];
            };
            const [aMajor, aMinor, aRev] = getParts(a);
            const [bMajor, bMinor, bRev] = getParts(b);
            return (bMajor - aMajor) || (bMinor - aMinor) || (bRev - aRev);
        });
    return files.length > 0 ? resolve(dir, files[0]) : null;
}

const filePath = isBundle 
    ? getLatestFile(bundleDir, /^universal_v.*\.bundle$/)
    : getLatestFile(binDir, /^www_v.*\.bin$/);

if (!filePath) {
    console.error(`Error: No recent ${isBundle ? 'bundle' : 'frontend bin'} found in ${isBundle ? bundleDir : binDir}`);
    process.exit(1);
}

const fileName = filePath.split(/[\\/]/).pop();
const versionMatch = fileName.match(/v(\d+\.\d+\.\d+)/);
const version = versionMatch ? versionMatch[1] : 'unknown';

console.log('-------------------------------------------');
console.log(`🚀 Deployment Started`);
console.log(`📍 Target device: http://${targetIP}`);
console.log(`📦 Packaging type: ${isBundle ? 'Universal Bundle' : 'Frontend Only'}`);
console.log(`📄 File: ${fileName}`);
console.log(`🔖 Version: ${version}`);
console.log('-------------------------------------------');

const fileBuf = readFileSync(filePath);
const urlPath = isBundle ? '/api/ota/bundle' : '/api/ota/frontend';
const url = `http://${targetIP}${urlPath}`;

console.log(`Uploading ${fileBuf.length} bytes using fetch API... (This mimics the browser UI upload)`);

async function deploy() {
    try {
        const response = await fetch(url, {
            method: 'POST',
            body: fileBuf,
            headers: {
                'Content-Type': 'application/octet-stream',
                'Content-Length': fileBuf.length.toString()
            }
        });

        if (response.ok) {
            const text = await response.text();
            console.log('\n✅ Success: Update committed!');
            console.log('Server response:', text);
            console.log('The device will reboot in ~1 second.');
            
            // Wait a few seconds to let the socket close gracefully before killing the process
            setTimeout(() => {
                console.log('Deployment script finished.');
                process.exit(0);
            }, 3000);
        } else {
            const text = await response.text();
            console.error(`\n❌ Error (${response.status}):`, text);
            process.exit(1);
        }
    } catch (e) {
        console.error(`\n❌ Problem with request:`, e.message);
        if (e.cause) console.error(e.cause);
        process.exit(1);
    }
}

deploy();
