import { execa, execaCommand } from "execa";
import { getWorkshopRoot } from "./apps.server.js";
import { checkConnection, getErrorMessage, getPkgProp } from "./utils.js";
const cwd = getWorkshopRoot();
async function getDiffUrl(commitBefore, commitAfter) {
  try {
    const { stdout: remoteUrl } = await execaCommand(
      "git config --get remote.origin.url",
      { cwd }
    );
    const [, username, repoName] = remoteUrl.match(/(?:[^/]+\/|:)([^/]+)\/([^.]+)\.git/) ?? [];
    const diffUrl = `https://github.com/${username}/${repoName}/compare/${commitBefore}...${commitAfter}`;
    return diffUrl;
  } catch (error) {
    console.error("Failed to get repository info:", getErrorMessage(error));
    return null;
  }
}
async function checkForUpdates() {
  const online = await checkConnection();
  if (!online)
    return { updatesAvailable: false };
  let localCommit;
  let remoteCommit;
  try {
    const currentBranch = (await execaCommand("git rev-parse --abbrev-ref HEAD", { cwd })).stdout.trim();
    localCommit = (await execaCommand("git rev-parse --short HEAD", { cwd })).stdout.trim();
    await execaCommand("git fetch --all", { cwd });
    remoteCommit = (await execaCommand(`git rev-parse --short origin/${currentBranch}`, {
      cwd
    })).stdout.trim();
    const { stdout } = await execa(
      "git",
      ["rev-list", "--count", "--left-right", "HEAD...@{upstream}"],
      { cwd }
    );
    const [, behind = 0] = stdout.trim().split(/\s+/).map(Number);
    const updatesAvailable = behind > 0;
    return {
      updatesAvailable,
      localCommit,
      remoteCommit,
      diffLink: await getDiffUrl(localCommit, remoteCommit)
    };
  } catch (error) {
    console.error("Unable to check for updates", getErrorMessage(error));
    return {
      updatesAvailable: false,
      localCommit,
      remoteCommit,
      diffLink: localCommit && remoteCommit ? await getDiffUrl(localCommit, remoteCommit) : null
    };
  }
}
async function updateLocalRepo() {
  try {
    const updates = await checkForUpdates();
    if (!updates.updatesAvailable) {
      return { status: "success", message: "No updates available." };
    }
    const uncommittedChanges = (await execaCommand("git status --porcelain", { cwd })).stdout.trim().length > 0;
    if (uncommittedChanges) {
      console.log("\u{1F45C} Stashing uncommitted changes...");
      await execaCommand("git stash", { cwd });
    }
    console.log("\u2B07\uFE0F Pulling latest changes...");
    await execaCommand("git pull origin HEAD", { cwd });
    if (uncommittedChanges) {
      console.log("\u{1F45C} re-applying stashed changes...");
      await execaCommand("git stash pop", { cwd });
    }
    console.log("\u{1F4E6} Re-installing dependencies...");
    await execaCommand("npm install", { cwd, stdio: "inherit" });
    const postUpdateScript = await getPkgProp(
      cwd,
      "kcd-workshop.scripts.postupdate",
      null
    );
    if (postUpdateScript) {
      console.log("\u{1F3C3} Running post update script...");
      await execaCommand(postUpdateScript, { cwd, stdio: "inherit" });
    }
    return { status: "success", message: "Updated successfully." };
  } catch (error) {
    return { status: "error", message: getErrorMessage(error) };
  }
}
export {
  checkForUpdates,
  updateLocalRepo
};
