import { fileURLToPath } from 'node:url';
import { dirname, resolve, join } from 'node:path';
import { mkdirSync, existsSync, statSync } from 'node:fs';
import { homedir } from 'node:os';

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

export const PROJECT_ROOT = resolve(__dirname, '..');

// OS-Standard-Pfad fuer App-interne Daten (Config, Browser-Sessions, Logs).
// Liegt ausserhalb des App-/Repo-Folders, damit Deinstallation/Update die User-Daten nicht zerstoert.
//   Windows: %APPDATA%\DocuDown
//   macOS:   ~/Library/Application Support/DocuDown
//   Linux:   $XDG_CONFIG_HOME/DocuDown (Default ~/.config/DocuDown)
// Override via Env-Var DOCUDOWN_HOME — sinnvoll fuer Dev (z. B. DOCUDOWN_HOME=. um im Repo zu bleiben).
function defaultAppDataDir() {
  if (process.env.DOCUDOWN_HOME) return resolve(process.env.DOCUDOWN_HOME);
  if (process.platform === 'win32') {
    return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'DocuDown');
  }
  if (process.platform === 'darwin') {
    return join(homedir(), 'Library', 'Application Support', 'DocuDown');
  }
  return join(process.env.XDG_CONFIG_HOME || join(homedir(), '.config'), 'DocuDown');
}

export const APP_DATA_DIR = defaultAppDataDir();
export const CONFIG_PATH = join(APP_DATA_DIR, 'config.enc');
export const BROWSER_DATA_ROOT = join(APP_DATA_DIR, 'browser-data');
export const LOG_DIR = join(APP_DATA_DIR, 'logs');

// Legacy-Pfade aus der Zeit, in der alles im Repo lag — nur fuer Migration verwendet.
export const LEGACY_CONFIG_PATH = join(PROJECT_ROOT, 'config.enc');
export const LEGACY_BROWSER_DATA_ROOT = join(PROJECT_ROOT, 'browser-data');
export const LEGACY_LOG_DIR = join(PROJECT_ROOT, 'logs');

function findUpwards(startDir, name, maxLevels = 6) {
  let dir = startDir;
  for (let i = 0; i <= maxLevels; i++) {
    const candidate = join(dir, name);
    if (existsSync(candidate) && statSync(candidate).isDirectory()) return candidate;
    const parent = dirname(dir);
    if (parent === dir) break;
    dir = parent;
  }
  return null;
}

export const DEFAULT_KONTO_ROOT = findUpwards(PROJECT_ROOT, 'Konto') ?? resolve(PROJECT_ROOT, '..', 'Konto');

export function ensureDir(p) {
  if (!existsSync(p)) mkdirSync(p, { recursive: true });
  return p;
}

export function browserDataDir(sourceKey, accountKey) {
  return ensureDir(join(BROWSER_DATA_ROOT, sourceKey, accountKey));
}

export function targetDirFor(rootDir, folderName, year, subfolder, opts) {
  return ensureDir(targetDirPath(rootDir, folderName, year, subfolder, opts));
}

// opts.yearSubfolder (default true): legt Files unter <folderName>/<year>/ ab.
// Auf false: <folderName>/ flach — sinnvoll fuer Quellen mit wenigen Files/Jahr.
export function targetDirPath(rootDir, folderName, year, subfolder, opts) {
  const yearSubfolder = opts?.yearSubfolder ?? true;
  const parts = [rootDir, folderName];
  if (subfolder) parts.push(subfolder);
  if (yearSubfolder) parts.push(String(year));
  return join(...parts);
}

// Prueft beide Layout-Varianten (mit/ohne Year-Subfolder), damit ein Wechsel
// des Layout-Settings nicht zu Doppel-Downloads bestehender Files fuehrt.
// Liefert den gefundenen Pfad oder null.
export function fileExistsAtAnyLayout(cfg, folderName, year, subfolder, filename) {
  const safe = safeFilename(filename);
  const current = cfg?.layout?.yearSubfolder ?? true;
  for (const yearSubfolder of [current, !current]) {
    const path = join(targetDirPath(cfg.rootDir, folderName, year, subfolder, { yearSubfolder }), safe);
    if (existsSync(path) && statSync(path).size > 0) return path;
  }
  return null;
}

// Windows-Reserved-Names: CON, PRN, AUX, NUL, COM1-9, LPT1-9 — ein File "CON.pdf" sprengt
// das fileSystem-API mit ENOENT/EACCES. Wir prefixen ein "_" davor.
const WIN_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|$)/i;

export function safeFilename(name) {
  let s = name
    .replace(/[\\/:*?"<>|]/g, '_')   // Windows-Verbotszeichen
    .replace(/\.{2,}/g, '.')          // doppelte Dots → einer (verhindert ".." als Pfad-Traversal)
    .replace(/^\.+/, '_')             // fuehrende Dots: ".env" → "_env" (auch Path-Traversal-Schutz)
    .trim()
    .replace(/[. ]+$/, '');           // Trailing dots/spaces — Windows strippt die stumm,
                                       // sonst Re-Download-Loop (Filename-Mismatch beim Lookup)
  if (WIN_RESERVED.test(s)) s = `_${s}`;
  return s || '_';                    // Falls alles weggeputzt wurde
}
