import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import fs from 'fs';
import { DbService } from './db.service';

@Injectable()
export class MaintenanceService {
  private logger = new Logger('MaintenanceService');

  constructor(private readonly db: DbService) {}

  cleanup(file: string, dirs: string[]) {
    for (let i = 0, l = dirs.length; i < l; i++) {
      const dir = dirs[i];
      if (file && dir && file.indexOf(dir) > -1) {
        const dataset = dir.replace(/.*\/(.*)/, '$1');
        const exists = fs.existsSync(file);
        if (!exists) this.db.removeFile(dataset, file, true);
      }
    }
  }

  purge(
    dirs: string[],
    dayMs = 24 * 60 * 60 * 1000,
    cleanerMs = 60 * 60 * 1000,
  ) {
    const ago = new Date(Date.now() - dayMs);
    this.logger.log(`Checking for "deleted" records older than ${ago}`);
    for (let i = 0, l = dirs.length; i < l; i++) {
      const dir = dirs[i];
      const dataset = dir.replace(/.*\/(.*)/, '$1');
      const files = this.db.getDeletedOlderThan(dataset, ago.toISOString());
      for (const file of files as { input: string }[]) {
        this.logger.log(`Purging "${file.input}" (${new Date()})`);
        if (file && file.input) this.db.removeFile(dataset, file.input, false);
      }
    }
    setTimeout(() => {
      this.purge(dirs, dayMs, cleanerMs);
    }, cleanerMs);
  }

  prune(dirs: string[]) {
    this.logger.log('Checking for any files that no longer exist on disk.');
    for (let i = 0, l = dirs.length; i < l; i++) {
      const dir = dirs[i];
      const dataset = dir.replace(/.*\/(.*)/, '$1');

      // Get all files for this dataset (not just successful ones)
      const allFiles = this.db.getAllFiles(dataset);
      for (const file of allFiles as { input: string; status: string }[]) {
        const exists = fs.existsSync(file.input);
        if (!exists) {
          // Only soft delete if not already marked as deleted
          if (file.status !== 'deleted') {
            this.logger.log(
              `Marking missing file as deleted: "${file.input}" (${new Date()})`,
            );
            this.db.removeFile(dataset, file.input, true); // soft delete
          }
        }
      }
    }
  }

  // Scheduled task cleanup - runs periodically to prevent task table from growing too large
  @Cron(CronExpression.EVERY_DAY_AT_2AM) // Run daily at 2 AM
  scheduledTaskCleanup() {
    this.logger.log('Running scheduled task cleanup');

    try {
      // Archive completed tasks older than 30 days
      const archiveResult = this.db.archiveOldTasks(30);
      this.logger.log(`Archived ${archiveResult?.changes || 0} old tasks`);

      // Delete failed tasks older than 7 days
      const failedResult = this.db.deleteTasksByStatus('failed', 7);
      this.logger.log(
        `Deleted ${failedResult.changes} failed tasks older than 7 days`,
      );

      // Delete skipped tasks older than 7 days
      const skippedResult = this.db.deleteTasksByStatus('skipped', 7);
      this.logger.log(
        `Deleted ${skippedResult.changes} skipped tasks older than 7 days`,
      );

      // Keep completed tasks for 90 days, then archive them
      const completedResult = this.db.deleteTasksByStatus('completed', 90);
      this.logger.log(
        `Deleted ${completedResult.changes} completed tasks older than 90 days`,
      );
    } catch (error) {
      this.logger.error(
        `Error during scheduled task cleanup: ${error.message}`,
      );
    }
  }
}
