/*
 * Copyright 2026, Jaime Terrats.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { existsSync, readFileSync, writeFileSync, renameSync, unlinkSync } from 'node:fs';
import { join, basename, resolve } from 'node:path';
import { homedir, tmpdir } from 'node:os';
import { ensureDir } from './file-writer.js';
let registryDirOverride;
const MAX_ENTRIES = 50;
export function setRegistryDir(dir) {
    registryDirOverride = dir;
}
function getRegistryDir() {
    return registryDirOverride ?? join(homedir(), '.setup-agents');
}
function getRegistryPath() {
    return join(getRegistryDir(), 'workspaces.json');
}
function readRegistry() {
    const registryPath = getRegistryPath();
    if (!existsSync(registryPath)) {
        return { workspaces: [] };
    }
    try {
        const content = readFileSync(registryPath, 'utf8');
        return JSON.parse(content);
    }
    catch {
        return { workspaces: [] };
    }
}
function writeRegistry(data) {
    const dir = getRegistryDir();
    ensureDir(dir);
    const registryPath = getRegistryPath();
    const tempPath = `${registryPath}.${Date.now()}.tmp`;
    writeFileSync(tempPath, JSON.stringify(data, null, 2) + '\n', 'utf8');
    try {
        renameSync(tempPath, registryPath);
    }
    catch (err) {
        try {
            unlinkSync(tempPath);
        }
        catch {
            /* best-effort cleanup */
        }
        throw err;
    }
}
function isConfigured(workspacePath) {
    return existsSync(join(workspacePath, '.setup-agents', 'config.json'));
}
function deriveWorkspaceName(workspacePath) {
    return basename(workspacePath) || workspacePath;
}
const TEMP_PATH_PATTERNS = ['/tmp/', '/private/tmp/', '/var/folders/'];
function isTempPath(p) {
    if (registryDirOverride)
        return false;
    const td = tmpdir();
    return TEMP_PATH_PATTERNS.some((pattern) => p.includes(pattern)) || p.startsWith(td);
}
/**
 * Returns all registered workspaces sorted by lastAccessed (most recent first).
 * Filters out entries whose paths no longer exist or reside in temp directories
 * unless includeTempPaths is set.
 */
export function listWorkspaces(opts) {
    const data = readRegistry();
    const includeTmp = opts?.includeTempPaths ?? false;
    const valid = data.workspaces.filter((w) => existsSync(w.path) && (includeTmp || !isTempPath(w.path)));
    if (valid.length < data.workspaces.length) {
        writeRegistry({ workspaces: valid });
    }
    return valid.sort((a, b) => new Date(b.lastAccessed).getTime() - new Date(a.lastAccessed).getTime());
}
/**
 * Registers a workspace path. If already registered, updates lastAccessed.
 * Rejects temp directory paths. Enforces a max of 50 entries via LRU eviction.
 */
export function registerWorkspace(workspacePath) {
    const resolved = resolve(workspacePath);
    if (isTempPath(resolved)) {
        return {
            path: resolved,
            name: deriveWorkspaceName(resolved),
            lastAccessed: new Date().toISOString(),
            configured: false,
        };
    }
    const data = readRegistry();
    const existing = data.workspaces.find((w) => w.path === resolved);
    const now = new Date().toISOString();
    if (existing) {
        existing.lastAccessed = now;
        existing.configured = isConfigured(resolved);
        existing.name = deriveWorkspaceName(resolved);
    }
    else {
        const entry = {
            path: resolved,
            name: deriveWorkspaceName(resolved),
            lastAccessed: now,
            configured: isConfigured(resolved),
        };
        data.workspaces.push(entry);
    }
    // LRU eviction: keep only the most recent MAX_ENTRIES
    if (data.workspaces.length > MAX_ENTRIES) {
        data.workspaces.sort((a, b) => new Date(b.lastAccessed).getTime() - new Date(a.lastAccessed).getTime());
        data.workspaces = data.workspaces.slice(0, MAX_ENTRIES);
    }
    writeRegistry(data);
    return data.workspaces.find((w) => w.path === resolved);
}
/**
 * Removes a workspace from the registry by path.
 * Returns true if the workspace was found and removed.
 */
export function removeWorkspace(workspacePath) {
    const resolved = resolve(workspacePath);
    const data = readRegistry();
    const initialLength = data.workspaces.length;
    data.workspaces = data.workspaces.filter((w) => w.path !== resolved);
    if (data.workspaces.length === initialLength) {
        return false;
    }
    writeRegistry(data);
    return true;
}
/**
 * Updates the lastAccessed timestamp for a workspace.
 * If the workspace is not registered, it auto-registers it.
 */
export function touchWorkspace(workspacePath) {
    return registerWorkspace(workspacePath);
}
//# sourceMappingURL=workspace-registry.js.map