"use strict";
/**
 * PID File Manager
 * Issue #96: npm install CLI support
 * Issue #136: Phase 2 - Task 2.4 - Added factory functions for Issue number support
 * SF-1: SRP - Separated from daemon.ts for single responsibility
 * MF-SEC-2: TOCTOU protection with O_EXCL atomic writes
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.PidManager = void 0;
exports.createPidManager = createPidManager;
exports.createIssuePidManager = createIssuePidManager;
const fs_1 = require("fs");
const resource_resolvers_1 = require("./resource-resolvers");
/**
 * PID file manager for daemon process tracking
 */
class PidManager {
    pidFilePath;
    constructor(pidFilePath) {
        this.pidFilePath = pidFilePath;
    }
    /**
     * Check if PID file exists
     */
    exists() {
        return (0, fs_1.existsSync)(this.pidFilePath);
    }
    /**
     * Read PID from file
     * @returns PID number or null if file doesn't exist or is invalid
     */
    readPid() {
        if (!this.exists()) {
            return null;
        }
        try {
            const content = (0, fs_1.readFileSync)(this.pidFilePath, 'utf-8').trim();
            const pid = parseInt(content, 10);
            if (isNaN(pid) || pid <= 0) {
                return null;
            }
            return pid;
        }
        catch {
            return null;
        }
    }
    /**
     * Write PID to file atomically
     * MF-SEC-2: Uses O_EXCL to prevent TOCTOU race conditions
     *
     * @returns true if successful, false if file already exists
     * @throws Error for other filesystem errors
     */
    writePid(pid) {
        try {
            // O_EXCL: Fail if file already exists (atomic check-and-create)
            const fd = (0, fs_1.openSync)(this.pidFilePath, fs_1.constants.O_WRONLY | fs_1.constants.O_CREAT | fs_1.constants.O_EXCL, 0o600);
            try {
                (0, fs_1.writeSync)(fd, String(pid));
                return true;
            }
            finally {
                (0, fs_1.closeSync)(fd);
            }
        }
        catch (err) {
            if (err.code === 'EEXIST') {
                // File already exists - another process is likely running
                return false;
            }
            throw err;
        }
    }
    /**
     * Remove PID file
     */
    removePid() {
        if (this.exists()) {
            try {
                (0, fs_1.unlinkSync)(this.pidFilePath);
            }
            catch {
                // Ignore errors during cleanup
            }
        }
    }
    /**
     * Check if the process recorded in PID file is running
     * NTH-1: ISP - Lightweight process check API
     *
     * @returns true if process is running, false otherwise
     */
    isProcessRunning() {
        const pid = this.readPid();
        if (pid === null) {
            return false;
        }
        try {
            // Sending signal 0 checks if process exists without killing it
            process.kill(pid, 0);
            return true;
        }
        catch (err) {
            if (err.code === 'ESRCH') {
                // Process not found
                return false;
            }
            // Other errors (e.g., EPERM) mean process exists but we can't signal it
            throw err;
        }
    }
}
exports.PidManager = PidManager;
/**
 * Factory function to create PidManager instance
 * Issue #136: Uses PidPathResolver for path resolution
 *
 * @param issueNo - Optional issue number for worktree-specific PID
 * @returns PidManager instance
 *
 * @example
 * ```typescript
 * // Main server PID manager
 * const mainManager = createPidManager();
 *
 * // Worktree-specific PID manager
 * const issueManager = createPidManager(135);
 * ```
 */
function createPidManager(issueNo) {
    const resolver = new resource_resolvers_1.PidPathResolver();
    const pidPath = resolver.resolve(issueNo);
    return new PidManager(pidPath);
}
/**
 * Factory function to create PidManager for a specific issue
 * Issue #136: Convenience function for worktree PID management
 *
 * @param issueNo - Issue number
 * @returns PidManager instance for the specified issue
 *
 * @example
 * ```typescript
 * const manager = createIssuePidManager(135);
 * if (manager.isProcessRunning()) {
 *   console.log('Worktree server for issue #135 is running');
 * }
 * ```
 */
function createIssuePidManager(issueNo) {
    return createPidManager(issueNo);
}
