"use strict";
/**
 * Directory Management
 *
 * Manages the .codegraph/ directory structure for CodeGraph data.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CODEGRAPH_DIR = void 0;
exports.getCodeGraphDir = getCodeGraphDir;
exports.isInitialized = isInitialized;
exports.findNearestCodeGraphRoot = findNearestCodeGraphRoot;
exports.createDirectory = createDirectory;
exports.removeDirectory = removeDirectory;
exports.listDirectoryContents = listDirectoryContents;
exports.getDirectorySize = getDirectorySize;
exports.ensureSubdirectory = ensureSubdirectory;
exports.validateDirectory = validateDirectory;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
/**
 * CodeGraph directory name
 */
exports.CODEGRAPH_DIR = '.codegraph';
/**
 * Get the .codegraph directory path for a project
 */
function getCodeGraphDir(projectRoot) {
    return path.join(projectRoot, exports.CODEGRAPH_DIR);
}
/**
 * Check if a project has been initialized with CodeGraph
 * Requires both .codegraph/ directory AND codegraph.db to exist
 */
function isInitialized(projectRoot) {
    const codegraphDir = getCodeGraphDir(projectRoot);
    if (!fs.existsSync(codegraphDir) || !fs.statSync(codegraphDir).isDirectory()) {
        return false;
    }
    // Must have codegraph.db, not just .codegraph folder
    const dbPath = path.join(codegraphDir, 'codegraph.db');
    return fs.existsSync(dbPath);
}
/**
 * Find the nearest parent directory containing .codegraph/
 *
 * Walks up from the given path to find a CodeGraph-initialized project,
 * similar to how git finds .git/ directories.
 *
 * @param startPath - Directory to start searching from
 * @returns The project root containing .codegraph/, or null if not found
 */
function findNearestCodeGraphRoot(startPath) {
    let current = path.resolve(startPath);
    const root = path.parse(current).root;
    while (current !== root) {
        if (isInitialized(current)) {
            return current;
        }
        const parent = path.dirname(current);
        if (parent === current)
            break; // Reached filesystem root
        current = parent;
    }
    // Check root as well
    if (isInitialized(current)) {
        return current;
    }
    return null;
}
/**
 * Create the .codegraph directory structure
 * Note: Only throws if codegraph.db already exists, not just if .codegraph/ exists.
 */
function createDirectory(projectRoot) {
    const codegraphDir = getCodeGraphDir(projectRoot);
    const dbPath = path.join(codegraphDir, 'codegraph.db');
    // Only throw if CodeGraph is actually initialized (db exists)
    // .codegraph/ folder alone is fine
    if (fs.existsSync(dbPath)) {
        throw new Error(`CodeGraph already initialized in ${projectRoot}`);
    }
    // Create main directory (if it doesn't exist)
    fs.mkdirSync(codegraphDir, { recursive: true });
    // Create .gitignore inside .codegraph (if it doesn't exist)
    const gitignorePath = path.join(codegraphDir, '.gitignore');
    if (!fs.existsSync(gitignorePath)) {
        const gitignoreContent = `# CodeGraph data files — local to each machine, not for committing.
# Ignore everything in .codegraph/ except this file itself, so transient
# files (the database, daemon.pid, sockets, logs) never show up in git.
*
!.gitignore
`;
        fs.writeFileSync(gitignorePath, gitignoreContent, 'utf-8');
    }
}
/**
 * Remove the .codegraph directory
 */
function removeDirectory(projectRoot) {
    const codegraphDir = getCodeGraphDir(projectRoot);
    if (!fs.existsSync(codegraphDir)) {
        return;
    }
    // Verify .codegraph is a real directory, not a symlink pointing elsewhere
    const lstat = fs.lstatSync(codegraphDir);
    if (lstat.isSymbolicLink()) {
        // Only remove the symlink itself, never follow it for recursive delete
        fs.unlinkSync(codegraphDir);
        return;
    }
    if (!lstat.isDirectory()) {
        // Not a directory - remove the single file
        fs.unlinkSync(codegraphDir);
        return;
    }
    // Recursively remove directory
    fs.rmSync(codegraphDir, { recursive: true, force: true });
}
/**
 * Get all files in the .codegraph directory
 */
function listDirectoryContents(projectRoot) {
    const codegraphDir = getCodeGraphDir(projectRoot);
    if (!fs.existsSync(codegraphDir)) {
        return [];
    }
    const files = [];
    function walkDir(dir, prefix = '') {
        const entries = fs.readdirSync(dir, { withFileTypes: true });
        for (const entry of entries) {
            const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
            // Skip symlinks to prevent following links outside .codegraph
            if (entry.isSymbolicLink()) {
                continue;
            }
            if (entry.isDirectory()) {
                walkDir(path.join(dir, entry.name), relativePath);
            }
            else {
                files.push(relativePath);
            }
        }
    }
    walkDir(codegraphDir);
    return files;
}
/**
 * Get the total size of the .codegraph directory in bytes
 */
function getDirectorySize(projectRoot) {
    const codegraphDir = getCodeGraphDir(projectRoot);
    if (!fs.existsSync(codegraphDir)) {
        return 0;
    }
    let totalSize = 0;
    function walkDir(dir) {
        const entries = fs.readdirSync(dir, { withFileTypes: true });
        for (const entry of entries) {
            // Skip symlinks to prevent following links outside .codegraph
            if (entry.isSymbolicLink()) {
                continue;
            }
            const fullPath = path.join(dir, entry.name);
            if (entry.isDirectory()) {
                walkDir(fullPath);
            }
            else {
                const stats = fs.statSync(fullPath);
                totalSize += stats.size;
            }
        }
    }
    walkDir(codegraphDir);
    return totalSize;
}
/**
 * Ensure a subdirectory exists within .codegraph
 */
function ensureSubdirectory(projectRoot, subdirName) {
    if (subdirName.includes('..') || subdirName.includes(path.sep) || subdirName.includes('/')) {
        throw new Error(`Invalid subdirectory name: ${subdirName}`);
    }
    const subdirPath = path.join(getCodeGraphDir(projectRoot), subdirName);
    if (!fs.existsSync(subdirPath)) {
        fs.mkdirSync(subdirPath, { recursive: true });
    }
    return subdirPath;
}
/**
 * Check if the .codegraph directory has valid structure
 */
function validateDirectory(projectRoot) {
    const errors = [];
    const codegraphDir = getCodeGraphDir(projectRoot);
    if (!fs.existsSync(codegraphDir)) {
        errors.push('CodeGraph directory does not exist');
        return { valid: false, errors };
    }
    if (!fs.statSync(codegraphDir).isDirectory()) {
        errors.push('.codegraph exists but is not a directory');
        return { valid: false, errors };
    }
    // Auto-repair missing .gitignore (non-critical file)
    const gitignorePath = path.join(codegraphDir, '.gitignore');
    if (!fs.existsSync(gitignorePath)) {
        try {
            const gitignoreContent = `# CodeGraph data files — local to each machine, not for committing.\n# Ignore everything in .codegraph/ except this file itself, so transient\n# files (the database, daemon.pid, sockets, logs) never show up in git.\n*\n!.gitignore\n`;
            fs.writeFileSync(gitignorePath, gitignoreContent, 'utf-8');
        }
        catch {
            // Non-fatal: warn but don't block
            errors.push('.gitignore missing in .codegraph directory and could not be created');
        }
    }
    return {
        valid: errors.length === 0,
        errors,
    };
}
//# sourceMappingURL=directory.js.map