const sharp = require('sharp');
const path = require('path');
const fs = require('fs').promises;
const { PREVIEW_FS_DIR, PREVIEW_CONFIG, UPLOAD_FS_DIR } = require('../constants');

class ImagePreviewService {
    /**
     * Generates a preview/thumbnail image from the original
     * @param {string} originalPath - Absolute path to the original image
     * @param {string} previewPath - Absolute path where preview should be saved
     * @returns {Promise<{success: boolean, previewPath?: string, error?: string}>}
     */
    async generatePreview(originalPath, previewPath) {
        try {
            // Ensure preview directory exists
            const previewDir = path.dirname(previewPath);
            await fs.mkdir(previewDir, { recursive: true });

            // Check if original file exists
            await fs.access(originalPath);

            // Generate preview using sharp
            await sharp(originalPath)
                .resize(PREVIEW_CONFIG.maxWidth, null, {
                    fit: 'inside',
                    withoutEnlargement: true
                })
                .jpeg({ quality: PREVIEW_CONFIG.quality })
                .toFile(previewPath);

            // Get file sizes for logging
            const [originalStats, previewStats] = await Promise.all([
                fs.stat(originalPath),
                fs.stat(previewPath)
            ]);

            const reductionPercent = ((1 - previewStats.size / originalStats.size) * 100).toFixed(1);

            console.log(`Preview generated: ${path.basename(previewPath)}`);
            console.log(`  Original: ${(originalStats.size / 1024).toFixed(1)} KB`);
            console.log(`  Preview: ${(previewStats.size / 1024).toFixed(1)} KB`);
            console.log(`  Reduction: ${reductionPercent}%`);

            return {
                success: true,
                previewPath,
                originalSize: originalStats.size,
                previewSize: previewStats.size,
                reduction: parseFloat(reductionPercent)
            };
        } catch (error) {
            console.error(`Error generating preview for ${originalPath}:`, error.message);
            return {
                success: false,
                error: error.message
            };
        }
    }

    /**
     * Generates previews for all images in a group
     * @param {Array<{file_path: string, file_name: string}>} images - Array of image objects
     * @param {string} baseDir - Base directory for original images (absolute path)
     * @param {string} previewBaseDir - Base directory for preview images (absolute path)
     * @returns {Promise<Array<{fileName: string, previewPath: string, success: boolean}>>}
     */
    async generatePreviewsForGroup(images, baseDir, previewBaseDir) {
        const results = [];

        for (const image of images) {
            const originalPath = path.join(baseDir, image.file_name);
            const previewFileName = this._getPreviewFileName(image.file_name);
            const previewPath = path.join(previewBaseDir, previewFileName);

            const result = await this.generatePreview(originalPath, previewPath);

            results.push({
                fileName: image.file_name,
                originalPath: image.file_path,
                previewFileName,
                previewPath: previewFileName, // Relative path for DB storage
                success: result.success,
                error: result.error
            });
        }

        return results;
    }

    /**
     * Gets the preview file path for a given original filename
     * @param {string} originalFileName - Original image filename
     * @returns {string} Preview filename (always .jpg extension)
     */
    _getPreviewFileName(originalFileName) {
        const baseName = path.parse(originalFileName).name;
        return `${baseName}.jpg`;
    }

    /**
     * Gets the absolute preview path for a given preview filename
     * @param {string} previewFileName - Preview filename
     * @returns {string} Absolute path to preview file
     */
    getPreviewPath(previewFileName) {
        return path.join(__dirname, '..', PREVIEW_FS_DIR, previewFileName);
    }

    /**
     * Gets the absolute original image path for a given filename
     * @param {string} fileName - Original image filename
     * @returns {string} Absolute path to original file
     */
    getOriginalPath(fileName) {
        return path.join(__dirname, '..', UPLOAD_FS_DIR, fileName);
    }

    /**
     * Cleans up orphaned preview files that don't have corresponding originals
     * @returns {Promise<{removed: number, errors: number}>}
     */
    async cleanupOrphanedPreviews() {
        try {
            const previewDir = path.join(__dirname, '..', PREVIEW_FS_DIR);
            const originalDir = path.join(__dirname, '..', UPLOAD_FS_DIR);

            // Check if preview directory exists
            try {
                await fs.access(previewDir);
            } catch {
                console.log('Preview directory does not exist yet, skipping cleanup');
                return { removed: 0, errors: 0 };
            }

            const previewFiles = await fs.readdir(previewDir);
            let removed = 0;
            let errors = 0;

            for (const previewFile of previewFiles) {
                try {
                    // Construct corresponding original filename (might have different extension)
                    const baseName = path.parse(previewFile).name;
                    
                    // Check all possible extensions
                    const possibleExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp'];
                    let originalExists = false;

                    for (const ext of possibleExtensions) {
                        const originalPath = path.join(originalDir, baseName + ext);
                        try {
                            await fs.access(originalPath);
                            originalExists = true;
                            break;
                        } catch {
                            // Continue checking
                        }
                    }

                    if (!originalExists) {
                        const previewPath = path.join(previewDir, previewFile);
                        await fs.unlink(previewPath);
                        console.log(`Removed orphaned preview: ${previewFile}`);
                        removed++;
                    }
                } catch (error) {
                    console.error(`Error processing ${previewFile}:`, error.message);
                    errors++;
                }
            }

            return { removed, errors };
        } catch (error) {
            console.error('Error during preview cleanup:', error.message);
            return { removed: 0, errors: 1 };
        }
    }

    /**
     * Checks if a preview exists for a given original filename
     * @param {string} originalFileName - Original image filename
     * @returns {Promise<boolean>}
     */
    async previewExists(originalFileName) {
        try {
            const previewFileName = this._getPreviewFileName(originalFileName);
            const previewPath = this.getPreviewPath(previewFileName);
            await fs.access(previewPath);
            return true;
        } catch {
            return false;
        }
    }
}

module.exports = new ImagePreviewService();
