import { NextResponse } from 'next/server';
import fs from 'fs-extra';
import path from 'path';
import { getSpectrogramsPath } from '@/lib/utils/paths';

/**
 * Robustly removes a directory with retries, exponential backoff, and manual file-by-file cleanup fallback
 * to handle transient file locks or pending OS handle releases (e.g. ENOTEMPTY / EBUSY).
 */
async function removeDirectoryWithRetry(dirPath: string, retries = 5, delayMs = 300): Promise<void> {
    for (let attempt = 1; attempt <= retries; attempt++) {
        try {
            if (!(await fs.pathExists(dirPath))) return;

            // Standard recursive force removal with internal retries
            await fs.rm(dirPath, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });

            if (!(await fs.pathExists(dirPath))) {
                return;
            }
        } catch (err) {
            console.warn(`Attempt ${attempt}/${retries} to remove directory ${dirPath} failed:`, err);
        }

        // Fallback: If directory still exists, manually remove contents individually
        try {
            if (await fs.pathExists(dirPath)) {
                const files = await fs.readdir(dirPath);
                for (const file of files) {
                    const fullPath = path.join(dirPath, file);
                    try {
                        await fs.remove(fullPath);
                    } catch (e) {
                        console.warn(`Failed to remove item inside directory ${fullPath}:`, e);
                    }
                }
                // Try rmdir on the directory
                await fs.rmdir(dirPath);
                if (!(await fs.pathExists(dirPath))) return;
            }
        } catch (err) {
            // Ignore intermediate loop errors; retry will continue
        }

        if (attempt < retries) {
            await new Promise((resolve) => setTimeout(resolve, delayMs * attempt));
        }
    }

    // Final attempt
    if (await fs.pathExists(dirPath)) {
        await fs.remove(dirPath);
    }
}

export async function POST(request: Request) {
    try {
        const { albumPath, upc } = await request.json();

        if (!albumPath) {
            return NextResponse.json({ error: 'Invalid album path' }, { status: 400 });
        }

        const albumName = path.basename(albumPath);
        const parentDir = path.dirname(albumPath);
        const errors: string[] = [];

        // 1. Delete generated torrent file(s) FIRST (independent of directory removal)
        if (process.env.DELETE_GENERATED_TORRENTS === 'true') {
            try {
                const primaryTorrentPath = path.join(parentDir, `${albumName}.torrent`);
                if (await fs.pathExists(primaryTorrentPath)) {
                    await fs.remove(primaryTorrentPath);
                    console.log(`Deleted generated torrent: ${primaryTorrentPath}`);
                }

                // Also check for matching torrent files in parent directory
                if (await fs.pathExists(parentDir)) {
                    const files = await fs.readdir(parentDir);
                    const matchingTorrents = files.filter(f =>
                        f.endsWith('.torrent') && f.toLowerCase().includes(albumName.toLowerCase())
                    );
                    for (const torrentFile of matchingTorrents) {
                        const tPath = path.join(parentDir, torrentFile);
                        if (await fs.pathExists(tPath)) {
                            await fs.remove(tPath);
                            console.log(`Deleted matching torrent: ${tPath}`);
                        }
                    }
                }
            } catch (tErr) {
                console.error('Error deleting generated torrent:', tErr);
                errors.push(`Torrent deletion warning: ${tErr instanceof Error ? tErr.message : String(tErr)}`);
            }
        }

        // 2. Delete spectrograms directory for this album (independent task)
        try {
            const specRoot = getSpectrogramsPath();
            const specDir = path.join(specRoot, upc || albumName);
            if (await fs.pathExists(specDir)) {
                await fs.remove(specDir);
            }
            if (upc && albumName !== upc) {
                const altSpecDir = path.join(specRoot, albumName);
                if (await fs.pathExists(altSpecDir)) {
                    await fs.remove(altSpecDir);
                }
            }
        } catch (sErr) {
            console.error('Error deleting spectrograms:', sErr);
            errors.push(`Spectrogram deletion warning: ${sErr instanceof Error ? sErr.message : String(sErr)}`);
        }

        // 3. Delete the album directory with retries
        if (await fs.pathExists(albumPath)) {
            try {
                await removeDirectoryWithRetry(albumPath, 5, 300);
            } catch (dirErr) {
                console.error('Error deleting album directory:', dirErr);
                errors.push(`Album directory deletion error: ${dirErr instanceof Error ? dirErr.message : String(dirErr)}`);
            }
        }

        // Verify result
        const directoryStillExists = await fs.pathExists(albumPath);
        if (directoryStillExists) {
            return NextResponse.json({
                error: `Failed to completely remove directory: ${path.basename(albumPath)}`,
                details: errors
            }, { status: 500 });
        }

        return NextResponse.json({ success: true, warnings: errors.length > 0 ? errors : undefined });
    } catch (error) {
        console.error('Error deleting album:', error);
        return NextResponse.json({ error: 'Failed to delete album' }, { status: 500 });
    }
}
