#!/usr/bin/env node
import { Command } from 'commander';
import { databaseManager } from './core/database.js';
import { spawn } from 'child_process';
import path from 'path';
import { fileURLToPath } from 'url';
import os from 'os';
import fs from 'fs';
const program = new Command();
program
    .name('gitdb')
    .description('GitHub-backed NoSQL database CLI')
    .version('1.0.0');
const HOME = os.homedir();
const PID_FILE = `${HOME}/.gitdb-server.pid`;
const LOG_FILE = `${HOME}/.gitdb-server.log`;
function getServerPid() {
    try {
        return parseInt(fs.readFileSync(PID_FILE, 'utf8'), 10);
    }
    catch {
        return null;
    }
}
function isProcessRunning(pid) {
    try {
        process.kill(pid, 0);
        return true;
    }
    catch {
        return false;
    }
}
// Connect to database
program
    .command('connect')
    .description('Connect to a GitHub repository database')
    .requiredOption('-t, --token <token>', 'GitHub personal access token')
    .requiredOption('-o, --owner <owner>', 'GitHub repository owner')
    .requiredOption('-r, --repo <repo>', 'GitHub repository name')
    .action(async (options) => {
    try {
        await databaseManager.connect({
            token: options.token,
            owner: options.owner,
            repo: options.repo
        });
        await databaseManager.initializeDatabase();
        console.log(`✅ Connected to database: ${options.owner}/${options.repo}`);
    }
    catch (error) {
        console.error(`❌ Connection failed: ${error.message}`);
        process.exit(1);
    }
});
// List collections
program
    .command('collections')
    .description('List all collections')
    .action(async () => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        const collections = await databaseManager.listCollections();
        if (collections.length === 0) {
            console.log('📁 No collections found');
        }
        else {
            console.log('📁 Collections:');
            collections.forEach(collection => console.log(`  - ${collection}`));
        }
    }
    catch (error) {
        console.error(`❌ Failed to list collections: ${error.message}`);
        process.exit(1);
    }
});
// Create collection
program
    .command('create-collection')
    .description('Create a new collection')
    .argument('<name>', 'Collection name')
    .action(async (name) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        await databaseManager.createCollection(name);
        console.log(`✅ Collection '${name}' created successfully`);
    }
    catch (error) {
        console.error(`❌ Failed to create collection: ${error.message}`);
        process.exit(1);
    }
});
// Delete collection
program
    .command('delete-collection')
    .description('Delete a collection')
    .argument('<name>', 'Collection name')
    .action(async (name) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        await databaseManager.deleteCollection(name);
        console.log(`✅ Collection '${name}' deleted successfully`);
    }
    catch (error) {
        console.error(`❌ Failed to delete collection: ${error.message}`);
        process.exit(1);
    }
});
// List documents
program
    .command('documents')
    .description('List documents in a collection')
    .argument('<collection>', 'Collection name')
    .action(async (collection) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        const documents = await databaseManager.listDocuments(collection);
        if (documents.length === 0) {
            console.log(`📄 No documents found in collection '${collection}'`);
        }
        else {
            console.log(`📄 Documents in '${collection}':`);
            documents.forEach(doc => console.log(`  - ${doc}`));
        }
    }
    catch (error) {
        console.error(`❌ Failed to list documents: ${error.message}`);
        process.exit(1);
    }
});
// Create document
program
    .command('create-doc')
    .description('Create a new document')
    .argument('<collection>', 'Collection name')
    .argument('<data>', 'Document data (JSON string)')
    .action(async (collection, data) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        const documentData = JSON.parse(data);
        const document = await databaseManager.createDocument(collection, documentData);
        console.log(`✅ Document created with ID: ${document._id}`);
        console.log(JSON.stringify(document, null, 2));
    }
    catch (error) {
        console.error(`❌ Failed to create document: ${error.message}`);
        process.exit(1);
    }
});
// Read document
program
    .command('read-doc')
    .description('Read a document by ID')
    .argument('<collection>', 'Collection name')
    .argument('<id>', 'Document ID')
    .action(async (collection, id) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        const document = await databaseManager.readDocument(collection, id);
        console.log(JSON.stringify(document, null, 2));
    }
    catch (error) {
        console.error(`❌ Failed to read document: ${error.message}`);
        process.exit(1);
    }
});
// Update document
program
    .command('update-doc')
    .description('Update a document by ID')
    .argument('<collection>', 'Collection name')
    .argument('<id>', 'Document ID')
    .argument('<data>', 'Update data (JSON string)')
    .action(async (collection, id, data) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        const updateData = JSON.parse(data);
        const document = await databaseManager.updateDocument(collection, id, updateData);
        console.log(`✅ Document updated successfully`);
        console.log(JSON.stringify(document, null, 2));
    }
    catch (error) {
        console.error(`❌ Failed to update document: ${error.message}`);
        process.exit(1);
    }
});
// Delete document
program
    .command('delete-doc')
    .description('Delete a document by ID')
    .argument('<collection>', 'Collection name')
    .argument('<id>', 'Document ID')
    .action(async (collection, id) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        await databaseManager.deleteDocument(collection, id);
        console.log(`✅ Document '${id}' deleted successfully`);
    }
    catch (error) {
        console.error(`❌ Failed to delete document: ${error.message}`);
        process.exit(1);
    }
});
// Find documents
program
    .command('find')
    .description('Find documents by query')
    .argument('<collection>', 'Collection name')
    .argument('<query>', 'Query (JSON string)')
    .action(async (collection, query) => {
    try {
        if (!databaseManager.isConnected()) {
            console.error('❌ Not connected to database. Use "gitdb connect" first.');
            process.exit(1);
        }
        const queryData = JSON.parse(query);
        const documents = await databaseManager.findDocuments(collection, queryData);
        if (documents.length === 0) {
            console.log('🔍 No documents found matching the query');
        }
        else {
            console.log(`🔍 Found ${documents.length} document(s):`);
            documents.forEach((doc, index) => {
                console.log(`\n--- Document ${index + 1} ---`);
                console.log(JSON.stringify(doc, null, 2));
            });
        }
    }
    catch (error) {
        console.error(`❌ Failed to find documents: ${error.message}`);
        process.exit(1);
    }
});
// Status
program
    .command('status')
    .description('Show database connection status')
    .action(() => {
    const connection = databaseManager.getConnection();
    if (connection) {
        console.log(`✅ Connected to: ${connection.owner}/${connection.repo}`);
    }
    else {
        console.log('❌ Not connected to any database');
    }
});
// Add passthrough for 'shell' command
program
    .command('shell')
    .description('Launch the interactive GitDB shell')
    .action(() => {
    // Resolve dist/shell.js relative to this file
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);
    const shellPath = path.resolve(__dirname, '../dist/shell.js');
    const child = spawn(process.execPath, [shellPath], { stdio: 'inherit' });
    child.on('exit', code => process.exit(code ?? 0));
});
// Add passthrough for 'server' command
program
    .command('server')
    .description('Start the GitDB server')
    .action(() => {
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);
    const serverPath = path.resolve(__dirname, '../dist/server.js');
    const child = spawn(process.execPath, [serverPath], { stdio: 'inherit' });
    child.on('exit', code => process.exit(code ?? 0));
});
program
    .command('server-start')
    .description('Start the GitDB server as a background process')
    .action(() => {
    const pid = getServerPid();
    if (pid && isProcessRunning(pid)) {
        console.log(`Server already running (PID: ${pid})`);
        process.exit(0);
    }
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);
    const serverPath = path.resolve(__dirname, '../dist/server.js');
    const out = fs.openSync(LOG_FILE, 'a');
    const child = spawn(process.execPath, [serverPath], {
        detached: true,
        stdio: ['ignore', out, out],
    });
    fs.writeFileSync(PID_FILE, String(child.pid));
    child.unref();
    console.log(`Server started in background (PID: ${child.pid})`);
});
program
    .command('server-restart')
    .description('Restart the GitDB server')
    .action(() => {
    const pid = getServerPid();
    if (pid && isProcessRunning(pid)) {
        try {
            process.kill(pid);
            console.log(`Stopped server (PID: ${pid})`);
        }
        catch (e) {
            console.log('Failed to stop server:', e.message);
        }
        fs.unlinkSync(PID_FILE);
    }
    // Start new server
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);
    const serverPath = path.resolve(__dirname, '../dist/server.js');
    const out = fs.openSync(LOG_FILE, 'a');
    const child = spawn(process.execPath, [serverPath], {
        detached: true,
        stdio: ['ignore', out, out],
    });
    fs.writeFileSync(PID_FILE, String(child.pid));
    child.unref();
    console.log(`Server restarted in background (PID: ${child.pid})`);
});
program
    .command('server-status')
    .description('Check if the GitDB server is running')
    .action(() => {
    const pid = getServerPid();
    if (pid && isProcessRunning(pid)) {
        console.log(`Server is running (PID: ${pid})`);
    }
    else {
        console.log('Server is not running');
    }
});
program
    .command('server-log')
    .description('Show the last 50 lines of the server log')
    .action(() => {
    if (!fs.existsSync(LOG_FILE)) {
        console.log('No server log found');
        return;
    }
    const lines = fs.readFileSync(LOG_FILE, 'utf8').split('\n');
    const lastLines = lines.slice(-50).join('\n');
    console.log(lastLines);
});
program.parse();
//# sourceMappingURL=cli.js.map