import fs from 'fs';
import path from 'path';

const DOWNLOADS_DIR =
  process.env.DOWNLOADS_DIR || path.join(__dirname, '../../public/downloads');

export interface FileEntry {
  name: string;
  isDirectory: boolean;
  size: number;
  mtime: Date;
}

export class FileService {
  public static getPublicRoot(): string {
    return DOWNLOADS_DIR;
  }

  public static getProtectedRoot(): string {
    const configured = process.env.PROTECTED_DIR;
    if (configured && path.isAbsolute(configured)) {
      return configured;
    }
    // Fallback to a protected folder inside the downloads root
    return path.join(DOWNLOADS_DIR, 'protected');
  }

  public static resolveProtectedPath(relativePath: string): string | null {
    const root = this.getProtectedRoot();
    const safePath = path.normalize(path.join(root, relativePath));
    if (!safePath.startsWith(root)) return null;
    return safePath;
  }

  public static resolveSafePath(relativePath: string): string | null {
    const safePath = path.normalize(path.join(DOWNLOADS_DIR, relativePath));
    if (!safePath.startsWith(DOWNLOADS_DIR)) return null;
    return safePath;
  }

  public static listDirectory(relativePath: string = '/'): FileEntry[] {
    const dirPath = this.resolveSafePath(relativePath);
    if (!dirPath) return [];
    if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory())
      return [];
    // If protected dir lives under downloads, hide its top-level folder from root listing
    const protectedRoot = this.getProtectedRoot();
    let protectedTopLevel: string | null = null;
    const relFromDownloads = path.relative(DOWNLOADS_DIR, protectedRoot);
    if (
      !relFromDownloads.startsWith('..') &&
      !path.isAbsolute(relFromDownloads) &&
      relFromDownloads.length > 0
    ) {
      protectedTopLevel = relFromDownloads.split(path.sep)[0] || null;
    }
    return fs
      .readdirSync(dirPath)
      .filter((name) => name !== protectedTopLevel)
      .map((name) => {
        const full = path.join(dirPath, name);
        const stat = fs.statSync(full);
        return {
          name,
          isDirectory: stat.isDirectory(),
          size: stat.isDirectory() ? 0 : stat.size,
          mtime: stat.mtime,
        };
      });
  }
}
