import { writeJson, projectDataDir } from '../../storage/base-store.js';
import { listSpecs, getSpec, deleteSpec } from '../../storage/spec-store.js';
import * as patternStore from '../../storage/pattern-store.js';
import * as decisionStore from '../../storage/decision-store.js';
import { moveToTrash, moveDataToTrash, countFiles, pathExists } from '../../storage/trash-store.js';
import { appendAuditEntry } from './audit-logger.js';
import { rm, mkdir, cp } from 'node:fs/promises';
import { join } from 'node:path';
/**
 * Check if any specs reference the given specId as a dependency.
 * Returns a list of dependent spec IDs for cascade awareness.
 */
export async function checkSpecDependencies(projectId, specId) {
    const specs = await listSpecs(projectId);
    const dependents = [];
    for (const s of specs) {
        if (s.id === specId) {
            continue;
        }
        const deps = s.dependencies;
        if (Array.isArray(deps) && deps.includes(specId)) {
            dependents.push(s.id);
        }
    }
    return dependents;
}
/**
 * Preview what would be deleted for a spec.
 */
export async function previewDeleteSpec(projectId, specIds) {
    const warnings = [];
    let itemsAffected = 0;
    for (const specId of specIds) {
        const spec = await getSpec(projectId, specId);
        if (!spec) {
            warnings.push(`Spec "${specId}" not found.`);
            continue;
        }
        itemsAffected += 1;
        const deps = await checkSpecDependencies(projectId, specId);
        if (deps.length > 0) {
            warnings.push(`Spec "${specId}" is referenced by: ${deps.join(', ')}`);
        }
    }
    return { success: true, action: 'preview', itemsAffected, warnings };
}
/**
 * Execute spec deletion (soft or hard).
 */
export async function executeDeleteSpec(projectId, specIds, force) {
    const warnings = [];
    const action = force ? 'hard_delete' : 'soft_delete';
    // Validate all specs exist first (atomic check)
    for (const specId of specIds) {
        const spec = await getSpec(projectId, specId);
        if (!spec) {
            return {
                success: false,
                action,
                itemsAffected: 0,
                warnings: [`Spec "${specId}" not found. No items were deleted (atomic rollback).`],
            };
        }
    }
    // Check dependencies for all
    for (const specId of specIds) {
        const deps = await checkSpecDependencies(projectId, specId);
        if (deps.length > 0) {
            warnings.push(`Spec "${specId}" is referenced by: ${deps.join(', ')}`);
        }
    }
    let lastAuditId;
    // Execute deletion for each spec
    for (const specId of specIds) {
        const specDir = join(projectDataDir(projectId), 'specs', specId);
        const dirExists = await pathExists(specDir);
        if (!force && dirExists) {
            await moveToTrash(projectId, 'spec', specId, specDir, { specId });
        }
        else if (dirExists) {
            await rm(specDir, { recursive: true, force: true });
        }
        await deleteSpec(projectId, specId);
        lastAuditId = await appendAuditEntry(projectId, action, 'spec', specId, { specIds });
    }
    return {
        success: true,
        action,
        itemsAffected: specIds.length,
        warnings,
        auditId: lastAuditId,
    };
}
/**
 * Preview what would be deleted for a project.
 */
export async function previewDeleteProject(projectId) {
    const dataDir = projectDataDir(projectId);
    const exists = await pathExists(dataDir);
    if (!exists) {
        return {
            success: false,
            action: 'preview',
            itemsAffected: 0,
            warnings: ['Project data directory not found.'],
        };
    }
    const fileCount = await countFiles(dataDir);
    return {
        success: true,
        action: 'preview',
        itemsAffected: fileCount,
        warnings: [`This will delete ${String(fileCount)} files in ${dataDir}.`],
    };
}
/**
 * Execute project deletion (soft or hard).
 */
