import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { execSync } from "child_process";
import { logger } from "../../../core/monitoring/logger.js";
class GitWorkflowError extends Error {
  constructor(message, context) {
    super(message);
    this.context = context;
    this.name = "GitWorkflowError";
  }
}
class GitWorkflowManager {
  config;
  agentBranches = /* @__PURE__ */ new Map();
  baselineBranch;
  mainBranch;
  constructor(config) {
    this.config = {
      enableGitWorkflow: true,
      branchStrategy: "agent",
      autoCommit: true,
      commitFrequency: 5,
      mergStrategy: "squash",
      requirePR: false,
      ...config
    };
    try {
      this.baselineBranch = this.getCurrentBranch();
      this.mainBranch = this.getMainBranch();
    } catch (error) {
      logger.warn("Git not initialized, workflow features disabled");
      this.config.enableGitWorkflow = false;
    }
  }
  /**
   * Initialize git workflow for an agent
   */
  async initializeAgentWorkflow(agent, task) {
    if (!this.config.enableGitWorkflow) return;
    let branchName = this.generateBranchName(agent, task);
    try {
      if (this.branchExists(branchName)) {
        const existingHasChanges = this.branchHasUnmergedChanges(branchName);
        if (existingHasChanges) {
          const timestamp = Date.now();
          branchName = `${branchName}-${timestamp}`;
          logger.info(
            `Branch already exists with changes, creating unique branch: ${branchName}`
          );
          this.createBranch(branchName);
        } else {
          logger.info(
            `Reusing existing branch for agent ${agent.role}: ${branchName}`
          );
          this.checkoutBranch(branchName);
        }
      } else {
        this.createBranch(branchName);
        logger.info(
          `Created git branch for agent ${agent.role}: ${branchName}`
        );
      }
      this.agentBranches.set(agent.id, branchName);
      if (this.config.autoCommit) {
        this.scheduleAutoCommit(agent, task);
      }
    } catch (error) {
      logger.error(
        `Failed to initialize git workflow for agent ${agent.role}`,
        error
      );
    }
  }
  /**
   * Commit agent work
   */
  async commitAgentWork(agent, task, message) {
    if (!this.config.enableGitWorkflow) return;
    const branchName = this.agentBranches.get(agent.id);
    if (!branchName) {
      logger.warn(`No branch found for agent ${agent.id}`);
      return;
    }
    try {
      this.checkoutBranch(branchName);
      const hasChanges = this.hasUncommittedChanges();
      if (!hasChanges) {
        logger.debug(`No changes to commit for agent ${agent.role}`);
        return;
      }
      execSync("git add -A", { encoding: "utf8" });
      const commitMessage = message || this.generateCommitMessage(agent, task);
      execSync(`git commit -m "${commitMessage}"`, { encoding: "utf8" });
      logger.info(`Agent ${agent.role} committed: ${commitMessage}`);
      if (this.hasRemote()) {
        try {
          execSync(`git push origin ${branchName}`, { encoding: "utf8" });
          logger.info(`Pushed branch ${branchName} to remote`);
        } catch (error) {
          logger.warn(`Could not push to remote: ${error}`);
        }
      }
    } catch (error) {
      logger.error(`Failed to commit agent work`, error);
    }
  }
  /**
   * Merge agent work back to baseline
   */
  async mergeAgentWork(agent, task) {
    if (!this.config.enableGitWorkflow) return;
    const branchName = this.agentBranches.get(agent.id);
    if (!branchName) {
      logger.warn(`No branch found for agent ${agent.id}`);
      return;
    }
    try {
      this.checkoutBranch(this.baselineBranch);
      if (this.config.requirePR) {
        await this.createPullRequest(agent, task, branchName);
      } else {
        this.mergeBranch(branchName);
        logger.info(`Merged agent ${agent.role} work from ${branchName}`);
      }
      this.deleteBranch(branchName);
      this.agentBranches.delete(agent.id);
    } catch (error) {
      logger.error(`Failed to merge agent work`, error);
    }
  }
  /**
   * Coordinate merges between multiple agents
   */
  async coordinateMerges(agents) {
    if (!this.config.enableGitWorkflow) return;
    logger.info("Coordinating merges from all agents");
    const integrationBranch = `swarm-integration-${Date.now()}`;
    this.createBranch(integrationBranch);
    for (const agent of agents) {
      const branchName = this.agentBranches.get(agent.id);
      if (branchName && this.branchExists(branchName)) {
        try {
          this.mergeBranch(branchName);
          logger.info(`Integrated ${agent.role} work`);
        } catch (error) {
          logger.error(`Failed to integrate ${agent.role} work: ${error}`);
        }
      }
    }
    const testsPass = await this.runIntegrationTests();
    if (testsPass) {
      this.checkoutBranch(this.baselineBranch);
      this.mergeBranch(integrationBranch);
      logger.info("Successfully integrated all agent work");
    } else {
      logger.warn(
        "Integration tests failed, keeping changes in branch: " + integrationBranch
      );
    }
  }
  /**
   * Handle merge conflicts
   */
  async resolveConflicts(agent) {
    const conflicts = this.getConflictedFiles();
    if (conflicts.length === 0) return;
    logger.warn(
      `Agent ${agent.role} encountering merge conflicts: ${conflicts.join(", ")}`
    );
    for (const file of conflicts) {
      try {
        if (this.isAgentFile(file, agent)) {
          execSync(`git checkout --ours ${file}`, { encoding: "utf8" });
          execSync(`git add ${file}`, { encoding: "utf8" });
        } else {
          execSync(`git checkout --theirs ${file}`, { encoding: "utf8" });
          execSync(`git add ${file}`, { encoding: "utf8" });
        }
      } catch (error) {
        logger.error(`Could not auto-resolve conflict in ${file}`);
      }
    }
    const remainingConflicts = this.getConflictedFiles();
    if (remainingConflicts.length === 0) {
      execSync("git commit --no-edit", { encoding: "utf8" });
      logger.info("All conflicts resolved automatically");
    } else {
      logger.error(
        `Manual intervention needed for: ${remainingConflicts.join(", ")}`
      );
    }
  }
  // Private helper methods
  getCurrentBranch() {
    try {
      return execSync("git rev-parse --abbrev-ref HEAD", { encoding: "utf8" }).trim();
    } catch (error) {
      logger.warn("Failed to get current branch", error);
      return "main";
    }
    return execSync("git rev-parse --abbrev-ref HEAD", {
      encoding: "utf8"
    }).trim();
  }
  getMainBranch() {
    try {
      const branches = execSync("git branch -r", { encoding: "utf8" });
      if (branches.includes("origin/main")) return "main";
      if (branches.includes("origin/master")) return "master";
    } catch (error) {
      logger.debug("Could not detect main branch from remotes", error);
    }
    return this.getCurrentBranch();
  }
  generateBranchName(agent, task) {
    const sanitizedTitle = task.title.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").substring(0, 30);
    switch (this.config.branchStrategy) {
      case "feature":
        return `feature/${sanitizedTitle}`;
      case "task":
        return `task/${task.id}`;
      case "agent":
      default:
        return `swarm/${agent.role}-${sanitizedTitle}`;
    }
  }
  createBranch(branchName) {
    try {
      try {
        const currentBranch = execSync("git branch --show-current", { encoding: "utf8" }).trim();
        if (currentBranch === branchName) {
          try {
            execSync("git checkout main", { encoding: "utf8" });
          } catch {
            execSync("git checkout master", { encoding: "utf8" });
          }
        }
        try {
          const worktrees = execSync("git worktree list --porcelain", { encoding: "utf8" });
          const lines = worktrees.split("\n");
          for (let i = 0; i < lines.length; i++) {
            if (lines[i].startsWith("branch ") && lines[i].includes(branchName)) {
              const worktreetPath = lines[i - 1].replace("worktree ", "");
              execSync(`git worktree remove --force "${worktreetPath}"`, { encoding: "utf8" });
              logger.info(`Removed worktree at ${worktreetPath} for branch ${branchName}`);
            }
          }
        } catch (worktreeError) {
          logger.warn("Failed to check/remove worktrees", worktreeError);
        }
        execSync(`git branch -D ${branchName}`, { encoding: "utf8" });
        logger.info(`Deleted existing branch ${branchName} for fresh start`);
      } catch {
      }
      execSync(`git checkout -b ${branchName}`, { encoding: "utf8" });
    } catch (error) {
      logger.error(`Failed to create branch ${branchName}`, error);
      throw new GitWorkflowError(`Failed to create branch: ${branchName}`, { branchName });
    }
  }
  checkoutBranch(branchName) {
    try {
      execSync(`git checkout ${branchName}`, { encoding: "utf8" });
    } catch (error) {
      logger.error(`Failed to checkout branch ${branchName}`, error);
      throw new GitWorkflowError(`Failed to checkout branch: ${branchName}`, { branchName });
    }
  }
  branchExists(branchName) {
    try {
      execSync(`git rev-parse --verify ${branchName}`, {
        encoding: "utf8",
        stdio: "pipe"
      });
      return true;
    } catch {
      return false;
    }
  }
  deleteBranch(branchName) {
    try {
      execSync(`git branch -d ${branchName}`, { encoding: "utf8" });
    } catch (error) {
      execSync(`git branch -D ${branchName}`, { encoding: "utf8" });
    }
  }
  mergeBranch(branchName) {
    const strategy = this.config.mergStrategy;
    switch (strategy) {
      case "squash":
        execSync(`git merge --squash ${branchName}`, { encoding: "utf8" });
        execSync('git commit -m "Squashed agent changes"', {
          encoding: "utf8"
        });
        break;
      case "rebase":
        execSync(`git rebase ${branchName}`, { encoding: "utf8" });
        break;
      case "merge":
      default:
        execSync(`git merge ${branchName}`, { encoding: "utf8" });
        break;
    }
  }
  hasUncommittedChanges() {
    try {
      const status = execSync("git status --porcelain", { encoding: "utf8" });
      return status.trim().length > 0;
    } catch (error) {
      logger.warn("Failed to check git status", error);
      return false;
    }
  }
  hasRemote() {
    try {
      execSync("git remote get-url origin", { encoding: "utf8" });
      return true;
    } catch {
      return false;
    }
  }
  getConflictedFiles() {
    try {
      const conflicts = execSync("git diff --name-only --diff-filter=U", {
        encoding: "utf8"
      });
      return conflicts.trim().split("\n").filter((f) => f.length > 0);
    } catch {
      return [];
    }
  }
  isAgentFile(file, agent) {
    if (!file || !agent?.role || !agent?.id) {
      return false;
    }
    return file.includes(agent.role) || file.includes(agent.id);
  }
  generateCommitMessage(agent, task) {
    const role = agent?.role || "agent";
    const title = task?.title || "task";
    const iteration = agent?.performance?.tasksCompleted || 1;
    return `[${role}] ${title} - Iteration ${iteration}`;
  }
  scheduleAutoCommit(agent, task) {
    const intervalMs = this.config.commitFrequency * 60 * 1e3;
    setInterval(async () => {
      await this.commitAgentWork(
        agent,
        task,
        `[${agent.role}] Auto-commit: ${task.title}`
      );
    }, intervalMs);
  }
  async createPullRequest(agent, task, branchName) {
    try {
      const title = `[Swarm ${agent.role}] ${task.title}`;
      const body = `
## Agent: ${agent.role}
## Task: ${task.title}

### Acceptance Criteria:
${task.acceptanceCriteria.map((c) => `- ${c}`).join("\n")}

### Status:
- Tasks Completed: ${agent.performance?.tasksCompleted || 0}
- Success Rate: ${agent.performance?.successRate || 0}%

Generated by Swarm Coordinator
      `;
      execSync(
        `gh pr create --title "${title}" --body "${body}" --base ${this.baselineBranch}`,
        {
          encoding: "utf8"
        }
      );
      logger.info(`Created PR for agent ${agent.role}`);
    } catch (error) {
      logger.warn(`Could not create PR: ${error}`);
    }
  }
  async runIntegrationTests() {
    try {
      execSync("npm test", { encoding: "utf8" });
      return true;
    } catch {
      return false;
    }
  }
  branchHasUnmergedChanges(branchName) {
    try {
      const currentBranch = this.getCurrentBranch();
      const unmerged = execSync(
        `git log ${currentBranch}..${branchName} --oneline`,
        { encoding: "utf8", stdio: "pipe" }
      );
      return unmerged.trim().length > 0;
    } catch {
      return true;
    }
  }
  /**
   * Get status of all agent branches
   */
  getGitStatus() {
    const status = {
      enabled: this.config.enableGitWorkflow,
      currentBranch: this.getCurrentBranch(),
      agentBranches: Array.from(this.agentBranches.entries()).map(
        ([agentId, branch]) => ({
          agentId,
          branch,
          exists: this.branchExists(branch)
        })
      ),
      hasUncommittedChanges: this.hasUncommittedChanges()
    };
    return status;
  }
}
const gitWorkflowManager = new GitWorkflowManager();
export {
  GitWorkflowError,
  GitWorkflowManager,
  gitWorkflowManager
};
//# sourceMappingURL=git-workflow-manager.js.map
