#!/usr/bin/env node

/**
 * Installation Source Tracking Script
 * Runs during npm install to detect how Desktop Commander was installed
 * 
 * Debug logging can be enabled with:
 * - DEBUG=desktop-commander npm install
 * - DEBUG=* npm install  
 * - NODE_ENV=development npm install
 * - DC_DEBUG=true npm install
 */

import { randomUUID } from 'crypto';
import * as https from 'https';
import { platform } from 'os';
import path from 'path';
import { fileURLToPath } from 'url';

// Get current file directory
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Debug logging utility - configurable via environment variables
const DEBUG_ENABLED = process.env.DEBUG === 'desktop-commander' || 
                      process.env.DEBUG === '*' || 
                      process.env.NODE_ENV === 'development' ||
                      process.env.DC_DEBUG === 'true';

const debug = (...args) => {
    if (DEBUG_ENABLED) {
        console.log('[Desktop Commander Debug]', ...args);
    }
};

const log = (...args) => {
    // Always show important messages, but prefix differently for debug vs production
    if (DEBUG_ENABLED) {
        console.log('[Desktop Commander]', ...args);
    }
};

/**
 * Get the client ID from the Desktop Commander config file, or generate a new one
 */
async function getClientId() {
    try {
        const { homedir } = await import('os');
        const { join } = await import('path');
        const fs = await import('fs');
        
        const USER_HOME = homedir();
        const CONFIG_DIR = join(USER_HOME, '.claude-server-commander');
        const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
        
        // Try to read existing config
        if (fs.existsSync(CONFIG_FILE)) {
            const configData = fs.readFileSync(CONFIG_FILE, 'utf8');
            const config = JSON.parse(configData);
            if (config.clientId) {
                debug(`Using existing clientId from config: ${config.clientId.substring(0, 8)}...`);
                return config.clientId;
            }
        }
        
        debug('No existing clientId found, generating new one');
        // Fallback to random UUID if config doesn't exist or lacks clientId
        return randomUUID();
    } catch (error) {
        debug(`Error reading config file: ${error.message}, using random UUID`);
        // If anything goes wrong, fall back to random UUID
        return randomUUID();
    }
}

// Telemetry proxy configuration (same as setup script)
const TELEMETRY_PROXY_URL = 'https://telemetry.desktopcommander.app/mp/collect';
const TELEMETRY_PROXY_FALLBACK_URL = 'https://dc-telemetry-proxy-83847352264.europe-west1.run.app/mp/collect';

/**
 * Detect installation source from environment and process context
 */
async function detectInstallationSource() {
    // Check npm environment variables for clues
    const npmConfigUserAgent = process.env.npm_config_user_agent || '';
    const npmExecpath = process.env.npm_execpath || '';
    const npmCommand = process.env.npm_command || '';
    const npmLifecycleEvent = process.env.npm_lifecycle_event || '';
    
    // Check process arguments and parent commands
    const processArgs = process.argv.join(' ');
    const processTitle = process.title || '';

    debug('Installation source detection...');
    debug(`npm_config_user_agent: ${npmConfigUserAgent}`);
    debug(`npm_execpath: ${npmExecpath}`);
    debug(`npm_command: ${npmCommand}`);
    debug(`npm_lifecycle_event: ${npmLifecycleEvent}`);
    debug(`process.argv: ${processArgs}`);
    debug(`process.title: ${processTitle}`);
    
    // Try to get parent process information
    let parentProcessInfo = null;
    try {
        const { execSync } = await import('child_process');
        const ppid = process.ppid;
        if (ppid && process.platform !== 'win32') {
            // Get parent process command line on Unix systems
            const parentCmd = execSync(`ps -p ${ppid} -o command=`, { encoding: 'utf8' }).trim();
            parentProcessInfo = parentCmd;
            debug(`parent process: ${parentCmd}`);
        }
    } catch (error) {
        debug(`Could not get parent process info: ${error.message}`);
    }
    
    // Smithery detection - look for smithery in the process chain
    const smitheryIndicators = [
        npmConfigUserAgent.includes('smithery'),
        npmExecpath.includes('smithery'),
        processArgs.includes('smithery'),
        processArgs.includes('@smithery/cli'),
        processTitle.includes('smithery'),
        parentProcessInfo && parentProcessInfo.includes('smithery'),
        parentProcessInfo && parentProcessInfo.includes('@smithery/cli')
    ];
    
    if (smitheryIndicators.some(indicator => indicator)) {
        return {
            source: 'smithery',
            details: {
                detection_method: 'process_chain',
                user_agent: npmConfigUserAgent,
                exec_path: npmExecpath,
                command: npmCommand,
                parent_process: parentProcessInfo || 'unknown',
                process_args: processArgs
            }
        };
    }
    
    // Direct NPX usage
    if (npmCommand === 'exec' || processArgs.includes('npx')) {
        return {
            source: 'npx-direct',
            details: {
                user_agent: npmConfigUserAgent,
                command: npmCommand,
                lifecycle_event: npmLifecycleEvent
            }
        };
    }
    
    // Regular npm install
    if (npmCommand === 'install' || npmLifecycleEvent === 'postinstall') {
        return {
            source: 'npm-install',
            details: {
                user_agent: npmConfigUserAgent,
                command: npmCommand,
                lifecycle_event: npmLifecycleEvent
            }
        };
    }
    
    // GitHub Codespaces
    if (process.env.CODESPACES) {
        return {
            source: 'github-codespaces',
            details: {
                codespace: process.env.CODESPACE_NAME || 'unknown'
            }
        };
    }
    
    // VS Code
    if (process.env.VSCODE_PID || process.env.TERM_PROGRAM === 'vscode') {
        return {
            source: 'vscode',
            details: {
                term_program: process.env.TERM_PROGRAM,
                vscode_pid: process.env.VSCODE_PID
            }
        };
    }
    
    // GitPod
    if (process.env.GITPOD_WORKSPACE_ID) {
        return {
            source: 'gitpod',
            details: {
                workspace_id: process.env.GITPOD_WORKSPACE_ID.substring(0, 8) + '...' // Truncate for privacy
            }
        };
    }
    
    // CI/CD environments
    if (process.env.CI) {
        if (process.env.GITHUB_ACTIONS) {
            return {
                source: 'github-actions',
                details: {
                    repository: process.env.GITHUB_REPOSITORY,
                    workflow: process.env.GITHUB_WORKFLOW
                }
            };
        }
        if (process.env.GITLAB_CI) {
            return {
                source: 'gitlab-ci',
                details: {
                    project: process.env.CI_PROJECT_NAME
                }
            };
        }
        if (process.env.JENKINS_URL) {
            return {
                source: 'jenkins',
                details: {
                    job: process.env.JOB_NAME
                }
            };
        }
        return {
            source: 'ci-cd-other',
            details: {
                ci_env: 'unknown'
            }
        };
    }
    
    // Docker detection
    if (process.env.DOCKER_CONTAINER) {
        return {
            source: 'docker',
            details: {
                container_id: process.env.HOSTNAME?.substring(0, 8) + '...' || 'unknown'
            }
        };
    }
    
    // Check for .dockerenv file (need to use fs import)
    try {
        const fs = await import('fs');
        if (fs.existsSync('/.dockerenv')) {
            return {
                source: 'docker',
                details: {
                    container_id: process.env.HOSTNAME?.substring(0, 8) + '...' || 'unknown'
                }
            };
        }
    } catch (error) {
        // Ignore fs errors
    }
    
    // Default fallback
    return {
        source: 'unknown',
        details: {
            user_agent: npmConfigUserAgent || 'none',
            command: npmCommand || 'none',
            lifecycle: npmLifecycleEvent || 'none'
        }
    };
}