export async function executeDeleteProject(projectId, force) {
    const dataDir = projectDataDir(projectId);
    const exists = await pathExists(dataDir);
    if (!exists) {
        return {
            success: false,
            action: force ? 'hard_delete' : 'soft_delete',
            itemsAffected: 0,
            warnings: ['Project data directory not found.'],
        };
    }
    const fileCount = await countFiles(dataDir);
    const action = force ? 'hard_delete' : 'soft_delete';
    if (!force) {
        // For soft delete of a project, move the entire directory
        // Use a global trash since project dir itself is being deleted
        const globalTrashDir = 'data/projects/.trash';
        const timestamp = Date.now();
        const trashSubdir = `${String(timestamp)}-project-${projectId}`;
        const destPath = join(globalTrashDir, trashSubdir);
        await mkdir(destPath, { recursive: true });
        await cp(dataDir, destPath, { recursive: true });
        await rm(dataDir, { recursive: true, force: true });
    }
    else {
        await rm(dataDir, { recursive: true, force: true });
    }
    const auditId = force
        ? undefined
        : await appendAuditEntry(projectId, action, 'project', projectId, { fileCount });
    return {
        success: true,
        action,
        itemsAffected: fileCount,
        warnings: [],
        auditId,
    };
}
/**
 * Execute pattern deletion (soft or hard).
 */
export async function executeDeletePattern(projectId, patternIds, force) {
    const action = force ? 'hard_delete' : 'soft_delete';
    // Validate all patterns exist first (atomic)
    for (const patternId of patternIds) {
        const pattern = await patternStore.getPattern(projectId, patternId);
        if (!pattern) {
            return {
                success: false,
                action,
                itemsAffected: 0,
                warnings: [`Pattern "${patternId}" not found. No items were deleted (atomic rollback).`],
            };
        }
    }
    let lastAuditId;
    for (const patternId of patternIds) {
        const pattern = await patternStore.getPattern(projectId, patternId);
        if (!force && pattern) {
            await moveDataToTrash(projectId, 'pattern', patternId, pattern, { patternId });
        }
        await patternStore.deletePattern(projectId, patternId);
        lastAuditId = await appendAuditEntry(projectId, action, 'pattern', patternId, { patternIds });
    }
    return {
        success: true,
        action,
        itemsAffected: patternIds.length,
        warnings: [],
        auditId: lastAuditId,
    };
}
/**
 * Preview what would be deleted for patterns.
 */
export async function previewDeletePattern(projectId, patternIds) {
    const warnings = [];
    let itemsAffected = 0;
    for (const patternId of patternIds) {
        const pattern = await patternStore.getPattern(projectId, patternId);
        if (!pattern) {
            warnings.push(`Pattern "${patternId}" not found.`);
            continue;
        }
        itemsAffected += 1;
    }
    return { success: true, action: 'preview', itemsAffected, warnings };
}
/**
 * Execute decision deletion.
 */
export async function executeDeleteDecision(projectId, decisionIds, force) {
    const action = force ? 'hard_delete' : 'soft_delete';
    const decisions = await decisionStore.getDecisions(projectId);
    // Validate all decisions exist first (atomic)
    for (const decisionId of decisionIds) {
        const decision = decisions.find((d) => d.id === decisionId);
        if (!decision) {
            return {
                success: false,
                action,
                itemsAffected: 0,
                warnings: [`Decision "${decisionId}" not found. No items were deleted (atomic rollback).`],
            };
        }
    }
    let lastAuditId;
    for (const decisionId of decisionIds) {
        const decision = decisions.find((d) => d.id === decisionId);
        if (!force && decision) {
            await moveDataToTrash(projectId, 'decision', decisionId, decision, { decisionId });
        }
        // Remove from decisions array and save
        const allDecisions = await decisionStore.getDecisions(projectId);
        const filtered = allDecisions.filter((d) => d.id !== decisionId);
        await writeJson(`${projectDataDir(projectId)}/decisions.json`, {
            decisions: filtered,
            lastUpdated: new Date().toISOString(),
        });
        lastAuditId = await appendAuditEntry(projectId, action, 'decision', decisionId, {
            decisionIds,
        });
    }
    return {
        success: true,
        action,
        itemsAffected: decisionIds.length,
        warnings: [],
        auditId: lastAuditId,
    };
}
/**
 * Preview what would be deleted for decisions.
 */
export async function previewDeleteDecision(projectId, decisionIds) {
    const decisions = await decisionStore.getDecisions(projectId);
    const warnings = [];
    let itemsAffected = 0;
    for (const decisionId of decisionIds) {
        const decision = decisions.find((d) => d.id === decisionId);
        if (!decision) {
            warnings.push(`Decision "${decisionId}" not found.`);
            continue;
        }
        itemsAffected += 1;
    }
    return { success: true, action: 'preview', itemsAffected, warnings };
}
//# sourceMappingURL=core.js.map