"use strict";

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

const { PACKAGE_ROOT, LOCK_FILE, LOCK_STALE_MS } = require("./constants");

function acquireLock(lockFile = LOCK_FILE) {
  try {
    const dir = path.dirname(lockFile);
    fs.mkdirSync(dir, { recursive: true });
    const pkg = require(path.join(PACKAGE_ROOT, "package.json"));
    const lockContent = JSON.stringify(
      {
        pid: process.pid,
        timestamp: Date.now(),
        version: pkg.version,
      },
      null,
      2,
    );

    // Atomic create — O_CREAT|O_EXCL via 'wx' flag
    try {
      fs.writeFileSync(lockFile, lockContent, {
        encoding: "utf-8",
        flag: "wx",
      });
      return { acquired: true };
    } catch (wxErr) {
      if (wxErr.code !== "EEXIST") {
        return {
          acquired: false,
          reason: `Failed to acquire lock: ${wxErr.message}`,
        };
      }
    }

    // Lock file exists — check staleness
    let lockData;
    try {
      lockData = JSON.parse(fs.readFileSync(lockFile, "utf-8"));
    } catch {
      // Corrupt lock file — remove and retry once
      try {
        fs.unlinkSync(lockFile);
      } catch {
        /* best-effort */
      }
      try {
        fs.writeFileSync(lockFile, lockContent, {
          encoding: "utf-8",
          flag: "wx",
        });
        return { acquired: true };
      } catch {
        return {
          acquired: false,
          reason: "Failed to acquire lock after removing corrupt lock file",
        };
      }
    }

    if (lockData && lockData.timestamp) {
      const age = Date.now() - lockData.timestamp;
      if (age < LOCK_STALE_MS) {
        return {
          acquired: false,
          reason: `Install already in progress (pid ${lockData.pid}, started ${Math.round(age / 1000)}s ago)`,
        };
      }
      // Stale lock — unlink before creating new (avoids silent overwrite)
      try {
        fs.unlinkSync(lockFile);
      } catch {
        /* best-effort */
      }
      try {
        fs.writeFileSync(lockFile, lockContent, {
          encoding: "utf-8",
          flag: "wx",
        });
        return { acquired: true };
      } catch {
        return {
          acquired: false,
          reason: "Failed to acquire lock after removing stale lock file",
        };
      }
    }

    // Lock data without timestamp — treat as corrupt
    try {
      fs.unlinkSync(lockFile);
    } catch {
      /* best-effort */
    }
    try {
      fs.writeFileSync(lockFile, lockContent, {
        encoding: "utf-8",
        flag: "wx",
      });
      return { acquired: true };
    } catch {
      return {
        acquired: false,
        reason: "Failed to acquire lock after removing invalid lock file",
      };
    }
  } catch (err) {
    return {
      acquired: false,
      reason: `Failed to acquire lock: ${err.message}`,
    };
  }
}

function releaseLock(lockFile = LOCK_FILE) {
  try {
    if (fs.existsSync(lockFile)) {
      fs.unlinkSync(lockFile);
    }
  } catch {
    // Best-effort — no throw
  }
}

module.exports = {
  acquireLock,
  releaseLock,
};
