/**
 * Sync Interceptor
 *
 * Central control point for all sync operations. Wraps sync operations with
 * permission checks and audit logging. Implements the interceptor pattern to
 * ensure consistent enforcement across all platforms (GitHub, JIRA, ADO).
 *
 * Pattern:
 *   Request → Interceptor → Permission Check → Execute/Deny → Log → Response
 *
 * @module core/sync/sync-interceptor
 */
import { consoleLogger } from '../../utils/logger.js';
/**
 * Permission denied error
 */
export class PermissionDeniedError extends Error {
    constructor(permission, platform, operation) {
        super(`Permission denied: ${permission.reason}`);
        this.permission = permission;
        this.platform = platform;
        this.operation = operation;
        this.name = 'PermissionDeniedError';
    }
}
/**
 * SyncInterceptor - Central control point for sync operations
 *
 * All sync operations must pass through this interceptor to ensure:
 * 1. Permissions are checked before execution
 * 2. All attempts are logged (success, denied, error)
 * 3. Consistent behavior across all platforms
 *
 * Usage:
 * ```typescript
 * const result = await interceptor.intercept(
 *   'github',
 *   'upsert-internal',
 *   'FS-001',
 *   'internal',
 *   () => this.githubClient.createIssue(item)
 * );
 *
 * if (result.allowed) {
 *   return result.result;
 * } else {
 *   console.log(`Denied: ${result.permission.reason}`);
 * }
 * ```
 */
export class SyncInterceptor {
    constructor(options) {
        this.permissionEnforcer = options.permissionEnforcer;
        this.auditLogger = options.auditLogger;
        this.logger = options.logger ?? consoleLogger;
        this.strictMode = options.strictMode ?? false;
    }
    /**
     * Intercept a sync operation
     *
     * Checks permissions, executes if allowed, logs the result.
     *
     * @param platform - Target platform (github, jira, ado)
     * @param operation - Operation type (read, update-status, upsert-internal, upsert-external)
     * @param itemId - Item ID being operated on
     * @param origin - Item origin (internal or external)
     * @param execute - Function to execute if permitted
     * @returns Interceptor result with operation outcome
     */
    async intercept(platform, operation, itemId, origin, execute) {
        const startTime = Date.now();
        // Check permission
        const permission = await this.permissionEnforcer.checkAndLog(platform, operation, itemId, origin);
        // Handle denial
        if (!permission.allowed) {
            const durationMs = Date.now() - startTime;
            await this.auditLogger.logDenied(platform, operation, itemId, permission.reason);
            this.logger.debug(`[SyncInterceptor] Denied: ${platform}/${operation} for ${itemId} - ${permission.reason}`);
            // Strict mode throws instead of returning
            if (this.strictMode) {
                throw new PermissionDeniedError(permission, platform, operation);
            }
            return {
                allowed: false,
                result: null,
                permission,
                durationMs,
            };
        }
        // Execute the operation
        try {
            const result = await execute();
            const durationMs = Date.now() - startTime;
            await this.auditLogger.logSuccess(platform, operation, itemId, durationMs);
            this.logger.debug(`[SyncInterceptor] Success: ${platform}/${operation} for ${itemId} (${durationMs}ms)`);
            return {
                allowed: true,
                result,
                permission,
                durationMs,
            };
        }
        catch (error) {
            const durationMs = Date.now() - startTime;
            const err = error instanceof Error ? error : new Error(String(error));
            await this.auditLogger.logError(platform, operation, itemId, err);
            this.logger.debug(`[SyncInterceptor] Error: ${platform}/${operation} for ${itemId} - ${err.message}`);
            return {
                allowed: true, // Was allowed, but failed
                result: null,
                permission,
                durationMs,
                error: err,
            };
        }
    }
    /**
     * Intercept with automatic origin detection
     */
    async interceptAuto(platform, operation, itemId, execute) {
        return this.intercept(platform, operation, itemId, this.detectOrigin(itemId), execute);
    }
    /**
     * Intercept a read operation (always allowed)
     */
    async interceptRead(platform, itemId, execute) {
        return this.intercept(platform, 'read', itemId, 'internal', execute);
    }
    /**
     * Intercept a status update operation
     */
    async interceptStatusUpdate(platform, itemId, execute) {
        return this.intercept(platform, 'update-status', itemId, this.detectOrigin(itemId), execute);
    }
    /**
     * Intercept an upsert operation - determines operation type from item origin
     */
    async interceptUpsert(platform, itemId, execute) {
        const origin = this.detectOrigin(itemId);
        const operation = origin === 'external' ? 'upsert-external' : 'upsert-internal';
        return this.intercept(platform, operation, itemId, origin, execute);
    }
    /**
     * Check if an operation would be allowed (without executing)
     */
    wouldAllow(platform, operation, itemId) {
        return this.permissionEnforcer.checkPermission(platform, operation, itemId, this.detectOrigin(itemId)).allowed;
    }
    /**
     * Get permission summary
     */
    getPermissionsSummary() {
        return this.permissionEnforcer.getPermissionsSummary().summary;
    }
    /**
     * Detect item origin from ID - external items end with 'E' or contain '-E-'
     */
    detectOrigin(itemId) {
        return (itemId.endsWith('E') || itemId.includes('-E-')) ? 'external' : 'internal';
    }
}
/**
 * Create a SyncInterceptor with default configuration
 *
 * @param permissionEnforcer - Permission enforcer instance
 * @param specweavePath - Path to .specweave directory
 * @param logger - Optional logger
 */
export async function createSyncInterceptor(permissionEnforcer, specweavePath, logger) {
    const { SyncAuditLogger: AuditLoggerClass } = await import('./sync-audit-logger.js');
    const auditLogger = new AuditLoggerClass({
        specweavePath,
        logger,
    });
    return new SyncInterceptor({
        permissionEnforcer,
        auditLogger,
        logger,
    });
}
//# sourceMappingURL=sync-interceptor.js.map