import fs from 'fs/promises';
import path from 'path';
import os from 'os';

interface ScanResult {
    path: string;
    size: number;
    lastAccessed: Date;
    type: 'node_modules' | 'vendor' | 'venv';
}

export async function scanDirectory(rootDir: string, maxDepth: number = 5): Promise<ScanResult[]> {
    const results: ScanResult[] = [];

    async function traverse(currentPath: string, depth: number) {
        if (depth > maxDepth) return;

        try {
            const entries = await fs.readdir(currentPath, { withFileTypes: true });

            for (const entry of entries) {
                const fullPath = path.join(currentPath, entry.name);

                if (entry.isDirectory()) {
                    if (entry.name === 'node_modules' || entry.name === 'vendor' || entry.name === '.venv') {
                        // Found a target
                        try {
                            const stats = await fs.stat(fullPath);
                            results.push({
                                path: fullPath,
                                size: 0, // Calculating size is expensive, might do lazily or separate task
                                lastAccessed: stats.atime,
                                type: entry.name as any
                            });
                            // Don't traverse inside node_modules
                            continue;
                        } catch (e) {
                            console.error(`Error stat-ing ${fullPath}`, e);
                        }
                    } else if (!entry.name.startsWith('.')) {
                        // Recurse normal directories
                        await traverse(fullPath, depth + 1);
                    }
                }
            }
        } catch (error) {
            console.error(`Error scanning ${currentPath}`, error);
        }
    }

    await traverse(rootDir, 0);
    return results;
}

export async function getFolderSize(folderPath: string): Promise<number> {
    let total = 0;
    try {
        const stats = await fs.stat(folderPath);
        if (stats.isFile()) return stats.size;

        const files = await fs.readdir(folderPath, { withFileTypes: true });
        for (const file of files) {
            total += await getFolderSize(path.join(folderPath, file.name));
        }
    } catch (e) {
        // ignore errors
    }
    return total;
}

export interface DeepScanResult {
    path: string;
    size: number;
    isDirectory: boolean;
}

export async function findLargeFiles(rootDir: string, threshold: number = 100 * 1024 * 1024): Promise<DeepScanResult[]> {
    const results: DeepScanResult[] = [];

    async function traverse(currentPath: string) {
        try {
            const stats = await fs.stat(currentPath);
            if (stats.size > threshold && !stats.isDirectory()) {
                results.push({ path: currentPath, size: stats.size, isDirectory: false });
                return;
            }

            if (stats.isDirectory()) {
                // SKIP node_modules to prevent self-deletion of the running app!
                if (path.basename(currentPath) === 'node_modules') return;

                const entries = await fs.readdir(currentPath, { withFileTypes: true });
                for (const entry of entries) {
                    if (entry.name.startsWith('.') && entry.name !== '.Trash') continue;
                    await traverse(path.join(currentPath, entry.name));
                }
            }
        } catch (e) { /* skip */ }
    }

    await traverse(rootDir);
    return results.sort((a, b) => b.size - a.size);
}

export async function getDeepDiveSummary() {
    const home = os.homedir();
    const targets = [
        path.join(home, 'Downloads'),
        path.join(home, 'Documents'),
        path.join(home, 'Desktop'),
        path.join(home, 'Library/Application Support'),
    ];

    const results: DeepScanResult[] = [];
    for (const t of targets) {
        console.log(`Scanning ${t}...`);
        const large = await findLargeFiles(t, 50 * 1024 * 1024); // 50MB+
        console.log(`Found ${large.length} large files in ${t}`);
        results.push(...large);
    }
    return results.slice(0, 20); // Top 20
}

import { exec } from 'child_process';
import util from 'util';
const execPromise = util.promisify(exec);

export async function getDiskUsage() {
    try {
        // macOS/Linux: df -k / gives 1K-blocks
        const { stdout } = await execPromise('df -k /');
        const lines = stdout.trim().split('\n');
        // Filesystem  1024-blocks      Used Available Capacity iused      ifree %iused  Mounted on
        // /dev/disk3s1s1 488245288 15266888 308805360     5%  350280 1957260560    0%   /
        if (lines.length < 2) return null;

        const parts = lines[1].split(/\s+/);
        // parts[1] is total in 1K blocks
        // parts[2] is used
        // parts[3] is available
        const total = parseInt(parts[1]) * 1024;
        const used = parseInt(parts[2]) * 1024;
        const available = parseInt(parts[3]) * 1024;

        return {
            totalGB: (total / 1024 / 1024 / 1024).toFixed(2),
            usedGB: (used / 1024 / 1024 / 1024).toFixed(2),
            freeGB: (available / 1024 / 1024 / 1024).toFixed(2)
        };
    } catch (e) {
        console.error("Error getting disk usage:", e);
        return null;
    }
}

export async function findHeavyFolders(rootDir: string): Promise<DeepScanResult[]> {
    try {
        console.log(`Deepest scan on: ${rootDir}`);
        // du -k -d 2: report size in KB, max depth 2
        // sort -nr: numeric reverse sort
        // head -n 50: top 50
        const { stdout } = await execPromise(`du -k -d 2 "${rootDir}" | sort -nr | head -n 50`);
        const lines = stdout.trim().split('\n');

        const results = lines.map(line => {
            // Trim leading whitespace
            const trimmed = line.trim();
            // Split by first whitespace only
            const firstSpace = trimmed.indexOf('\t'); // du output is usually tab separated or space
            // Actually du output on mac is "size<tab>path"

            // Robust splitting for size and path
            const match = trimmed.match(/^(\d+)\s+(.+)$/);
            if (!match) return null;

            const sizeK = parseInt(match[1]);
            const fullPath = match[2];

            return {
                path: fullPath,
                size: sizeK * 1024, // Convert KB to Bytes
                isDirectory: true
            };
        }).filter(item => item !== null && item.path !== rootDir) as DeepScanResult[];

        return results;
    } catch (e) {
        console.error("Deepest scan failed:", e);
        return [];
    }
}