/**
 * Send installation tracking to telemetry proxy
 */
async function trackInstallation(installationData) {
    try {
        const uniqueUserId = await getClientId();
        log("user id", uniqueUserId)
        // Prepare telemetry payload
        const payload = {
            client_id: uniqueUserId,
            non_personalized_ads: false,
            timestamp_micros: Date.now() * 1000,
            events: [{
                name: 'package_installed',
                params: {
                    timestamp: new Date().toISOString(),
                    platform: platform(),
                    installation_source: installationData.source,
                    installation_details: JSON.stringify(installationData.details),
                    package_name: '@wonderwhy-er/desktop-commander',
                    install_method: 'npm-lifecycle',
                    node_version: process.version,
                    npm_version: process.env.npm_version || 'unknown'
                }
            }]
        };

        const postData = JSON.stringify(payload);
        
        const options = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': Buffer.byteLength(postData)
            }
        };

        const sent = await postTelemetryPayload(TELEMETRY_PROXY_URL, postData, options);
        if (!sent) {
            await postTelemetryPayload(TELEMETRY_PROXY_FALLBACK_URL, postData, options);
        }
        log(`Installation tracked: ${installationData.source}`);

    } catch (error) {
        debug(`Failed to track installation: ${error.message}`);
        // Don't fail the installation process
    }
}

// TODO(dedup): postTelemetryPayload is copy-pasted across setup/uninstall/track
// scripts + a variant in src/utils/capture.ts. Consolidate into one shared module.
// TODO(timeout): per-endpoint timeout here is 5s, but ensureTrackingCompleted caps
// the whole flow at 6s — so if the primary times out, the fallback gets ~1s and
// almost never completes. Lower per-endpoint timeout (capture.ts uses 3s) or raise
// the overall budget so the fallback is actually usable.
async function postTelemetryPayload(endpoint, postData, options) {
    return await new Promise((resolve) => {
        let settled = false;
        let timeoutId;
        const finish = (result) => {
            if (settled) return;
            settled = true;
            clearTimeout(timeoutId);
            resolve(result);
        };
        const req = https.request(endpoint, options);
        
        timeoutId = setTimeout(() => {
            req.destroy();
            finish(false);
        }, 5000);

        req.on('error', (error) => {
            debug(`Telemetry error: ${error.message}`);
            finish(false);
        });

        req.on('response', (res) => {
            res.on('data', () => {});
            res.on('error', (error) => {
                debug(`Telemetry response error: ${error.message}`);
                finish(false);
            });
            res.on('end', () => {
                finish(res.statusCode >= 200 && res.statusCode < 300);
            });
            res.on('close', () => {
                finish(false);
            });
        });

        req.write(postData);
        req.end();
    });
}

/**
 * Main execution
 */
async function main() {
    try {
        log('Package installation detected');
        
        const installationData = await detectInstallationSource();
        log(`Installation source: ${installationData.source}`);
        
        await trackInstallation(installationData);
        
    } catch (error) {
        debug(`Installation tracking error: ${error.message}`);
        // Don't fail the installation
    }
}

// Only run if this script is executed directly (not imported)
if (import.meta.url === `file://${process.argv[1]}`) {
    main();
}

export { detectInstallationSource, trackInstallation };
