import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export class FileCleanupService {
  constructor() {
    this.uploadsDir = path.join(__dirname, '../uploads');
    this.outputDir = path.join(__dirname, '../output');
    this.tempDir = path.join(__dirname, '../temp');
    this.retentionHours = 24;
  }

  async cleanupOldFiles() {
    try {
      console.log('🧹 Starting file cleanup process...');
      
      const now = Date.now();
      const retentionMs = this.retentionHours * 60 * 60 * 1000; // 24 hours in milliseconds
      const cutoffTime = now - retentionMs;

      // Cleanup uploads directory
      await this.cleanupDirectory(this.uploadsDir, cutoffTime, 'uploads');
      
      // Cleanup output directory (processed files)
      await this.cleanupDirectory(this.outputDir, cutoffTime, 'output');
      
      // Cleanup temp directory
      await this.cleanupDirectory(this.tempDir, cutoffTime, 'temp');

      console.log('✅ File cleanup completed successfully');
    } catch (error) {
      console.error('❌ File cleanup error:', error);
    }
  }

  async cleanupDirectory(dirPath, cutoffTime, dirName) {
    try {
      // Check if directory exists
      try {
        await fs.access(dirPath);
      } catch (error) {
        console.log(`📁 Directory ${dirName} does not exist, skipping cleanup`);
        return;
      }

      const items = await fs.readdir(dirPath, { withFileTypes: true });
      let deletedFiles = 0;
      let deletedDirs = 0;

      for (const item of items) {
        const itemPath = path.join(dirPath, item.name);
        
        try {
          const stats = await fs.stat(itemPath);
          const isOld = stats.mtime.getTime() < cutoffTime;

          if (isOld) {
            if (item.isDirectory()) {
              // Recursively delete old directories
              await this.deleteDirectory(itemPath);
              deletedDirs++;
              console.log(`🗂️  Deleted old directory: ${path.relative(process.cwd(), itemPath)}`);
            } else {
              // Delete old files
              await fs.unlink(itemPath);
              deletedFiles++;
              console.log(`🗑️  Deleted old file: ${path.relative(process.cwd(), itemPath)}`);
            }
          }
        } catch (error) {
          console.error(`⚠️  Error processing ${itemPath}:`, error.message);
        }
      }

      if (deletedFiles > 0 || deletedDirs > 0) {
        console.log(`📊 ${dirName} cleanup: ${deletedFiles} files, ${deletedDirs} directories deleted`);
      } else {
        console.log(`✨ ${dirName} directory is clean (no old files found)`);
      }
    } catch (error) {
      console.error(`❌ Error cleaning up ${dirName} directory:`, error);
    }
  }

  async deleteDirectory(dirPath) {
    try {
      const items = await fs.readdir(dirPath);
      
      // Delete all contents first
      for (const item of items) {
        const itemPath = path.join(dirPath, item);
        const stats = await fs.stat(itemPath);
        
        if (stats.isDirectory()) {
          await this.deleteDirectory(itemPath);
        } else {
          await fs.unlink(itemPath);
        }
      }
      
      // Delete the empty directory
      await fs.rmdir(dirPath);
    } catch (error) {
      console.error(`Error deleting directory ${dirPath}:`, error);
    }
  }

  async getDirectorySize(dirPath) {
    try {
      const items = await fs.readdir(dirPath, { withFileTypes: true });
      let totalSize = 0;
      let fileCount = 0;

      for (const item of items) {
        const itemPath = path.join(dirPath, item.name);
        
        if (item.isDirectory()) {
          const subDirInfo = await this.getDirectorySize(itemPath);
          totalSize += subDirInfo.size;
          fileCount += subDirInfo.count;
        } else {
          const stats = await fs.stat(itemPath);
          totalSize += stats.size;
          fileCount++;
        }
      }

      return { size: totalSize, count: fileCount };
    } catch (error) {
      return { size: 0, count: 0 };
    }
  }

  async getCleanupStats() {
    try {
      const uploadsInfo = await this.getDirectorySize(this.uploadsDir);
      const outputInfo = await this.getDirectorySize(this.outputDir);
      const tempInfo = await this.getDirectorySize(this.tempDir);

      const formatSize = (bytes) => {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
      };

      return {
        uploads: {
          files: uploadsInfo.count,
          size: formatSize(uploadsInfo.size)
        },
        output: {
          files: outputInfo.count,
          size: formatSize(outputInfo.size)
        },
        temp: {
          files: tempInfo.count,
          size: formatSize(tempInfo.size)
        },
        total: {
          files: uploadsInfo.count + outputInfo.count + tempInfo.count,
          size: formatSize(uploadsInfo.size + outputInfo.size + tempInfo.size)
        }
      };
    } catch (error) {
      console.error('Error getting cleanup stats:', error);
      return null;
    }
  }

  startPeriodicCleanup() {
    // Run cleanup immediately
    this.cleanupOldFiles();
    
    // Then run every 6 hours
    const intervalMs = 6 * 60 * 60 * 1000; // 6 hours
    setInterval(() => {
      this.cleanupOldFiles();
    }, intervalMs);

    console.log(`🔄 Periodic file cleanup started (every 6 hours, retention: ${this.retentionHours} hours)`);
  }
}

export const fileCleanupService = new FileCleanupService();