import { exec } from 'child_process';
import { promisify } from 'util';
import * as fs from 'fs/promises';
import * as path from 'path';
import * as os from 'os';

const execAsync = promisify(exec);

export type ToolStatus = {
    name: string;
    exists: boolean;
    path?: string;
};

export type ToolCheckResult = {
    allExists: boolean;
    tools: ToolStatus[];
    mkbrrPresetExists?: boolean;
};

const REQUIRED_TOOLS = ['sox', 'mkbrr', 'salmon'];

async function checkMkbrrPreset(): Promise<boolean> {
    const tempDir = os.tmpdir();
    const dummyFile = path.join(tempDir, `mkbrr_check_${Date.now()}`);
    const outputFile = `${dummyFile}.torrent`;
    const presetName = 'red';

    try {
        // Create a dummy file
        await fs.writeFile(dummyFile, 'test');

        // Try to create a torrent with the red preset
        // We expect this to fail if the preset doesn't exist
        // If it succeeds (or fails for other reasons but finds the preset), we're good
        try {
            // Explicitly set output file to ensure we know where it is for cleanup
            await execAsync(`mkbrr create "${dummyFile}" -P ${presetName} -o "${outputFile}"`);
            return true;
        } catch (error: any) {
            // Check for the specific error message indicating the preset is missing
            // We use the presetName variable so this logic holds if we change the preset for testing
            if (error.stderr && error.stderr.includes(`preset "${presetName}" not found`)) {
                return false;
            }
            // If it failed for another reason (e.g. file issue), but didn't complain about the preset,
            // we assume the preset exists.
            return true;
        }
    } catch (error) {
        console.error('Error checking mkbrr preset:', error);
        return false; // Fail safe
    } finally {
        // Cleanup
        try {
            await fs.unlink(dummyFile);
            await fs.unlink(outputFile).catch(() => { }); // Ignore if torrent wasn't created
        } catch (e) {
            // Ignore cleanup errors
        }
    }
}

export async function checkTools(): Promise<ToolCheckResult> {
    const results: ToolStatus[] = await Promise.all(
        REQUIRED_TOOLS.map(async (tool) => {
            try {
                const { stdout } = await execAsync(`which ${tool}`);
                return {
                    name: tool,
                    exists: true,
                    path: stdout.trim(),
                };
            } catch (error) {
                return {
                    name: tool,
                    exists: false,
                };
            }
        })
    );

    const allExists = results.every((result) => result.exists);

    let mkbrrPresetExists = true;
    const mkbrrStatus = results.find(r => r.name === 'mkbrr');
    if (mkbrrStatus && mkbrrStatus.exists) {
        mkbrrPresetExists = await checkMkbrrPreset();
    }

    return {
        allExists: allExists && mkbrrPresetExists,
        tools: results,
        mkbrrPresetExists,
    };
}
