import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { v4 as uuidv4 } from "uuid";
import { ConflictDetector } from "./conflict-detector.js";
import { StackDiffVisualizer } from "./stack-diff.js";
import { ResolutionEngine } from "./resolution-engine.js";
import { logger } from "../monitoring/logger.js";
class UnifiedMergeResolver {
  conflictDetector;
  diffVisualizer;
  resolutionEngine;
  activeSessions = /* @__PURE__ */ new Map();
  rollbackSnapshots = /* @__PURE__ */ new Map();
  statistics = {
    totalConflicts: 0,
    resolvedConflicts: 0,
    averageResolutionTime: 0,
    successRate: 0,
    rollbackCount: 0
  };
  constructor() {
    this.conflictDetector = new ConflictDetector();
    this.diffVisualizer = new StackDiffVisualizer();
    this.resolutionEngine = new ResolutionEngine();
    logger.debug("UnifiedMergeResolver initialized");
  }
  /**
   * Start a new merge session with automatic conflict detection
   */
  async startMergeSession(stack1, stack2, options) {
    const sessionId = `unified-merge-${Date.now()}-${uuidv4().substring(0, 8)}`;
    const conflicts = this.conflictDetector.detectConflicts(stack1, stack2);
    let rollbackPoint;
    if (options?.preserveRollback !== false) {
      rollbackPoint = this.createRollbackSnapshot(sessionId, stack1, stack2);
    }
    const session = {
      sessionId,
      stack1,
      stack2,
      conflicts,
      status: "analyzing",
      rollbackPoint,
      startedAt: Date.now(),
      metadata: {
        totalFrames: stack1.frames.length + stack2.frames.length,
        conflictCount: conflicts.length,
        resolvedCount: 0
      }
    };
    this.activeSessions.set(sessionId, session);
    this.statistics.totalConflicts += conflicts.length;
    logger.info(`Merge session started: ${sessionId}`, {
      stack1Id: stack1.id,
      stack2Id: stack2.id,
      conflictCount: conflicts.length
    });
    if (options?.autoResolve && conflicts.length > 0 && options.context) {
      const defaultStrategy = options.strategy || "ai_suggest";
      await this.resolveConflicts(sessionId, defaultStrategy, options.context);
    }
    return sessionId;
  }
  /**
   * Generate a preview of the merge result
   */
  async generatePreview(sessionId, strategy) {
    const session = this.activeSessions.get(sessionId);
    if (!session) {
      throw new Error(`Session not found: ${sessionId}`);
    }
    const preview = this.diffVisualizer.generateMergePreview(
      session.stack1,
      session.stack2,
      strategy
    );
    session.preview = preview;
    session.status = "preview";
    session.metadata.strategyUsed = strategy;
    this.activeSessions.set(sessionId, session);
    logger.info(`Preview generated for session: ${sessionId}`, {
      mergedFrameCount: preview.mergedFrames.length,
      estimatedSuccess: preview.estimatedSuccess
    });
    return preview;
  }
  /**
   * Resolve conflicts using the specified strategy
   */
  async resolveConflicts(sessionId, strategy, context) {
    const session = this.activeSessions.get(sessionId);
    if (!session) {
      throw new Error(`Session not found: ${sessionId}`);
    }
    session.status = "resolving";
    try {
      const result = await this.resolutionEngine.resolveConflicts(
        session.stack1,
        session.stack2,
        strategy,
        context
      );
      session.resolution = result.resolution;
      session.status = result.success ? "completed" : "failed";
      session.completedAt = Date.now();
      session.metadata.resolvedCount = session.conflicts.filter(
        (c) => c.resolution !== void 0
      ).length;
      session.metadata.strategyUsed = strategy;
      this.activeSessions.set(sessionId, session);
      if (result.success) {
        this.statistics.resolvedConflicts += session.metadata.resolvedCount;
        this.updateSuccessRate();
        this.updateAverageResolutionTime(session);
      }
      logger.info(`Conflicts resolved for session: ${sessionId}`, {
        success: result.success,
        strategy,
        resolvedCount: session.metadata.resolvedCount
      });
      return result;
    } catch (error) {
      session.status = "failed";
      this.activeSessions.set(sessionId, session);
      logger.error(
        `Failed to resolve conflicts for session: ${sessionId}`,
        error
      );
      throw error;
    }
  }
  /**
   * Rollback a merge to its original state
   */
  async rollback(sessionId) {
    const session = this.activeSessions.get(sessionId);
    if (!session || !session.rollbackPoint) {
      logger.warn(`Cannot rollback session: ${sessionId} - no rollback point`);
      return false;
    }
    const snapshot = this.rollbackSnapshots.get(session.rollbackPoint);
    if (!snapshot) {
      logger.error(`Rollback snapshot not found: ${session.rollbackPoint}`);
      return false;
    }
    session.stack1 = snapshot.stack1;
    session.stack2 = snapshot.stack2;
    session.status = "rolled_back";
    session.resolution = void 0;
    session.conflicts = this.conflictDetector.detectConflicts(
      snapshot.stack1,
      snapshot.stack2
    );
    session.metadata.resolvedCount = 0;
    this.activeSessions.set(sessionId, session);
    this.statistics.rollbackCount++;
    logger.info(`Session rolled back: ${sessionId}`);
    return true;
  }
  /**
   * Get merge session details
   */
  getSession(sessionId) {
    return this.activeSessions.get(sessionId);
  }
  /**
   * List all active merge sessions
   */
  listActiveSessions() {
    return Array.from(this.activeSessions.values()).filter(
      (s) => s.status !== "completed" && s.status !== "rolled_back" && s.status !== "failed"
    );
  }
  /**
   * Get merge statistics
   */
  getStatistics() {
    return { ...this.statistics };
  }
  /**
   * Analyze parallel solutions across stacks
   */
  analyzeParallelSolutions(frames) {
    const solutions = this.conflictDetector.analyzeParallelSolutions(frames);
    const recommendations = [];
    if (solutions.length > 1) {
      const grouped = /* @__PURE__ */ new Map();
      for (const sol of solutions) {
        const key = sol.approach.toLowerCase();
        if (!grouped.has(key)) {
          grouped.set(key, []);
        }
        grouped.get(key).push(sol);
      }
      for (const [approach, group] of grouped) {
        if (group.length > 1) {
          const avgEffectiveness = group.reduce((sum, s) => sum + (s.effectiveness || 0), 0) / group.length;
          recommendations.push(
            `${group.length} parallel solutions using "${approach}" approach (avg effectiveness: ${(avgEffectiveness * 100).toFixed(1)}%)`
          );
        }
      }
      const best = solutions.reduce(
        (a, b) => (a.effectiveness || 0) > (b.effectiveness || 0) ? a : b,
        solutions[0]
      );
      if (best && best.effectiveness && best.effectiveness > 0.7) {
        recommendations.push(
          `Recommended: Use solution from frame "${best.frameId}" (${(best.effectiveness * 100).toFixed(1)}% effectiveness)`
        );
      }
    }
    return {
      solutions: solutions.map((s) => ({
        frameId: s.frameId,
        approach: s.approach,
        effectiveness: s.effectiveness || 0
      })),
      recommendations
    };
  }
  /**
   * Create a visual diff between two stacks
   */
  createVisualDiff(baseFrame, stack1, stack2) {
    const diff = this.diffVisualizer.visualizeDivergence(
      baseFrame,
      stack1,
      stack2
    );
    const conflicts = this.conflictDetector.detectConflicts(stack1, stack2);
    return {
      nodes: diff.nodes.map((n) => ({
        id: n.id,
        type: n.type,
        depth: n.frame?.depth
      })),
      edges: diff.edges.map((e) => ({
        source: e.source,
        target: e.target,
        type: e.type
      })),
      conflicts: conflicts.map((c) => ({
        frameId1: c.frameId1,
        frameId2: c.frameId2,
        severity: c.severity
      }))
    };
  }
  /**
   * Close a merge session and clean up resources
   */
  closeSession(sessionId) {
    const session = this.activeSessions.get(sessionId);
    if (session) {
      if (session.rollbackPoint) {
        this.rollbackSnapshots.delete(session.rollbackPoint);
      }
      this.activeSessions.delete(sessionId);
      logger.debug(`Session closed: ${sessionId}`);
    }
  }
  // Private helpers
  createRollbackSnapshot(sessionId, stack1, stack2) {
    const snapshotId = `rollback-${sessionId}`;
    this.rollbackSnapshots.set(snapshotId, {
      stack1: this.deepCloneStack(stack1),
      stack2: this.deepCloneStack(stack2)
    });
    return snapshotId;
  }
  deepCloneStack(stack) {
    return {
      ...stack,
      frames: stack.frames.map((f) => ({ ...f })),
      events: stack.events.map((e) => ({ ...e }))
    };
  }
  updateSuccessRate() {
    if (this.statistics.totalConflicts > 0) {
      this.statistics.successRate = this.statistics.resolvedConflicts / this.statistics.totalConflicts;
    }
  }
  updateAverageResolutionTime(session) {
    if (session.completedAt && session.startedAt) {
      const duration = session.completedAt - session.startedAt;
      const completedSessions = Array.from(this.activeSessions.values()).filter(
        (s) => s.completedAt
      ).length;
      if (completedSessions === 1) {
        this.statistics.averageResolutionTime = duration;
      } else {
        this.statistics.averageResolutionTime = (this.statistics.averageResolutionTime * (completedSessions - 1) + duration) / completedSessions;
      }
    }
  }
}
export {
  UnifiedMergeResolver
};
//# sourceMappingURL=unified-merge-resolver.js.map
