const fs = require('fs');
const path = require('path');

function ensureDirForFile(filePath) {
  const dir = path.dirname(filePath);
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
}

function cloneDefault(defaultValue) {
  return JSON.parse(JSON.stringify(defaultValue));
}

function fsyncPath(filePath) {
  let fd = null;
  try {
    fd = fs.openSync(filePath, 'r');
    fs.fsyncSync(fd);
  } catch (error) {
    if (error.code !== 'EINVAL' && error.code !== 'EBADF') {
      throw error;
    }
  } finally {
    if (fd !== null) {
      fs.closeSync(fd);
    }
  }
}

function readJsonFile(filePath, defaultValue, validate = () => true) {
  ensureDirForFile(filePath);
  if (!fs.existsSync(filePath)) {
    writeJsonFile(filePath, defaultValue, { backup: false });
    return cloneDefault(defaultValue);
  }

  try {
    const raw = fs.readFileSync(filePath, 'utf8');
    const parsed = JSON.parse(raw);
    if (validate(parsed)) {
      return parsed;
    }
    throw new Error('JSON shape validation failed');
  } catch (error) {
    const backupPath = `${filePath}.bak`;
    if (fs.existsSync(backupPath)) {
      try {
        const backup = JSON.parse(fs.readFileSync(backupPath, 'utf8'));
        if (validate(backup)) {
          console.warn(`[JSON-STORE] Nutze Backup fuer ${filePath}: ${error.message}`);
          return backup;
        }
      } catch (backupError) {
        console.warn(`[JSON-STORE] Backup fuer ${filePath} ist unbrauchbar: ${backupError.message}`);
      }
    }
    throw error;
  }
}

function writeJsonFile(filePath, payload, { backup = true } = {}) {
  ensureDirForFile(filePath);
  const dir = path.dirname(filePath);
  const tmpPath = path.join(
    dir,
    `.${path.basename(filePath)}.${process.pid}.${Date.now()}.tmp`
  );

  const serialized = JSON.stringify(payload, null, 2);
  fs.writeFileSync(tmpPath, serialized);
  fsyncPath(tmpPath);

  if (backup && fs.existsSync(filePath)) {
    fs.copyFileSync(filePath, `${filePath}.bak`);
  }

  fs.renameSync(tmpPath, filePath);
  try {
    fsyncPath(dir);
  } catch (error) {
    console.warn(`[JSON-STORE] Directory fsync fuer ${dir} fehlgeschlagen: ${error.message}`);
  }
}

module.exports = {
  readJsonFile,
  writeJsonFile
};
